Merge "Introduce #createWindowContext with display"
diff --git a/Android.bp b/Android.bp
index 9493733..0e40ef7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -349,6 +349,7 @@
         ":framework-telecomm-sources",
         ":framework-telephony-common-sources",
         ":framework-telephony-sources",
+        ":framework-vcn-util-sources",
         ":framework-wifi-annotations",
         ":framework-wifi-non-updatable-sources",
         ":PacProcessor-aidl-sources",
@@ -604,8 +605,9 @@
     ],
     required: [
         "framework-platform-compat-config",
-        // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly.
+        // TODO: remove gps_debug, cec_config.xml and protolog.conf.json when the build system propagates "required" properly.
         "gps_debug.conf",
+        "cec_config.xml",
         "icu4j-platform-compat-config",
         "libcore-platform-compat-config",
         "protolog.conf.json.gz",
@@ -1334,8 +1336,6 @@
     sdk_version: "module_current",
     min_sdk_version: "30",
     srcs: [
-        "core/java/android/content/pm/BaseParceledListSlice.java",
-        "core/java/android/content/pm/ParceledListSlice.java",
         "core/java/android/os/HandlerExecutor.java",
         "core/java/com/android/internal/util/AsyncChannel.java",
         "core/java/com/android/internal/util/AsyncService.java",
@@ -1354,12 +1354,6 @@
     ],
 }
 
-filegroup {
-    name: "framework-wifi-util-lib-aidls",
-    srcs: ["core/java/android/content/pm/ParceledListSlice.aidl"],
-    path: "core/java",
-}
-
 // utility classes statically linked into wifi-service
 filegroup {
     name: "framework-wifi-service-shared-srcs",
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 7ed7ec5..3d6bdbf 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -67,7 +67,7 @@
         ":opt-net-voip-srcs",
         ":art.module.public.api{.public.stubs.source}",
         ":conscrypt.module.public.api{.public.stubs.source}",
-        ":android_icu4j_public_api_files",
+        ":i18n.module.public.api{.public.stubs.source}",
         "test-mock/src/**/*.java",
         "test-runner/src/**/*.java",
     ],
diff --git a/BATTERY_STATS_OWNERS b/BATTERY_STATS_OWNERS
new file mode 100644
index 0000000..7728975
--- /dev/null
+++ b/BATTERY_STATS_OWNERS
@@ -0,0 +1,4 @@
+# OWNERS of BatteryStats related files
+bookatz@google.com
+dplotnikov@google.com
+mwachens@google.com
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..4160122
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,31 @@
+# This top-level list should remain narrowly defined as team leads; individual
+# teams are strongly encouraged to define narrower OWNERS files at deeper
+# levels within the source tree; see OWNERS.md for more details
+akulian@google.com
+dsandler@android.com
+dsandler@google.com
+hackbod@android.com
+hackbod@google.com
+jjaggi@google.com
+jsharkey@android.com
+jsharkey@google.com
+michaelwr@google.com
+nandana@google.com
+narayan@google.com
+ogunwale@google.com
+roosa@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+yamasani@google.com
+
+# API changes are already covered by API-Review+1 (http://mdb/android-api-council)
+# via https://android.git.corp.google.com/All-Projects/+/refs/meta/config/rules.pl.
+per-file */api/*current.txt = *
+
+# Support bulk translation updates
+per-file */res*/values*/*.xml = byi@google.com, delphij@google.com
+
+per-file Android.bp = file:platform/build/soong:/OWNERS
+per-file Android.mk = file:platform/build/soong:/OWNERS
+per-file ApiDocs.bp = file:platform/build/soong:/OWNERS
+per-file StubLibraries.bp = file:platform/build/soong:/OWNERS
diff --git a/OWNERS.md b/OWNERS.md
new file mode 100644
index 0000000..601b5c64
--- /dev/null
+++ b/OWNERS.md
@@ -0,0 +1,68 @@
+# Background
+
+As general background, `OWNERS` files expedite code reviews by helping code
+authors quickly find relevant reviewers, and they also ensure that stakeholders
+are involved in code changes in their areas.
+
+The structure of `frameworks/base/` is unique among Android repositories, and
+it's evolved into a complex interleaved structure over the years.  Because of
+this structure, the best place to authoritatively define `OWNERS` can vary
+wildly, but here are some common patterns:
+
+* `core/java/` contains source that is included in the base classpath, and as
+such it's where most APIs are defined:
+  * `core/java/android/app/`
+  * `core/java/android/content/`
+* `services/core/` contains most system services, and these directories
+typically have more granularity than `core/java/`, since they can be refactored
+without API changes:
+  * `services/core/java/com/android/server/net/`
+  * `services/core/java/com/android/server/wm/`
+* `services/` contains several system services that have been isolated from the
+main `services/core/` project:
+  * `services/appwidget/`
+  * `services/midi/`
+* `apex/` contains Mainline modules:
+  * `apex/jobscheduler/`
+  * `apex/permission/`
+* Finally, some teams may have dedicated top-level directories:
+  * `media/`
+  * `wifi/`
+
+# Design
+
+Area maintainers are strongly encouraged to list people in a single
+authoritative `OWNERS` file in **exactly one** location.  Then, other paths
+should reference that single authoritative `OWNERS` file using an include
+directive.  This approach ensures that updates are applied consistently across
+the tree, reducing maintenance burden.
+
+# Examples
+
+The exact syntax of `OWNERS` files can be difficult to get correct, so here are
+some common examples:
+
+```
+# Complete include of top-level owners from this repo
+include /ZYGOTE_OWNERS
+# Partial include of top-level owners from this repo
+per-file ZygoteFile.java = file:/ZYGOTE_OWNERS
+```
+```
+# Complete include of subdirectory owners from this repo
+include /services/core/java/com/android/server/net/OWNERS
+# Partial include of subdirectory owners from this repo
+per-file NetworkFile.java = file:/services/core/java/com/android/server/net/OWNERS
+```
+```
+# Complete include of top-level owners from another repo
+include platform/libcore:/OWNERS
+# Partial include of top-level owners from another repo
+per-file LibcoreFile.java = file:platform/libcore:/OWNERS
+```
+```
+# Complete include of subdirectory owners from another repo
+include platform/frameworks/av:/camera/OWNERS
+# Partial include of subdirectory owners from another repo
+per-file CameraFile.java = file:platform/frameworks/av:/camera/OWNERS
+```
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 380839e..12ee889 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -48,7 +48,6 @@
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
         ":art.module.public.api{.public.stubs.source}",
-        ":android_icu4j_public_api_files",
         "**/package.html",
     ],
     sdk_version: "core_platform",
@@ -251,6 +250,7 @@
         "framework-statsd.stubs",
         "framework-tethering.stubs",
         "framework-wifi.stubs",
+        "i18n.module.public.api.stubs",
         "private-stub-annotations-jar",
     ],
     defaults: ["android_defaults_stubs_current"],
@@ -270,6 +270,7 @@
         "framework-statsd.stubs.system",
         "framework-tethering.stubs.system",
         "framework-wifi.stubs.system",
+        "i18n.module.public.api.stubs",
         "private-stub-annotations-jar",
     ],
     defaults: [
@@ -305,6 +306,7 @@
         "framework-statsd.stubs.system",
         "framework-tethering.stubs.system",
         "framework-wifi.stubs.system",
+        "i18n.module.public.api.stubs",
         "private-stub-annotations-jar",
     ],
     defaults: [
diff --git a/ZYGOTE_OWNERS b/ZYGOTE_OWNERS
new file mode 100644
index 0000000..90a185b
--- /dev/null
+++ b/ZYGOTE_OWNERS
@@ -0,0 +1,5 @@
+calin@google.com
+chriswailes@google.com
+maco@google.com
+narayan@google.com
+ngeoffray@google.com
diff --git a/apct-tests/perftests/OWNERS b/apct-tests/perftests/OWNERS
new file mode 100644
index 0000000..a060ad9
--- /dev/null
+++ b/apct-tests/perftests/OWNERS
@@ -0,0 +1,2 @@
+timmurray@google.com
+philipcuadra@google.com
diff --git a/apct-tests/perftests/autofill/OWNERS b/apct-tests/perftests/autofill/OWNERS
new file mode 100644
index 0000000..c52751d
--- /dev/null
+++ b/apct-tests/perftests/autofill/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/autofill/OWNERS
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp
index be5072c..be700a2 100644
--- a/apct-tests/perftests/blobstore/Android.bp
+++ b/apct-tests/perftests/blobstore/Android.bp
@@ -21,6 +21,7 @@
     "androidx.annotation_annotation",
     "apct-perftests-utils",
     "ub-uiautomator",
+    "collector-device-lib-platform",
   ],
   platform_apis: true,
   test_suites: ["device-tests"],
diff --git a/apct-tests/perftests/blobstore/AndroidTest.xml b/apct-tests/perftests/blobstore/AndroidTest.xml
index 19456c6..58761d0 100644
--- a/apct-tests/perftests/blobstore/AndroidTest.xml
+++ b/apct-tests/perftests/blobstore/AndroidTest.xml
@@ -24,5 +24,22 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.perftests.blob" />
         <option name="hidden-api-checks" value="false"/>
+
+        <!-- TODO: Add PerfettoListener to automatically capture perfetto traces for each test-->
+        <!-- Listener related args for collecting the traces and waiting for the device
+             to stabilize. -->
+        <option name="device-listeners"
+                value="android.device.collectors.ProcLoadListener" />
+        <!-- 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" />
     </test>
 </configuration>
\ No newline at end of file
diff --git a/apct-tests/perftests/blobstore/OWNERS b/apct-tests/perftests/blobstore/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/apct-tests/perftests/blobstore/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
diff --git a/apct-tests/perftests/contentcapture/OWNERS b/apct-tests/perftests/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/apct-tests/perftests/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/apct-tests/perftests/core/apps/overlay/OWNERS b/apct-tests/perftests/core/apps/overlay/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/apct-tests/perftests/core/apps/overlay/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/apct-tests/perftests/core/src/android/accounts/OWNERS b/apct-tests/perftests/core/src/android/accounts/OWNERS
new file mode 100644
index 0000000..df1b4f4
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/accounts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/accounts/OWNERS
diff --git a/apct-tests/perftests/core/src/android/database/OWNERS b/apct-tests/perftests/core/src/android/database/OWNERS
new file mode 100644
index 0000000..bb9a2ca
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/database/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/database/OWNERS
diff --git a/apct-tests/perftests/inputmethod/OWNERS b/apct-tests/perftests/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/apct-tests/perftests/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
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/apct-tests/perftests/packagemanager/OWNERS b/apct-tests/perftests/packagemanager/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/apct-tests/perftests/textclassifier/OWNERS b/apct-tests/perftests/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/apct-tests/perftests/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/apct-tests/perftests/windowmanager/OWNERS b/apct-tests/perftests/windowmanager/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/apct-tests/perftests/windowmanager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
index 2aea61f..98b5938 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
@@ -24,8 +24,8 @@
 import static org.hamcrest.core.Is.is;
 
 import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityTaskManager;
+import android.window.TaskSnapshot;
 import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
diff --git a/apex/Android.bp b/apex/Android.bp
index 4e80acb..77ff6db 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_visibility: [":__subpackages__"],
+}
+
 mainline_stubs_args =
     "--error UnhiddenSystemApi " +
     "--hide BroadcastBehavior " +
@@ -136,6 +140,13 @@
         enabled: true,
         sdk_version: "module_current",
     },
+    defaults_visibility: [
+        ":__subpackages__",
+        "//frameworks/base/libs/hwui",
+        "//frameworks/base/wifi",
+        "//packages/modules:__subpackages__",
+        "//packages/providers/MediaProvider:__subpackages__",
+    ],
 }
 
 // Defaults for mainline module system server provided java_sdk_library instances.
@@ -147,6 +158,10 @@
         enabled: true,
         sdk_version: "module_current",
     },
+    defaults_visibility: [
+        ":__subpackages__",
+        "//packages/modules:__subpackages__",
+    ],
 }
 
 stubs_defaults {
diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS
new file mode 100644
index 0000000..1703369
--- /dev/null
+++ b/apex/appsearch/OWNERS
@@ -0,0 +1,3 @@
+adorokhine@google.com
+sudheersai@google.com
+yamasani@google.com
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 12afde4..b3eb911 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -19,6 +19,7 @@
         "java/**/*.aidl",
     ],
     path: "java",
+    visibility: ["//frameworks/base"],
 }
 
 java_sdk_library {
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/Android.bp b/apex/appsearch/service/Android.bp
index fc1d707..2fd5c73 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -28,5 +28,11 @@
         "libicing",
     ],
     jarjar_rules: "jarjar-rules.txt",
+    visibility: [
+        "//frameworks/base/apex/appsearch:__subpackages__",
+        // These are required until appsearch is properly unbundled.
+        "//frameworks/base/services/tests/mockingservicestests",
+        "//frameworks/base/services/tests/servicestests",
+    ],
     apex_available: ["com.android.appsearch"],
 }
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/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp
new file mode 100644
index 0000000..54d5039
--- /dev/null
+++ b/apex/appsearch/testing/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+java_library {
+    name: "AppSearchTestUtils",
+    srcs: ["java/**/*.java"],
+    libs: [
+        "androidx.test.ext.junit",
+        "framework",
+        "framework-appsearch",
+        "guava",
+        "truth-prebuilt",
+    ],
+    visibility: ["//cts/tests/appsearch"],
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java
new file mode 100644
index 0000000..b1e760a
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java
@@ -0,0 +1,145 @@
+/*
+ * 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 com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSession;
+import android.app.appsearch.BatchResultCallback;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByUriRequest;
+import android.app.appsearch.PutDocumentsRequest;
+import android.app.appsearch.RemoveByUriRequest;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.app.appsearch.SetSchemaRequest;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class AppSearchSessionShim {
+    private final AppSearchSession mAppSearchSession;
+    private final ExecutorService mExecutor;
+
+    @NonNull
+    public static ListenableFuture<AppSearchResult<AppSearchSessionShim>> createSearchSession(
+            @NonNull AppSearchManager.SearchContext searchContext) {
+        Context context = ApplicationProvider.getApplicationContext();
+        AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+        SettableFuture<AppSearchResult<AppSearchSession>> future = SettableFuture.create();
+        ExecutorService executor = Executors.newCachedThreadPool();
+        appSearchManager.createSearchSession(searchContext, executor, future::set);
+        return Futures.transform(future, (instance) -> {
+            if (!instance.isSuccess()) {
+                return AppSearchResult.newFailedResult(
+                        instance.getResultCode(), instance.getErrorMessage());
+            }
+            AppSearchSession searchSession = instance.getResultValue();
+            AppSearchSessionShim shim = new AppSearchSessionShim(searchSession, executor);
+            return AppSearchResult.newSuccessfulResult(shim);
+        }, executor);
+    }
+
+    private AppSearchSessionShim(
+            @NonNull AppSearchSession session, @NonNull ExecutorService executor) {
+        mAppSearchSession = Preconditions.checkNotNull(session);
+        mExecutor = Preconditions.checkNotNull(executor);
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchResult<Void>> setSchema(@NonNull SetSchemaRequest request) {
+        SettableFuture<AppSearchResult<Void>> future = SettableFuture.create();
+        mAppSearchSession.setSchema(request, mExecutor, future::set);
+        return future;
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchBatchResult<String, Void>> putDocuments(
+            @NonNull PutDocumentsRequest request) {
+        SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create();
+        mAppSearchSession.putDocuments(
+                request, mExecutor, new BatchResultCallbackAdapter<>(future));
+        return future;
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByUri(
+            @NonNull GetByUriRequest request) {
+        SettableFuture<AppSearchBatchResult<String, GenericDocument>> future =
+                SettableFuture.create();
+        mAppSearchSession.getByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future));
+        return future;
+    }
+
+    @NonNull
+    public SearchResultsShim query(
+            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+        SearchResults searchResults =
+                mAppSearchSession.query(queryExpression, searchSpec, mExecutor);
+        return new SearchResultsShim(searchResults);
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchBatchResult<String, Void>> removeByUri(
+            @NonNull RemoveByUriRequest request) {
+        SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create();
+        mAppSearchSession.removeByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future));
+        return future;
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchResult<Void>> removeByQuery(
+            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+        SettableFuture<AppSearchResult<Void>> future = SettableFuture.create();
+        mAppSearchSession.removeByQuery(queryExpression, searchSpec, mExecutor, future::set);
+        return future;
+    }
+
+    private static final class BatchResultCallbackAdapter<K, V>
+            implements BatchResultCallback<K, V> {
+        private final SettableFuture<AppSearchBatchResult<K, V>> mFuture;
+
+        BatchResultCallbackAdapter(SettableFuture<AppSearchBatchResult<K, V>> future) {
+            mFuture = future;
+        }
+
+        @Override
+        public void onResult(AppSearchBatchResult<K, V> result) {
+            mFuture.set(result);
+        }
+
+        @Override
+        public void onSystemError(Throwable t) {
+            mFuture.setException(t);
+        }
+    }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java
new file mode 100644
index 0000000..5146426
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java
@@ -0,0 +1,78 @@
+/*
+ * 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 com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GlobalSearchSession;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class GlobalSearchSessionShim {
+    private final GlobalSearchSession mGlobalSearchSession;
+    private final ExecutorService mExecutor;
+
+    @NonNull
+    public static ListenableFuture<AppSearchResult<GlobalSearchSessionShim>>
+            createGlobalSearchSession() {
+        Context context = ApplicationProvider.getApplicationContext();
+        AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+        SettableFuture<AppSearchResult<GlobalSearchSession>> future = SettableFuture.create();
+        ExecutorService executor = Executors.newCachedThreadPool();
+        appSearchManager.createGlobalSearchSession(executor, future::set);
+        return Futures.transform(future, (instance) -> {
+            if (!instance.isSuccess()) {
+                return AppSearchResult.newFailedResult(
+                        instance.getResultCode(), instance.getErrorMessage());
+            }
+            GlobalSearchSession searchSession = instance.getResultValue();
+            GlobalSearchSessionShim shim = new GlobalSearchSessionShim(searchSession, executor);
+            return AppSearchResult.newSuccessfulResult(shim);
+        }, executor);
+    }
+
+    private GlobalSearchSessionShim(
+            @NonNull GlobalSearchSession session, @NonNull ExecutorService executor) {
+        mGlobalSearchSession = Preconditions.checkNotNull(session);
+        mExecutor = Preconditions.checkNotNull(executor);
+    }
+
+    @NonNull
+    public SearchResultsShim query(
+            @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+        SearchResults searchResults =
+                mGlobalSearchSession.query(queryExpression, searchSpec, mExecutor);
+        return new SearchResultsShim(searchResults);
+    }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java
new file mode 100644
index 0000000..cf43401
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java
@@ -0,0 +1,54 @@
+/*
+ * 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 com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchResults;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.io.Closeable;
+import java.util.List;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class SearchResultsShim implements Closeable {
+    private final SearchResults mSearchResults;
+
+    SearchResultsShim(@NonNull SearchResults searchResults) {
+        mSearchResults = Preconditions.checkNotNull(searchResults);
+    }
+
+    @NonNull
+    public ListenableFuture<AppSearchResult<List<SearchResult>>> getNextPage() {
+        SettableFuture<AppSearchResult<List<SearchResult>>> future = SettableFuture.create();
+        mSearchResults.getNextPage(future::set);
+        return future;
+    }
+
+    @Override
+    public void close() {
+        mSearchResults.close();
+    }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java
new file mode 100644
index 0000000..907509c
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.android.server.appsearch.testing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByUriRequest;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SetSchemaRequest;
+import android.content.Context;
+
+import com.google.common.collect.ImmutableList;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class AppSearchTestUtils {
+
+    // List of databases that may be used in tests. Keeping them in a centralized location helps
+    // #cleanup know which databases to clear.
+    public static final String DEFAULT_DATABASE = AppSearchManager.DEFAULT_DATABASE_NAME;
+    public static final String DB_1 = "testDb1";
+    public static final String DB_2 = "testDb2";
+
+    public static void cleanup(Context context) throws Exception {
+        List<String> databases = ImmutableList.of(DEFAULT_DATABASE, DB_1, DB_2);
+        for (String database : databases) {
+            AppSearchSessionShim session = checkIsResultSuccess(
+                    AppSearchSessionShim.createSearchSession(
+                            new AppSearchManager.SearchContext.Builder()
+                                    .setDatabaseName(database).build()));
+            checkIsResultSuccess(session.setSchema(
+                    new SetSchemaRequest.Builder().setForceOverride(true).build()));
+        }
+    }
+
+    public static <V> V checkIsResultSuccess(Future<AppSearchResult<V>> future) throws Exception {
+        AppSearchResult<V> result = future.get();
+        if (!result.isSuccess()) {
+            throw new AssertionFailedError("AppSearchResult not successful: " + result);
+        }
+        return result.getResultValue();
+    }
+
+    public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess(
+            Future<AppSearchBatchResult<K, V>> future) throws Exception {
+        AppSearchBatchResult<K, V> result = future.get();
+        if (!result.isSuccess()) {
+            throw new AssertionFailedError("AppSearchBatchResult not successful: " + result);
+        }
+        return result;
+    }
+
+    public static List<GenericDocument> doGet(
+            AppSearchSessionShim session, String namespace, String... uris) throws Exception {
+        AppSearchBatchResult<String, GenericDocument> result = checkIsBatchResultSuccess(
+                session.getByUri(
+                        new GetByUriRequest.Builder()
+                                .setNamespace(namespace).addUri(uris).build()));
+        assertThat(result.getSuccesses()).hasSize(uris.length);
+        assertThat(result.getFailures()).isEmpty();
+        List<GenericDocument> list = new ArrayList<>(uris.length);
+        for (String uri : uris) {
+            list.add(result.getSuccesses().get(uri));
+        }
+        return list;
+    }
+
+    public static List<GenericDocument> convertSearchResultsToDocuments(
+            SearchResultsShim searchResults) throws Exception {
+        List<SearchResult> results = checkIsResultSuccess(searchResults.getNextPage());
+        List<GenericDocument> documents = new ArrayList<>();
+        while (results.size() > 0) {
+            for (SearchResult result : results) {
+                documents.add(result.getDocument());
+            }
+            results = checkIsResultSuccess(searchResults.getNextPage());
+        }
+        return documents;
+    }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java
new file mode 100644
index 0000000..5c919b4
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * @hide
+ */
+package com.android.server.appsearch.testing;
diff --git a/apex/blobstore/OWNERS b/apex/blobstore/OWNERS
index 8e04399..a53bbea 100644
--- a/apex/blobstore/OWNERS
+++ b/apex/blobstore/OWNERS
@@ -1,4 +1,2 @@
-set noparent
-
 sudheersai@google.com
 yamasani@google.com
diff --git a/apex/blobstore/framework/Android.bp b/apex/blobstore/framework/Android.bp
index 2469351..3499553 100644
--- a/apex/blobstore/framework/Android.bp
+++ b/apex/blobstore/framework/Android.bp
@@ -19,6 +19,7 @@
         "java/**/*.aidl"
     ],
     path: "java",
+    visibility: ["//frameworks/base"],
 }
 
 java_library {
diff --git a/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp
index 22b0cbe..f6cbac1 100644
--- a/apex/blobstore/service/Android.bp
+++ b/apex/blobstore/service/Android.bp
@@ -25,4 +25,9 @@
         "services.core",
         "services.usage",
     ],
+    visibility: [
+        // These are required until blobstore is properly unbundled.
+        "//frameworks/base/services",
+        "//frameworks/base/services/tests/mockingservicestests",
+    ],
 }
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index d004eed..c77ea33 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -1,6 +1,7 @@
-yamasani@google.com
-omakoto@google.com
 ctate@android.com
 ctate@google.com
+dplotnikov@google.com
 kwekua@google.com
-suprabh@google.com
\ No newline at end of file
+omakoto@google.com
+suprabh@google.com
+yamasani@google.com
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index dab295b..6650e67 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -5,6 +5,7 @@
         "java/**/*.aidl",
     ],
     path: "java",
+    visibility: ["//frameworks/base"],
 }
 
 java_library {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index d16217d..6eb44a7 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -281,11 +281,11 @@
     public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3;
 
     /**
-     * Whether it's a so-called "HPJ" or not.
+     * Whether it's an expedited job or not.
      *
      * @hide
      */
-    public static final int FLAG_FOREGROUND_JOB = 1 << 4;
+    public static final int FLAG_EXPEDITED = 1 << 4;
 
     /**
      * @hide
@@ -586,10 +586,19 @@
     }
 
     /**
-     * @see JobInfo.Builder#setForeground(boolean)
+     * @see JobInfo.Builder#setExpedited(boolean)
      */
+    public boolean isExpedited() {
+        return (flags & FLAG_EXPEDITED) != 0;
+    }
+
+    /**
+     * @see JobInfo.Builder#setExpedited(boolean)
+     * @deprecated Use {@link #isExpedited()} instead
+     */
+    @Deprecated
     public boolean isForegroundJob() {
-        return (flags & FLAG_FOREGROUND_JOB) != 0;
+        return (flags & FLAG_EXPEDITED) != 0;
     }
 
     /**
@@ -1458,35 +1467,51 @@
 
         /**
          * Setting this to true indicates that this job is important and needs to run as soon as
-         * possible with stronger guarantees than regular jobs. These "foreground" jobs will:
+         * possible with stronger guarantees than regular jobs. These "expedited" jobs will:
          * <ol>
          *     <li>Run as soon as possible</li>
          *     <li>Be exempted from Doze and battery saver restrictions</li>
          *     <li>Have network access</li>
+         *     <li>Less likely to be killed than regular jobs</li>
          * </ol>
          *
          * Since these jobs have stronger guarantees than regular jobs, they will be subject to
-         * stricter quotas. As long as an app has available foreground quota, jobs scheduled with
+         * stricter quotas. As long as an app has available expedited quota, jobs scheduled with
          * this set to true will run with these guarantees. If an app has run out of available
-         * foreground quota, any pending foreground jobs will run as regular jobs.
-         * {@link JobParameters#isForegroundJob()} can be used to know whether the executing job
-         * has foreground guarantees or not. In addition, {@link JobScheduler#schedule(JobInfo)}
+         * expedited quota, any pending expedited jobs will run as regular jobs.
+         * {@link JobParameters#isExpeditedJob()} can be used to know whether the executing job
+         * has expedited guarantees or not. In addition, {@link JobScheduler#schedule(JobInfo)}
          * will immediately return {@link JobScheduler#RESULT_FAILURE} if the app does not have
          * available quota (and the job will not be successfully scheduled).
          *
-         * Foreground jobs may only set network constraints. No other constraints are allowed.
+         * Expedited jobs may only set network, storage-not-low, and persistence constraints.
+         * No other constraints are allowed.
          *
-         * Note: Even though foreground jobs are meant to run as soon as possible, they may be
-         * deferred if the system is under heavy load or the network constraint is satisfied
+         * Note: Even though expedited jobs are meant to run as soon as possible, they may be
+         * deferred if the system is under heavy load or requested constraints are not satisfied.
          *
-         * @see JobInfo#isForegroundJob()
+         * @see JobInfo#isExpedited()
          */
         @NonNull
+        public Builder setExpedited(boolean expedited) {
+            if (expedited) {
+                mFlags |= FLAG_EXPEDITED;
+            } else {
+                mFlags &= (~FLAG_EXPEDITED);
+            }
+            return this;
+        }
+
+        /**
+         * @deprecated Use {@link #setExpedited(boolean)} instead.
+         */
+        @Deprecated
+        @NonNull
         public Builder setForeground(boolean foreground) {
             if (foreground) {
-                mFlags |= FLAG_FOREGROUND_JOB;
+                mFlags |= FLAG_EXPEDITED;
             } else {
-                mFlags &= (~FLAG_FOREGROUND_JOB);
+                mFlags &= (~FLAG_EXPEDITED);
             }
             return this;
         }
@@ -1506,7 +1531,7 @@
          * @param importantWhileForeground whether to relax doze restrictions for this job when the
          *                                 app is in the foreground. False by default.
          * @see JobInfo#isImportantWhileForeground()
-         * @deprecated Use {@link #setForeground(boolean)} instead.
+         * @deprecated Use {@link #setExpedited(boolean)} instead.
          */
         @Deprecated
         public Builder setImportantWhileForeground(boolean importantWhileForeground) {
@@ -1633,26 +1658,24 @@
                     "An important while foreground job cannot have a time delay");
         }
 
-        if ((flags & FLAG_FOREGROUND_JOB) != 0) {
+        if ((flags & FLAG_EXPEDITED) != 0) {
             if (hasEarlyConstraint) {
-                throw new IllegalArgumentException("A foreground job cannot have a time delay");
+                throw new IllegalArgumentException("An expedited job cannot have a time delay");
             }
             if (hasLateConstraint) {
-                throw new IllegalArgumentException("A foreground job cannot have a deadline");
+                throw new IllegalArgumentException("An expedited job cannot have a deadline");
             }
             if (isPeriodic) {
-                throw new IllegalArgumentException("A foreground job cannot be periodic");
+                throw new IllegalArgumentException("An expedited job cannot be periodic");
             }
-            if (isPersisted) {
-                throw new IllegalArgumentException("A foreground job cannot be persisted");
-            }
-            if (constraintFlags != 0 || (flags & ~FLAG_FOREGROUND_JOB) != 0) {
+            if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0
+                    || (flags & ~FLAG_EXPEDITED) != 0) {
                 throw new IllegalArgumentException(
-                        "A foreground job can only have network constraints");
+                        "An expedited job can only have network and storage-not-low constraints");
             }
             if (triggerContentUris != null && triggerContentUris.length > 0) {
                 throw new IllegalArgumentException(
-                        "Can't call addTriggerContentUri() on a foreground job");
+                        "Can't call addTriggerContentUri() on an expedited job");
             }
         }
     }
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index a71b856..0d3e001 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -111,9 +111,7 @@
     @UnsupportedAppUsage
     private final IBinder callback;
     private final boolean overrideDeadlineExpired;
-    // HPJs = foreground jobs.
-    // TODO(171305774): clean up naming
-    private final boolean mIsHpj;
+    private final boolean mIsExpedited;
     private final Uri[] mTriggeredContentUris;
     private final String[] mTriggeredContentAuthorities;
     private final Network network;
@@ -124,7 +122,7 @@
     /** @hide */
     public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
             Bundle transientExtras, ClipData clipData, int clipGrantFlags,
-            boolean overrideDeadlineExpired, boolean isHpj, Uri[] triggeredContentUris,
+            boolean overrideDeadlineExpired, boolean isExpedited, Uri[] triggeredContentUris,
             String[] triggeredContentAuthorities, Network network) {
         this.jobId = jobId;
         this.extras = extras;
@@ -133,7 +131,7 @@
         this.clipGrantFlags = clipGrantFlags;
         this.callback = callback;
         this.overrideDeadlineExpired = overrideDeadlineExpired;
-        this.mIsHpj = isHpj;
+        this.mIsExpedited = isExpedited;
         this.mTriggeredContentUris = triggeredContentUris;
         this.mTriggeredContentAuthorities = triggeredContentAuthorities;
         this.network = network;
@@ -199,14 +197,24 @@
     }
 
     /**
-     * @return Whether this job is running as a foreground job or not. A job is guaranteed to have
-     * all foreground job guarantees for the duration of the job execution if this returns
+     * @return Whether this job is running as an expedited job or not. A job is guaranteed to have
+     * all expedited job guarantees for the duration of the job execution if this returns
      * {@code true}. This will return {@code false} if the job that wasn't requested to run as a
-     * foreground job, or if it was requested to run as a foreground job but the app didn't have
-     * any remaining foreground job quota at the time of execution.
+     * expedited job, or if it was requested to run as an expedited job but the app didn't have
+     * any remaining expedited job quota at the time of execution.
+     *
+     * @see JobInfo.Builder#setExpedited(boolean)
      */
+    public boolean isExpeditedJob() {
+        return mIsExpedited;
+    }
+
+    /**
+     * @deprecated Use {@link #isExpeditedJob()} instead.
+     */
+    @Deprecated
     public boolean isForegroundJob() {
-        return mIsHpj;
+        return mIsExpedited;
     }
 
     /**
@@ -352,7 +360,7 @@
         }
         callback = in.readStrongBinder();
         overrideDeadlineExpired = in.readInt() == 1;
-        mIsHpj = in.readBoolean();
+        mIsExpedited = in.readBoolean();
         mTriggeredContentUris = in.createTypedArray(Uri.CREATOR);
         mTriggeredContentAuthorities = in.createStringArray();
         if (in.readInt() != 0) {
@@ -389,7 +397,7 @@
         }
         dest.writeStrongBinder(callback);
         dest.writeInt(overrideDeadlineExpired ? 1 : 0);
-        dest.writeBoolean(mIsHpj);
+        dest.writeBoolean(mIsExpedited);
         dest.writeTypedArray(mTriggeredContentUris, flags);
         dest.writeStringArray(mTriggeredContentAuthorities);
         if (network != null) {
diff --git a/apex/jobscheduler/framework/java/android/app/job/OWNERS b/apex/jobscheduler/framework/java/android/app/job/OWNERS
new file mode 100644
index 0000000..b4a45f5
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 330738
+
+yamasani@google.com
+omakoto@google.com
+ctate@android.com
+ctate@google.com
+kwekua@google.com
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index 8aa88c2..35bd317 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -23,4 +23,12 @@
     required: [
         "libalarm_jni",
     ],
+    visibility: [
+        "//frameworks/base/apex/jobscheduler:__subpackages__",
+        // These are required until jobscheduler is properly unbundled.
+        "//frameworks/base/services",
+        "//frameworks/base/services/tests/mockingservicestests",
+        "//frameworks/base/services/tests/servicestests",
+        "//frameworks/base/tests/JobSchedulerPerfTests",
+    ],
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index 0feaade..dba1d4b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -207,7 +207,7 @@
     private boolean isFgJob(JobStatus job) {
         // (It's super confusing PRIORITY_BOUND_FOREGROUND_SERVICE isn't FG here)
         return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP
-                || job.shouldTreatAsForegroundJob();
+                || job.shouldTreatAsExpeditedJob();
     }
 
     @GuardedBy("mLock")
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 9ea402c..1910553 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -835,9 +835,10 @@
             return o2.overrideState - o1.overrideState;
         }
         if (o1.getSourceUid() == o2.getSourceUid()) {
-            final boolean o1FGJ = o1.isRequestedForegroundJob();
-            if (o1FGJ != o2.isRequestedForegroundJob()) {
-                // Attempt to run requested HPJs ahead of regular jobs, regardless of HPJ quota.
+            final boolean o1FGJ = o1.isRequestedExpeditedJob();
+            if (o1FGJ != o2.isRequestedExpeditedJob()) {
+                // Attempt to run requested expedited jobs ahead of regular jobs, regardless of
+                // expedited job quota.
                 return o1FGJ ? -1 : 1;
             }
         }
@@ -1143,9 +1144,9 @@
 
             JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
 
-            // Return failure early if HPJ quota used up.
-            if (jobStatus.isRequestedForegroundJob()
-                    && !mQuotaController.isWithinHpjQuotaLocked(jobStatus)) {
+            // Return failure early if expedited job quota used up.
+            if (jobStatus.isRequestedExpeditedJob()
+                    && !mQuotaController.isWithinEJQuotaLocked(jobStatus)) {
                 return JobScheduler.RESULT_FAILURE;
             }
 
@@ -1897,9 +1898,9 @@
             Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
         }
 
-        // Intentionally not checking HPJ quota here. An app can't find out if it's run out of quota
-        // when it asks JS to reschedule an HPJ. Instead, the rescheduled HPJ will just be demoted
-        // to a regular job if the app has no HPJ quota left.
+        // Intentionally not checking expedited job quota here. An app can't find out if it's run
+        // out of quota when it asks JS to reschedule an expedited job. Instead, the rescheduled
+        // EJ will just be demoted to a regular job if the app has no EJ quota left.
 
         // If the job wants to be rescheduled, we first need to make the next upcoming
         // job so we can transfer any appropriate state over from the previous job when
@@ -2044,7 +2045,6 @@
 
                 }
                 maybeRunPendingJobsLocked();
-                // Don't remove JOB_EXPIRED in case one came along while processing the queue.
             }
         }
     }
@@ -2110,6 +2110,15 @@
      * as many as we can.
      */
     private void queueReadyJobsForExecutionLocked() {
+        // This method will check and capture all ready jobs, so we don't need to keep any messages
+        // in the queue.
+        mHandler.removeMessages(MSG_CHECK_JOB_GREEDY);
+        // MSG_CHECK_JOB is a weaker form of _GREEDY. Since we're checking and queueing all ready
+        // jobs, we don't need to keep any MSG_CHECK_JOB messages in the queue.
+        mHandler.removeMessages(MSG_CHECK_JOB);
+        // This method will capture all expired jobs that are ready, so there's no need to keep
+        // the _EXPIRED messages in the queue.
+        mHandler.removeMessages(MSG_JOB_EXPIRED);
         if (DEBUG) {
             Slog.d(TAG, "queuing all ready jobs for execution:");
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 5fed199..a9ca730 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -76,10 +76,10 @@
     /** Amount of time a job is allowed to execute for before being considered timed-out. */
     public static final long DEFAULT_EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000;  // 10mins.
     /**
-     * Amount of time a RESTRICTED HPJ is allowed to execute for before being considered
+     * Amount of time a RESTRICTED expedited job is allowed to execute for before being considered
      * timed-out.
      */
-    public static final long DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS =
+    public static final long DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS =
             DEFAULT_EXECUTING_TIMESLICE_MILLIS / 2;
     /** Amount of time the JobScheduler waits for the initial service launch+bind. */
     private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000;
@@ -231,7 +231,7 @@
             final JobInfo ji = job.getJob();
             mParams = new JobParameters(mRunningCallback, job.getJobId(), ji.getExtras(),
                     ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(),
-                    isDeadlineExpired, job.shouldTreatAsForegroundJob(),
+                    isDeadlineExpired, job.shouldTreatAsExpeditedJob(),
                     triggeredUris, triggeredAuthorities, job.network);
             mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis();
 
@@ -259,7 +259,7 @@
             boolean binding = false;
             try {
                 final int bindFlags;
-                if (job.shouldTreatAsForegroundJob()) {
+                if (job.shouldTreatAsExpeditedJob()) {
                     // Add BIND_FOREGROUND_SERVICE to make it BFGS. Without it, it'll be
                     // PROCESS_STATE_IMPORTANT_FOREGROUND. Unclear which is better here.
                     // TODO(171305774): The job should run on the little cores. We'll probably need
@@ -865,9 +865,9 @@
         final long timeoutMillis;
         switch (mVerb) {
             case VERB_EXECUTING:
-                timeoutMillis = mRunningJob.shouldTreatAsForegroundJob()
+                timeoutMillis = mRunningJob.shouldTreatAsExpeditedJob()
                         && mRunningJob.getStandbyBucket() == RESTRICTED_INDEX
-                        ? DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS
+                        ? DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS
                         : DEFAULT_EXECUTING_TIMESLICE_MILLIS;
                 break;
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 5ec1b89..cd71247 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -85,7 +85,7 @@
     static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
     static final int CONSTRAINT_DEVICE_NOT_DOZING = 1 << 25; // Implicit constraint
     static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24;      // Implicit constraint
-    static final int CONSTRAINT_WITHIN_HPJ_QUOTA = 1 << 23;  // Implicit constraint
+    static final int CONSTRAINT_WITHIN_EXPEDITED_QUOTA = 1 << 23;    // Implicit constraint
     static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
 
     /**
@@ -363,8 +363,8 @@
     private boolean mReadyDeadlineSatisfied;
 
     /**
-     * The device isn't Dozing or this job will be in the foreground. This implicit constraint must
-     * be satisfied.
+     * The device isn't Dozing or this job is exempt from Dozing (eg. it will be in the foreground
+     * or will run as an expedited job). This implicit constraint must be satisfied.
      */
     private boolean mReadyNotDozing;
 
@@ -377,8 +377,8 @@
     /** The job is within its quota based on its standby bucket. */
     private boolean mReadyWithinQuota;
 
-    /** The job is a foreground job with sufficient quota to run as a foreground job. */
-    private boolean mReadyWithinHpjQuota;
+    /** The job is an expedited job with sufficient quota to run as an expedited job. */
+    private boolean mReadyWithinExpeditedQuota;
 
     /** The job's dynamic requirements have been satisfied. */
     private boolean mReadyDynamicSatisfied;
@@ -1040,17 +1040,17 @@
         mPersistedUtcTimes = null;
     }
 
-    /** @return true if the app has requested that this run as a foreground job. */
-    public boolean isRequestedForegroundJob() {
-        return (getFlags() & JobInfo.FLAG_FOREGROUND_JOB) != 0;
+    /** @return true if the app has requested that this run as an expedited job. */
+    public boolean isRequestedExpeditedJob() {
+        return (getFlags() & JobInfo.FLAG_EXPEDITED) != 0;
     }
 
     /**
-     * @return true if all foreground job requirements are satisfied and therefore this should be
-     * treated as a foreground job.
+     * @return true if all expedited job requirements are satisfied and therefore this should be
+     * treated as an expedited job.
      */
-    public boolean shouldTreatAsForegroundJob() {
-        return mReadyWithinHpjQuota && isRequestedForegroundJob();
+    public boolean shouldTreatAsExpeditedJob() {
+        return mReadyWithinExpeditedQuota && isRequestedExpeditedJob();
     }
 
     /**
@@ -1058,16 +1058,16 @@
      * in Doze.
      */
     public boolean canRunInDoze() {
-        return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0 || shouldTreatAsForegroundJob();
+        return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0 || shouldTreatAsExpeditedJob();
     }
 
     boolean canRunInBatterySaver() {
         return (getInternalFlags() & INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0
-                || shouldTreatAsForegroundJob();
+                || shouldTreatAsExpeditedJob();
     }
 
     boolean shouldIgnoreNetworkBlocking() {
-        return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0 || shouldTreatAsForegroundJob();
+        return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0 || shouldTreatAsExpeditedJob();
     }
 
     /** @return true if the constraint was changed, false otherwise. */
@@ -1147,10 +1147,10 @@
     }
 
     /** @return true if the constraint was changed, false otherwise. */
-    boolean setForegroundJobQuotaConstraintSatisfied(boolean state) {
-        if (setConstraintSatisfied(CONSTRAINT_WITHIN_HPJ_QUOTA, state)) {
+    boolean setExpeditedJobQuotaConstraintSatisfied(boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, state)) {
             // The constraint was changed. Update the ready flag.
-            mReadyWithinHpjQuota = state;
+            mReadyWithinExpeditedQuota = state;
             return true;
         }
         return false;
@@ -1285,9 +1285,9 @@
                 oldValue = mReadyWithinQuota;
                 mReadyWithinQuota = true;
                 break;
-            case CONSTRAINT_WITHIN_HPJ_QUOTA:
-                oldValue = mReadyWithinHpjQuota;
-                mReadyWithinHpjQuota = true;
+            case CONSTRAINT_WITHIN_EXPEDITED_QUOTA:
+                oldValue = mReadyWithinExpeditedQuota;
+                mReadyWithinExpeditedQuota = true;
                 break;
             default:
                 satisfied |= constraint;
@@ -1311,8 +1311,8 @@
             case CONSTRAINT_WITHIN_QUOTA:
                 mReadyWithinQuota = oldValue;
                 break;
-            case CONSTRAINT_WITHIN_HPJ_QUOTA:
-                mReadyWithinHpjQuota = oldValue;
+            case CONSTRAINT_WITHIN_EXPEDITED_QUOTA:
+                mReadyWithinExpeditedQuota = oldValue;
                 break;
             default:
                 mReadyDynamicSatisfied = mDynamicConstraints != 0
@@ -1328,7 +1328,7 @@
         // sessions (exempt from dynamic restrictions), we need the additional check to ensure
         // that NEVER jobs don't run.
         // TODO: cleanup quota and standby bucket management so we don't need the additional checks
-        if ((!mReadyWithinQuota && !mReadyDynamicSatisfied && !shouldTreatAsForegroundJob())
+        if ((!mReadyWithinQuota && !mReadyDynamicSatisfied && !shouldTreatAsExpeditedJob())
                 || getEffectiveStandbyBucket() == NEVER_INDEX) {
             return false;
         }
@@ -1541,8 +1541,8 @@
         if ((constraints & CONSTRAINT_WITHIN_QUOTA) != 0) {
             pw.print(" WITHIN_QUOTA");
         }
-        if ((constraints & CONSTRAINT_WITHIN_HPJ_QUOTA) != 0) {
-            pw.print(" WITHIN_HPJ_QUOTA");
+        if ((constraints & CONSTRAINT_WITHIN_EXPEDITED_QUOTA) != 0) {
+            pw.print(" WITHIN_EXPEDITED_QUOTA");
         }
         if (constraints != 0) {
             pw.print(" [0x");
@@ -1616,8 +1616,8 @@
         if ((constraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
             proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_BACKGROUND_NOT_RESTRICTED);
         }
-        if ((constraints & CONSTRAINT_WITHIN_HPJ_QUOTA) != 0) {
-            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_WITHIN_HPJ_QUOTA);
+        if ((constraints & CONSTRAINT_WITHIN_EXPEDITED_QUOTA) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_WITHIN_EXPEDITED_JOB_QUOTA);
         }
     }
 
@@ -1836,10 +1836,10 @@
         pw.print(prefix);
         pw.print("  readyComponentEnabled: ");
         pw.println(serviceInfo != null);
-        if ((getFlags() & JobInfo.FLAG_FOREGROUND_JOB) != 0) {
+        if ((getFlags() & JobInfo.FLAG_EXPEDITED) != 0) {
             pw.print(prefix);
-            pw.print("  mReadyWithinHpjQuota: ");
-            pw.println(mReadyWithinHpjQuota);
+            pw.print("  mReadyWithinExpeditedQuota: ");
+            pw.println(mReadyWithinExpeditedQuota);
         }
 
         if (changedAuthorities != null) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index a3a20c6..7b87dfb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -301,15 +301,17 @@
     /** Timer for each package-userId combo. */
     private final SparseArrayMap<String, Timer> mPkgTimers = new SparseArrayMap<>();
 
-    /** Timer for HPJs for each package-userId combo. */
-    private final SparseArrayMap<String, Timer> mHpjPkgTimers = new SparseArrayMap<>();
+    /** Timer for expedited jobs for each package-userId combo. */
+    private final SparseArrayMap<String, Timer> mEJPkgTimers = new SparseArrayMap<>();
 
     /** List of all regular timing sessions for a package-userId combo, in chronological order. */
     private final SparseArrayMap<String, List<TimingSession>> mTimingSessions =
             new SparseArrayMap<>();
 
-    /** List of all hpj timing sessions for a package-userId combo, in chronological order. */
-    private final SparseArrayMap<String, List<TimingSession>> mHpjTimingSessions =
+    /**
+     * List of all expedited job timing sessions for a package-userId combo, in chronological order.
+     */
+    private final SparseArrayMap<String, List<TimingSession>> mEJTimingSessions =
             new SparseArrayMap<>();
 
     /**
@@ -322,7 +324,7 @@
     private final SparseArrayMap<String, ExecutionStats[]> mExecutionStatsCache =
             new SparseArrayMap<>();
 
-    private final SparseArrayMap<String, ShrinkableDebits> mHpjStats = new SparseArrayMap<>();
+    private final SparseArrayMap<String, ShrinkableDebits> mEJStats = new SparseArrayMap<>();
 
     private final SparseArrayMap<String, TopAppTimer> mTopAppTrackers = new SparseArrayMap<>();
 
@@ -493,41 +495,41 @@
      * The rolling window size for each standby bucket. Within each window, an app will have 10
      * minutes to run its jobs.
      */
-    private final long[] mHpjLimitsMs = new long[]{
-            QcConstants.DEFAULT_HPJ_LIMIT_ACTIVE_MS,
-            QcConstants.DEFAULT_HPJ_LIMIT_WORKING_MS,
-            QcConstants.DEFAULT_HPJ_LIMIT_FREQUENT_MS,
-            QcConstants.DEFAULT_HPJ_LIMIT_RARE_MS,
+    private final long[] mEJLimitsMs = new long[]{
+            QcConstants.DEFAULT_EJ_LIMIT_ACTIVE_MS,
+            QcConstants.DEFAULT_EJ_LIMIT_WORKING_MS,
+            QcConstants.DEFAULT_EJ_LIMIT_FREQUENT_MS,
+            QcConstants.DEFAULT_EJ_LIMIT_RARE_MS,
             0, // NEVER
-            QcConstants.DEFAULT_HPJ_LIMIT_RESTRICTED_MS
+            QcConstants.DEFAULT_EJ_LIMIT_RESTRICTED_MS
     };
 
     /**
-     * The period of time used to calculate HPJ sessions. Apps can only have HPJ sessions
-     * totalling {@link #mHpjLimitsMs}[bucket within this period of time (without factoring in any
-     * rewards or free HPJs).
+     * The period of time used to calculate expedited job sessions. Apps can only have expedited job
+     * sessions totalling {@link #mEJLimitsMs}[bucket within this period of time (without factoring
+     * in any rewards or free EJs).
      */
-    private long mHpjLimitWindowSizeMs = QcConstants.DEFAULT_HPJ_WINDOW_SIZE_MS;
+    private long mEJLimitWindowSizeMs = QcConstants.DEFAULT_EJ_WINDOW_SIZE_MS;
 
     /**
      * Length of time used to split an app's top time into chunks.
      */
-    public long mHpjTopAppTimeChunkSizeMs = QcConstants.DEFAULT_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS;
+    public long mEJTopAppTimeChunkSizeMs = QcConstants.DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS;
 
     /**
-     * How much HPJ quota to give back to an app based on the number of top app time chunks it had.
+     * How much EJ quota to give back to an app based on the number of top app time chunks it had.
      */
-    public long mHpjRewardTopAppMs = QcConstants.DEFAULT_HPJ_REWARD_TOP_APP_MS;
+    public long mEJRewardTopAppMs = QcConstants.DEFAULT_EJ_REWARD_TOP_APP_MS;
 
     /**
-     * How much HPJ quota to give back to an app based on each non-top user interaction.
+     * How much EJ quota to give back to an app based on each non-top user interaction.
      */
-    public long mHpjRewardInteractionMs = QcConstants.DEFAULT_HPJ_REWARD_INTERACTION_MS;
+    public long mEJRewardInteractionMs = QcConstants.DEFAULT_EJ_REWARD_INTERACTION_MS;
 
     /**
-     * How much HPJ quota to give back to an app based on each notification seen event.
+     * How much EJ quota to give back to an app based on each notification seen event.
      */
-    public long mHpjRewardNotificationSeenMs = QcConstants.DEFAULT_HPJ_REWARD_NOTIFICATION_SEEN_MS;
+    public long mEJRewardNotificationSeenMs = QcConstants.DEFAULT_EJ_REWARD_NOTIFICATION_SEEN_MS;
 
     /** An app has reached its quota. The message should contain a {@link Package} object. */
     @VisibleForTesting
@@ -538,9 +540,12 @@
     private static final int MSG_CHECK_PACKAGE = 2;
     /** Process state for a UID has changed. */
     private static final int MSG_UID_PROCESS_STATE_CHANGED = 3;
-    /** An app has reached its HPJ quota. The message should contain a {@link Package} object. */
+    /**
+     * An app has reached its expedited job quota. The message should contain a {@link Package}
+     * object.
+     */
     @VisibleForTesting
-    static final int MSG_REACHED_HPJ_QUOTA = 4;
+    static final int MSG_REACHED_EJ_QUOTA = 4;
     /**
      * Process a new {@link UsageEvents.Event}. The event will be the message's object and the
      * userId will the first arg.
@@ -588,15 +593,15 @@
         jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
         final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
         setConstraintSatisfied(jobStatus, isWithinQuota);
-        final boolean outOfHpjQuota;
-        if (jobStatus.isRequestedForegroundJob()) {
-            final boolean isWithinHpjQuota = isWithinHpjQuotaLocked(jobStatus);
-            jobStatus.setForegroundJobQuotaConstraintSatisfied(isWithinHpjQuota);
-            outOfHpjQuota = !isWithinHpjQuota;
+        final boolean outOfEJQuota;
+        if (jobStatus.isRequestedExpeditedJob()) {
+            final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
+            jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinEJQuota);
+            outOfEJQuota = !isWithinEJQuota;
         } else {
-            outOfHpjQuota = false;
+            outOfEJQuota = false;
         }
-        if (!isWithinQuota || outOfHpjQuota) {
+        if (!isWithinQuota || outOfEJQuota) {
             maybeScheduleStartAlarmLocked(userId, pkgName, jobStatus.getEffectiveStandbyBucket());
         }
     }
@@ -620,10 +625,10 @@
         final int userId = jobStatus.getSourceUserId();
         final String packageName = jobStatus.getSourcePackageName();
         final SparseArrayMap<String, Timer> timerMap =
-                jobStatus.shouldTreatAsForegroundJob() ? mHpjPkgTimers : mPkgTimers;
+                jobStatus.shouldTreatAsExpeditedJob() ? mEJPkgTimers : mPkgTimers;
         Timer timer = timerMap.get(userId, packageName);
         if (timer == null) {
-            timer = new Timer(uid, userId, packageName, !jobStatus.shouldTreatAsForegroundJob());
+            timer = new Timer(uid, userId, packageName, !jobStatus.shouldTreatAsExpeditedJob());
             timerMap.add(userId, packageName, timer);
         }
         timer.startTrackingJobLocked(jobStatus);
@@ -638,8 +643,8 @@
             if (timer != null) {
                 timer.stopTrackingJob(jobStatus);
             }
-            if (jobStatus.isRequestedForegroundJob()) {
-                timer = mHpjPkgTimers.get(jobStatus.getSourceUserId(),
+            if (jobStatus.isRequestedExpeditedJob()) {
+                timer = mEJPkgTimers.get(jobStatus.getSourceUserId(),
                         jobStatus.getSourcePackageName());
                 if (timer != null) {
                     timer.stopTrackingJob(jobStatus);
@@ -669,12 +674,12 @@
     public void onUserRemovedLocked(int userId) {
         mTrackedJobs.delete(userId);
         mPkgTimers.delete(userId);
-        mHpjPkgTimers.delete(userId);
+        mEJPkgTimers.delete(userId);
         mTimingSessions.delete(userId);
-        mHpjTimingSessions.delete(userId);
+        mEJTimingSessions.delete(userId);
         mInQuotaAlarmListener.removeAlarmsLocked(userId);
         mExecutionStatsCache.delete(userId);
-        mHpjStats.delete(userId);
+        mEJStats.delete(userId);
         mUidToPackageCache.clear();
     }
 
@@ -688,18 +693,18 @@
                 timer.dropEverythingLocked();
             }
         }
-        timer = mHpjPkgTimers.delete(userId, packageName);
+        timer = mEJPkgTimers.delete(userId, packageName);
         if (timer != null) {
             if (timer.isActive()) {
-                Slog.e(TAG, "clearAppStats called before HPJ Timer turned off.");
+                Slog.e(TAG, "clearAppStats called before EJ Timer turned off.");
                 timer.dropEverythingLocked();
             }
         }
         mTimingSessions.delete(userId, packageName);
-        mHpjTimingSessions.delete(userId, packageName);
+        mEJTimingSessions.delete(userId, packageName);
         mInQuotaAlarmListener.removeAlarmLocked(userId, packageName);
         mExecutionStatsCache.delete(userId, packageName);
-        mHpjStats.delete(userId, packageName);
+        mEJStats.delete(userId, packageName);
     }
 
     private boolean isUidInForeground(int uid) {
@@ -724,47 +729,47 @@
                 || isUidInForeground(jobStatus.getSourceUid())) {
             return JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS;
         }
-        if (jobStatus.shouldTreatAsForegroundJob()) {
+        if (jobStatus.shouldTreatAsExpeditedJob()) {
             return jobStatus.getStandbyBucket() == RESTRICTED_INDEX
-                    ? JobServiceContext.DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS
+                    ? JobServiceContext.DEFAULT_RESTRICTED_EXPEDITED_JOB_EXECUTING_TIMESLICE_MILLIS
                     : JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS;
         }
         return getRemainingExecutionTimeLocked(jobStatus);
     }
 
-    /** @return true if the job is within hpj quota. */
-    public boolean isWithinHpjQuotaLocked(@NonNull final JobStatus jobStatus) {
+    /** @return true if the job is within expedited job quota. */
+    public boolean isWithinEJQuotaLocked(@NonNull final JobStatus jobStatus) {
         if (isQuotaFree(jobStatus.getEffectiveStandbyBucket())) {
             return true;
         }
         // A job is within quota if one of the following is true:
-        //   1. it's already running (already executing HPJS should be allowed to finish)
+        //   1. it's already running (already executing expedited jobs should be allowed to finish)
         //   2. the app is currently in the foreground
         //   3. the app overall is within its quota
         if (isTopStartedJobLocked(jobStatus) || isUidInForeground(jobStatus.getSourceUid())) {
             return true;
         }
-        Timer hpjTimer = mHpjPkgTimers.get(jobStatus.getSourceUserId(),
+        Timer ejTimer = mEJPkgTimers.get(jobStatus.getSourceUserId(),
                 jobStatus.getSourcePackageName());
-        // Any already executing HPJs should be allowed to finish.
-        if (hpjTimer != null && hpjTimer.isRunning(jobStatus)) {
+        // Any already executing expedited jbos should be allowed to finish.
+        if (ejTimer != null && ejTimer.isRunning(jobStatus)) {
             return true;
         }
 
-        return 0 < getRemainingHpjExecutionTimeLocked(
+        return 0 < getRemainingEJExecutionTimeLocked(
                 jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
     }
 
     @NonNull
-    private ShrinkableDebits getHpjQuotaLocked(final int userId,
+    private ShrinkableDebits getEJQuotaLocked(final int userId,
             @NonNull final String packageName) {
-        ShrinkableDebits debits = mHpjStats.get(userId, packageName);
+        ShrinkableDebits debits = mEJStats.get(userId, packageName);
         if (debits == null) {
             debits = new ShrinkableDebits(
                     JobSchedulerService.standbyBucketForPackage(
                             packageName, userId, sElapsedRealtimeClock.millis())
             );
-            mHpjStats.add(userId, packageName, debits);
+            mEJStats.add(userId, packageName, debits);
         }
         return debits;
     }
@@ -858,18 +863,18 @@
     }
 
     @VisibleForTesting
-    long getRemainingHpjExecutionTimeLocked(final int userId, @NonNull final String packageName) {
-        ShrinkableDebits quota = getHpjQuotaLocked(userId, packageName);
+    long getRemainingEJExecutionTimeLocked(final int userId, @NonNull final String packageName) {
+        ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
         if (quota.getStandbyBucketLocked() == NEVER_INDEX) {
             return 0;
         }
-        final long limitMs = mHpjLimitsMs[quota.getStandbyBucketLocked()];
+        final long limitMs = mEJLimitsMs[quota.getStandbyBucketLocked()];
         long remainingMs = limitMs - quota.getTallyLocked();
 
         // Stale sessions may still be factored into tally. Make sure they're removed.
-        List<TimingSession> timingSessions = mHpjTimingSessions.get(userId, packageName);
+        List<TimingSession> timingSessions = mEJTimingSessions.get(userId, packageName);
         final long nowElapsed = sElapsedRealtimeClock.millis();
-        final long windowStartTimeElapsed = nowElapsed - mHpjLimitWindowSizeMs;
+        final long windowStartTimeElapsed = nowElapsed - mEJLimitWindowSizeMs;
         if (timingSessions != null) {
             while (timingSessions.size() > 0) {
                 TimingSession ts = timingSessions.get(0);
@@ -888,7 +893,7 @@
             }
         }
 
-        Timer timer = mHpjPkgTimers.get(userId, packageName);
+        Timer timer = mEJPkgTimers.get(userId, packageName);
         if (timer == null) {
             return remainingMs;
         }
@@ -986,24 +991,24 @@
     }
 
     /**
-     * Returns the amount of time, in milliseconds, until the package would have reached its HPJ
-     * quota, assuming it has a job counting towards the quota the entire time and the quota isn't
-     * replenished at all in that time.
+     * Returns the amount of time, in milliseconds, until the package would have reached its
+     * expedited job quota, assuming it has a job counting towards the quota the entire time and
+     * the quota isn't replenished at all in that time.
      */
     @VisibleForTesting
-    long getTimeUntilHpjQuotaConsumedLocked(final int userId, @NonNull final String packageName) {
+    long getTimeUntilEJQuotaConsumedLocked(final int userId, @NonNull final String packageName) {
         final long remainingExecutionTimeMs =
-                getRemainingHpjExecutionTimeLocked(userId, packageName);
+                getRemainingEJExecutionTimeLocked(userId, packageName);
 
-        List<TimingSession> sessions = mHpjTimingSessions.get(userId, packageName);
+        List<TimingSession> sessions = mEJTimingSessions.get(userId, packageName);
         if (sessions == null || sessions.size() == 0) {
             return remainingExecutionTimeMs;
         }
 
         final long nowElapsed = sElapsedRealtimeClock.millis();
-        ShrinkableDebits quota = getHpjQuotaLocked(userId, packageName);
-        final long limitMs = mHpjLimitsMs[quota.getStandbyBucketLocked()];
-        final long startWindowElapsed = Math.max(0, nowElapsed - mHpjLimitWindowSizeMs);
+        ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
+        final long limitMs = mEJLimitsMs[quota.getStandbyBucketLocked()];
+        final long startWindowElapsed = Math.max(0, nowElapsed - mEJLimitWindowSizeMs);
         long remainingDeadSpaceMs = remainingExecutionTimeMs;
         // Total time looked at where a session wouldn't be phasing out.
         long deadSpaceMs = 0;
@@ -1014,7 +1019,7 @@
             TimingSession session = sessions.get(i);
             if (session.endTimeElapsed < startWindowElapsed) {
                 // Edge case where a session became stale in the time between the call to
-                // getRemainingHpjExecutionTimeLocked and this line.
+                // getRemainingEJExecutionTimeLocked and this line.
                 remainingDeadSpaceMs += session.endTimeElapsed - session.startTimeElapsed;
                 sessions.remove(i);
                 i--;
@@ -1291,18 +1296,18 @@
 
     @VisibleForTesting
     void saveTimingSession(final int userId, @NonNull final String packageName,
-            @NonNull final TimingSession session, boolean isHpj) {
+            @NonNull final TimingSession session, boolean isExpedited) {
         synchronized (mLock) {
             final SparseArrayMap<String, List<TimingSession>> sessionMap =
-                    isHpj ? mHpjTimingSessions : mTimingSessions;
+                    isExpedited ? mEJTimingSessions : mTimingSessions;
             List<TimingSession> sessions = sessionMap.get(userId, packageName);
             if (sessions == null) {
                 sessions = new ArrayList<>();
                 sessionMap.add(userId, packageName, sessions);
             }
             sessions.add(session);
-            if (isHpj) {
-                final ShrinkableDebits quota = getHpjQuotaLocked(userId, packageName);
+            if (isExpedited) {
+                final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
                 quota.transactOnDebitsLocked(session.endTimeElapsed - session.startTimeElapsed);
             } else {
                 // Adding a new session means that the current stats are now incorrect.
@@ -1316,7 +1321,7 @@
     private void grantRewardForInstantEvent(
             final int userId, @NonNull final String packageName, final long credit) {
         synchronized (mLock) {
-            final ShrinkableDebits quota = getHpjQuotaLocked(userId, packageName);
+            final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
             quota.transactOnDebitsLocked(-credit);
             if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
                 mStateChangedListener.onControllerStateChanged();
@@ -1356,7 +1361,7 @@
         }
         mEarliestEndTimeFunctor.reset();
         mTimingSessions.forEach(mEarliestEndTimeFunctor);
-        mHpjTimingSessions.forEach(mEarliestEndTimeFunctor);
+        mEJTimingSessions.forEach(mEarliestEndTimeFunctor);
         final long earliestEndElapsed = mEarliestEndTimeFunctor.earliestEndElapsed;
         if (earliestEndElapsed == Long.MAX_VALUE) {
             // Couldn't find a good time to clean up. Maybe this was called after we deleted all
@@ -1412,7 +1417,7 @@
             Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isCharging());
         }
         // Deal with Timers first.
-        mHpjPkgTimers.forEach(mTimerChargingUpdateFunctor);
+        mEJPkgTimers.forEach(mTimerChargingUpdateFunctor);
         mPkgTimers.forEach(mTimerChargingUpdateFunctor);
         // Now update jobs.
         maybeUpdateAllConstraintsLocked();
@@ -1447,7 +1452,7 @@
         // Quota is the same for all jobs within a package.
         final int realStandbyBucket = jobs.valueAt(0).getStandbyBucket();
         final boolean realInQuota = isWithinQuotaLocked(userId, packageName, realStandbyBucket);
-        boolean outOfHpjQuota = false;
+        boolean outOfEJQuota = false;
         boolean changed = false;
         for (int i = jobs.size() - 1; i >= 0; --i) {
             final JobStatus js = jobs.valueAt(i);
@@ -1466,13 +1471,13 @@
                 changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
             }
 
-            if (js.isRequestedForegroundJob()) {
-                boolean isWithinHpjQuota = isWithinHpjQuotaLocked(js);
-                changed |= js.setForegroundJobQuotaConstraintSatisfied(isWithinHpjQuota);
-                outOfHpjQuota |= !isWithinHpjQuota;
+            if (js.isRequestedExpeditedJob()) {
+                boolean isWithinEJQuota = isWithinEJQuotaLocked(js);
+                changed |= js.setExpeditedJobQuotaConstraintSatisfied(isWithinEJQuota);
+                outOfEJQuota |= !isWithinEJQuota;
             }
         }
-        if (!realInQuota || outOfHpjQuota) {
+        if (!realInQuota || outOfEJQuota) {
             // Don't want to use the effective standby bucket here since that bump the bucket to
             // ACTIVE for one of the jobs, which doesn't help with other jobs that aren't
             // exempted.
@@ -1491,20 +1496,19 @@
         @Override
         public void accept(JobStatus jobStatus) {
             wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
-            final boolean outOfHpjQuota;
-            if (jobStatus.isRequestedForegroundJob()) {
-                final boolean isWithinHpjQuota = isWithinHpjQuotaLocked(jobStatus);
-                wasJobChanged |= jobStatus.setForegroundJobQuotaConstraintSatisfied(
-                        isWithinHpjQuota);
-                outOfHpjQuota = !isWithinHpjQuota;
+            final boolean outOfEJQuota;
+            if (jobStatus.isRequestedExpeditedJob()) {
+                final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
+                wasJobChanged |= jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinEJQuota);
+                outOfEJQuota = !isWithinEJQuota;
             } else {
-                outOfHpjQuota = false;
+                outOfEJQuota = false;
             }
 
             final int userId = jobStatus.getSourceUserId();
             final String packageName = jobStatus.getSourcePackageName();
             final int realStandbyBucket = jobStatus.getStandbyBucket();
-            if (isWithinQuotaLocked(userId, packageName, realStandbyBucket) && !outOfHpjQuota) {
+            if (isWithinQuotaLocked(userId, packageName, realStandbyBucket) && !outOfEJQuota) {
                 // TODO(141645789): we probably shouldn't cancel the alarm until we've verified
                 // that all jobs for the userId-package are within quota.
                 mInQuotaAlarmListener.removeAlarmLocked(userId, packageName);
@@ -1557,13 +1561,13 @@
         final boolean isUnderJobCountQuota = isUnderJobCountQuotaLocked(stats, standbyBucket);
         final boolean isUnderTimingSessionCountQuota = isUnderSessionCountQuotaLocked(stats,
                 standbyBucket);
-        final long remainingHpjQuota = getRemainingHpjExecutionTimeLocked(userId, packageName);
+        final long remainingEJQuota = getRemainingEJExecutionTimeLocked(userId, packageName);
 
-        if (stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
+        final boolean inRegularQuota = stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
                 && stats.executionTimeInMaxPeriodMs < mMaxExecutionTimeMs
                 && isUnderJobCountQuota
-                && isUnderTimingSessionCountQuota
-                && remainingHpjQuota > 0) {
+                && isUnderTimingSessionCountQuota;
+        if (inRegularQuota && remainingEJQuota > 0) {
             // Already in quota. Why was this method called?
             if (DEBUG) {
                 Slog.e(TAG, "maybeScheduleStartAlarmLocked called for " + pkgString
@@ -1577,11 +1581,8 @@
         }
 
         long inRegularQuotaTimeElapsed = Long.MAX_VALUE;
-        long inHpjQuotaTimeElapsed = Long.MAX_VALUE;
-        if (!(stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
-                && stats.executionTimeInMaxPeriodMs < mMaxExecutionTimeMs
-                && isUnderJobCountQuota
-                && isUnderTimingSessionCountQuota)) {
+        long inEJQuotaTimeElapsed = Long.MAX_VALUE;
+        if (!inRegularQuota) {
             // The time this app will have quota again.
             long inQuotaTimeElapsed = stats.inQuotaTimeElapsed;
             if (!isUnderJobCountQuota && stats.bgJobCountInWindow < stats.jobCountLimit) {
@@ -1597,22 +1598,39 @@
             }
             inRegularQuotaTimeElapsed = inQuotaTimeElapsed;
         }
-        if (remainingHpjQuota <= 0) {
-            final long limitMs = mHpjLimitsMs[standbyBucket] - mQuotaBufferMs;
-            List<TimingSession> timingSessions = mHpjTimingSessions.get(userId, packageName);
+        if (remainingEJQuota <= 0) {
+            final long limitMs = mEJLimitsMs[standbyBucket] - mQuotaBufferMs;
             long sumMs = 0;
-            for (int i = timingSessions.size() - 1; i >= 0; --i) {
-                TimingSession ts = timingSessions.get(i);
-                final long durationMs = ts.endTimeElapsed - ts.startTimeElapsed;
-                sumMs += durationMs;
+            final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
+            if (ejTimer != null && ejTimer.isActive()) {
+                final long nowElapsed = sElapsedRealtimeClock.millis();
+                sumMs += ejTimer.getCurrentDuration(nowElapsed);
                 if (sumMs >= limitMs) {
-                    inHpjQuotaTimeElapsed =
-                            ts.startTimeElapsed + (sumMs - limitMs) + mHpjLimitWindowSizeMs;
-                    break;
+                    inEJQuotaTimeElapsed = (nowElapsed - limitMs) + mEJLimitWindowSizeMs;
                 }
             }
+            List<TimingSession> timingSessions = mEJTimingSessions.get(userId, packageName);
+            if (timingSessions != null) {
+                for (int i = timingSessions.size() - 1; i >= 0; --i) {
+                    TimingSession ts = timingSessions.get(i);
+                    final long durationMs = ts.endTimeElapsed - ts.startTimeElapsed;
+                    sumMs += durationMs;
+                    if (sumMs >= limitMs) {
+                        inEJQuotaTimeElapsed =
+                                ts.startTimeElapsed + (sumMs - limitMs) + mEJLimitWindowSizeMs;
+                        break;
+                    }
+                }
+            } else if ((ejTimer == null || !ejTimer.isActive()) && inRegularQuota) {
+                // In some strange cases, an app may end be in the NEVER bucket but could have run
+                // some regular jobs. This results in no EJ timing sessions and QC having a bad
+                // time.
+                Slog.wtf(TAG,
+                        string(userId, packageName) + " has 0 EJ quota without running anything");
+                return;
+            }
         }
-        long inQuotaTimeElapsed = Math.min(inRegularQuotaTimeElapsed, inHpjQuotaTimeElapsed);
+        long inQuotaTimeElapsed = Math.min(inRegularQuotaTimeElapsed, inEJQuotaTimeElapsed);
 
         if (inQuotaTimeElapsed <= sElapsedRealtimeClock.millis()) {
             final long nowElapsed = sElapsedRealtimeClock.millis();
@@ -1964,13 +1982,13 @@
                     return;
                 }
                 Message msg = mHandler.obtainMessage(
-                        mRegularJobTimer ? MSG_REACHED_QUOTA : MSG_REACHED_HPJ_QUOTA, mPkg);
+                        mRegularJobTimer ? MSG_REACHED_QUOTA : MSG_REACHED_EJ_QUOTA, mPkg);
                 final long timeRemainingMs = mRegularJobTimer
                         ? getTimeUntilQuotaConsumedLocked(mPkg.userId, mPkg.packageName)
-                        : getTimeUntilHpjQuotaConsumedLocked(mPkg.userId, mPkg.packageName);
+                        : getTimeUntilEJQuotaConsumedLocked(mPkg.userId, mPkg.packageName);
                 if (DEBUG) {
                     Slog.i(TAG,
-                            (mRegularJobTimer ? "Regular job" : "HPJ") + " for " + mPkg + " has "
+                            (mRegularJobTimer ? "Regular job" : "EJ") + " for " + mPkg + " has "
                                     + timeRemainingMs + "ms left.");
                 }
                 // If the job was running the entire time, then the system would be up, so it's
@@ -1981,12 +1999,12 @@
 
         private void cancelCutoff() {
             mHandler.removeMessages(
-                    mRegularJobTimer ? MSG_REACHED_QUOTA : MSG_REACHED_HPJ_QUOTA, mPkg);
+                    mRegularJobTimer ? MSG_REACHED_QUOTA : MSG_REACHED_EJ_QUOTA, mPkg);
         }
 
         public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate) {
             pw.print("Timer<");
-            pw.print(mRegularJobTimer ? "REG" : " HPJ");
+            pw.print(mRegularJobTimer ? "REG" : " EJ");
             pw.print(">{");
             pw.print(mPkg);
             pw.print("} ");
@@ -2061,8 +2079,8 @@
                             mActivities.removeReturnOld(event.mInstanceId);
                     if (existingEvent != null && mActivities.size() == 0) {
                         final long totalTopTimeMs = nowElapsed - mStartTimeElapsed;
-                        int numTimeChunks = (int) (totalTopTimeMs / mHpjTopAppTimeChunkSizeMs);
-                        final long remainderMs = totalTopTimeMs % mHpjTopAppTimeChunkSizeMs;
+                        int numTimeChunks = (int) (totalTopTimeMs / mEJTopAppTimeChunkSizeMs);
+                        final long remainderMs = totalTopTimeMs % mEJTopAppTimeChunkSizeMs;
                         if (remainderMs >= SECOND_IN_MILLIS) {
                             // "Round up"
                             numTimeChunks++;
@@ -2072,8 +2090,8 @@
                                     "Crediting " + mPkg + " for " + numTimeChunks + " time chunks");
                         }
                         final ShrinkableDebits quota =
-                                getHpjQuotaLocked(mPkg.userId, mPkg.packageName);
-                        quota.transactOnDebitsLocked(-mHpjRewardTopAppMs * numTimeChunks);
+                                getEJQuotaLocked(mPkg.userId, mPkg.packageName);
+                        quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
                         if (maybeUpdateConstraintForPkgLocked(mPkg.userId, mPkg.packageName)) {
                             mStateChangedListener.onControllerStateChanged();
                         }
@@ -2150,7 +2168,7 @@
         }
         List<JobStatus> restrictedChanges = new ArrayList<>();
         synchronized (mLock) {
-            ShrinkableDebits debits = mHpjStats.get(userId, packageName);
+            ShrinkableDebits debits = mEJStats.get(userId, packageName);
             if (debits != null) {
                 debits.setStandbyBucketLocked(bucketIndex);
             }
@@ -2174,7 +2192,7 @@
             if (timer != null && timer.isActive()) {
                 timer.rescheduleCutoff();
             }
-            timer = mHpjPkgTimers.get(userId, packageName);
+            timer = mEJPkgTimers.get(userId, packageName);
             if (timer != null && timer.isActive()) {
                 timer.rescheduleCutoff();
             }
@@ -2219,8 +2237,8 @@
     @VisibleForTesting
     void deleteObsoleteSessionsLocked() {
         mTimingSessions.forEach(mDeleteOldSessionsFunctor);
-        // Don't delete HPJ timing sessions here. They'll be removed in
-        // getRemainingHpjExecutionTimeLocked().
+        // Don't delete EJ timing sessions here. They'll be removed in
+        // getRemainingEJExecutionTimeLocked().
     }
 
     private class QcHandler extends Handler {
@@ -2264,16 +2282,16 @@
                         }
                         break;
                     }
-                    case MSG_REACHED_HPJ_QUOTA: {
+                    case MSG_REACHED_EJ_QUOTA: {
                         Package pkg = (Package) msg.obj;
                         if (DEBUG) {
-                            Slog.d(TAG, "Checking if " + pkg + " has reached its HPJ quota.");
+                            Slog.d(TAG, "Checking if " + pkg + " has reached its EJ quota.");
                         }
 
-                        long timeRemainingMs = getRemainingHpjExecutionTimeLocked(
+                        long timeRemainingMs = getRemainingEJExecutionTimeLocked(
                                 pkg.userId, pkg.packageName);
                         if (timeRemainingMs <= 0) {
-                            if (DEBUG) Slog.d(TAG, pkg + " has reached its HPJ quota.");
+                            if (DEBUG) Slog.d(TAG, pkg + " has reached its EJ quota.");
                             if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
                                 mStateChangedListener.onControllerStateChanged();
                             }
@@ -2281,11 +2299,11 @@
                             // This could potentially happen if an old session phases out while a
                             // job is currently running.
                             // Reschedule message
-                            Message rescheduleMsg = obtainMessage(MSG_REACHED_HPJ_QUOTA, pkg);
-                            timeRemainingMs = getTimeUntilHpjQuotaConsumedLocked(
+                            Message rescheduleMsg = obtainMessage(MSG_REACHED_EJ_QUOTA, pkg);
+                            timeRemainingMs = getTimeUntilEJQuotaConsumedLocked(
                                     pkg.userId, pkg.packageName);
                             if (DEBUG) {
-                                Slog.d(TAG, pkg + " has " + timeRemainingMs + "ms left for HPJ");
+                                Slog.d(TAG, pkg + " has " + timeRemainingMs + "ms left for EJ");
                             }
                             sendMessageDelayed(rescheduleMsg, timeRemainingMs);
                         }
@@ -2327,7 +2345,7 @@
                             }
                             // Update Timers first.
                             if (mPkgTimers.indexOfKey(userId) >= 0
-                                    || mHpjPkgTimers.indexOfKey(userId) >= 0) {
+                                    || mEJPkgTimers.indexOfKey(userId) >= 0) {
                                 ArraySet<String> packages = mUidToPackageCache.get(uid);
                                 if (packages == null) {
                                     try {
@@ -2345,7 +2363,7 @@
                                 }
                                 if (packages != null) {
                                     for (int i = packages.size() - 1; i >= 0; --i) {
-                                        Timer t = mHpjPkgTimers.get(userId, packages.valueAt(i));
+                                        Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
                                         if (t != null) {
                                             t.onStateChangedLocked(nowElapsed, isQuotaFree);
                                         }
@@ -2386,13 +2404,13 @@
                                 // Don't need to include SHORTCUT_INVOCATION. The app will be
                                 // launched through it (if it's not already on top).
                                 grantRewardForInstantEvent(
-                                        userId, pkgName, mHpjRewardInteractionMs);
+                                        userId, pkgName, mEJRewardInteractionMs);
                                 break;
                             case UsageEvents.Event.NOTIFICATION_SEEN:
                                 // Intentionally don't give too much for notification seen.
                                 // Interactions will award more.
                                 grantRewardForInstantEvent(
-                                        userId, pkgName, mHpjRewardNotificationSeenMs);
+                                        userId, pkgName, mEJRewardNotificationSeenMs);
                                 break;
                         }
 
@@ -2583,7 +2601,7 @@
         mQcConstants.mShouldReevaluateConstraints = false;
         mQcConstants.mRateLimitingConstantsUpdated = false;
         mQcConstants.mExecutionPeriodConstantsUpdated = false;
-        mQcConstants.mHpjLimitConstantsUpdated = false;
+        mQcConstants.mEJLimitConstantsUpdated = false;
     }
 
     @Override
@@ -2609,7 +2627,7 @@
         private boolean mShouldReevaluateConstraints = false;
         private boolean mRateLimitingConstantsUpdated = false;
         private boolean mExecutionPeriodConstantsUpdated = false;
-        private boolean mHpjLimitConstantsUpdated = false;
+        private boolean mEJLimitConstantsUpdated = false;
 
         /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */
         private static final String QC_CONSTANT_PREFIX = "qc_";
@@ -2684,35 +2702,35 @@
         static final String KEY_MIN_QUOTA_CHECK_DELAY_MS =
                 QC_CONSTANT_PREFIX + "min_quota_check_delay_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_LIMIT_ACTIVE_MS =
-                QC_CONSTANT_PREFIX + "hpj_limit_active_ms";
+        static final String KEY_EJ_LIMIT_ACTIVE_MS =
+                QC_CONSTANT_PREFIX + "ej_limit_active_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_LIMIT_WORKING_MS =
-                QC_CONSTANT_PREFIX + "hpj_limit_working_ms";
+        static final String KEY_EJ_LIMIT_WORKING_MS =
+                QC_CONSTANT_PREFIX + "ej_limit_working_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_LIMIT_FREQUENT_MS =
-                QC_CONSTANT_PREFIX + "hpj_limit_frequent_ms";
+        static final String KEY_EJ_LIMIT_FREQUENT_MS =
+                QC_CONSTANT_PREFIX + "ej_limit_frequent_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_LIMIT_RARE_MS =
-                QC_CONSTANT_PREFIX + "hpj_limit_rare_ms";
+        static final String KEY_EJ_LIMIT_RARE_MS =
+                QC_CONSTANT_PREFIX + "ej_limit_rare_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_LIMIT_RESTRICTED_MS =
-                QC_CONSTANT_PREFIX + "hpj_limit_restricted_ms";
+        static final String KEY_EJ_LIMIT_RESTRICTED_MS =
+                QC_CONSTANT_PREFIX + "ej_limit_restricted_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_WINDOW_SIZE_MS =
-                QC_CONSTANT_PREFIX + "hpj_window_size_ms";
+        static final String KEY_EJ_WINDOW_SIZE_MS =
+                QC_CONSTANT_PREFIX + "ej_window_size_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS =
-                QC_CONSTANT_PREFIX + "hpj_top_app_time_chunk_size_ms";
+        static final String KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS =
+                QC_CONSTANT_PREFIX + "ej_top_app_time_chunk_size_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_REWARD_TOP_APP_MS =
-                QC_CONSTANT_PREFIX + "hpj_reward_top_app_ms";
+        static final String KEY_EJ_REWARD_TOP_APP_MS =
+                QC_CONSTANT_PREFIX + "ej_reward_top_app_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_REWARD_INTERACTION_MS =
-                QC_CONSTANT_PREFIX + "hpj_reward_interaction_ms";
+        static final String KEY_EJ_REWARD_INTERACTION_MS =
+                QC_CONSTANT_PREFIX + "ej_reward_interaction_ms";
         @VisibleForTesting
-        static final String KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS =
-                QC_CONSTANT_PREFIX + "hpj_reward_notification_seen_ms";
+        static final String KEY_EJ_REWARD_NOTIFICATION_SEEN_MS =
+                QC_CONSTANT_PREFIX + "ej_reward_notification_seen_ms";
 
         private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_MS =
                 10 * 60 * 1000L; // 10 minutes
@@ -2754,16 +2772,16 @@
         private static final int DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 20;
         private static final long DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS = 5000; // 5 seconds
         private static final long DEFAULT_MIN_QUOTA_CHECK_DELAY_MS = MINUTE_IN_MILLIS;
-        private static final long DEFAULT_HPJ_LIMIT_ACTIVE_MS = 30 * MINUTE_IN_MILLIS;
-        private static final long DEFAULT_HPJ_LIMIT_WORKING_MS = DEFAULT_HPJ_LIMIT_ACTIVE_MS;
-        private static final long DEFAULT_HPJ_LIMIT_FREQUENT_MS = 10 * MINUTE_IN_MILLIS;
-        private static final long DEFAULT_HPJ_LIMIT_RARE_MS = DEFAULT_HPJ_LIMIT_FREQUENT_MS;
-        private static final long DEFAULT_HPJ_LIMIT_RESTRICTED_MS = 5 * MINUTE_IN_MILLIS;
-        private static final long DEFAULT_HPJ_WINDOW_SIZE_MS = 24 * HOUR_IN_MILLIS;
-        private static final long DEFAULT_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS = 30 * SECOND_IN_MILLIS;
-        private static final long DEFAULT_HPJ_REWARD_TOP_APP_MS = 10 * SECOND_IN_MILLIS;
-        private static final long DEFAULT_HPJ_REWARD_INTERACTION_MS = 15 * SECOND_IN_MILLIS;
-        private static final long DEFAULT_HPJ_REWARD_NOTIFICATION_SEEN_MS = 0;
+        private static final long DEFAULT_EJ_LIMIT_ACTIVE_MS = 30 * MINUTE_IN_MILLIS;
+        private static final long DEFAULT_EJ_LIMIT_WORKING_MS = DEFAULT_EJ_LIMIT_ACTIVE_MS;
+        private static final long DEFAULT_EJ_LIMIT_FREQUENT_MS = 10 * MINUTE_IN_MILLIS;
+        private static final long DEFAULT_EJ_LIMIT_RARE_MS = DEFAULT_EJ_LIMIT_FREQUENT_MS;
+        private static final long DEFAULT_EJ_LIMIT_RESTRICTED_MS = 5 * MINUTE_IN_MILLIS;
+        private static final long DEFAULT_EJ_WINDOW_SIZE_MS = 24 * HOUR_IN_MILLIS;
+        private static final long DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = 30 * SECOND_IN_MILLIS;
+        private static final long DEFAULT_EJ_REWARD_TOP_APP_MS = 10 * SECOND_IN_MILLIS;
+        private static final long DEFAULT_EJ_REWARD_INTERACTION_MS = 15 * SECOND_IN_MILLIS;
+        private static final long DEFAULT_EJ_REWARD_NOTIFICATION_SEEN_MS = 0;
 
         /** How much time each app will have to run jobs within their standby bucket window. */
         public long ALLOWED_TIME_PER_PERIOD_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
@@ -2924,72 +2942,67 @@
         private static final long MIN_RATE_LIMITING_WINDOW_MS = 30 * SECOND_IN_MILLIS;
 
         /**
-         * The total session limit of the particular standby bucket. Apps in this standby bucket
-         * can
-         * only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-         * HPJs).
+         * The total expedited job session limit of the particular standby bucket. Apps in this
+         * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_LIMIT_ACTIVE_MS = DEFAULT_HPJ_LIMIT_ACTIVE_MS;
+        public long EJ_LIMIT_ACTIVE_MS = DEFAULT_EJ_LIMIT_ACTIVE_MS;
 
         /**
-         * The total session limit of the particular standby bucket. Apps in this standby bucket
-         * can
-         * only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-         * HPJs).
+         * The total expedited job session limit of the particular standby bucket. Apps in this
+         * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_LIMIT_WORKING_MS = DEFAULT_HPJ_LIMIT_WORKING_MS;
+        public long EJ_LIMIT_WORKING_MS = DEFAULT_EJ_LIMIT_WORKING_MS;
 
         /**
-         * The total session limit of the particular standby bucket. Apps in this standby bucket
-         * can
-         * only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-         * HPJs).
+         * The total expedited job session limit of the particular standby bucket. Apps in this
+         * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_LIMIT_FREQUENT_MS = DEFAULT_HPJ_LIMIT_FREQUENT_MS;
+        public long EJ_LIMIT_FREQUENT_MS = DEFAULT_EJ_LIMIT_FREQUENT_MS;
 
         /**
-         * The total session limit of the particular standby bucket. Apps in this standby bucket
-         * can
-         * only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-         * HPJs).
+         * The total expedited job session limit of the particular standby bucket. Apps in this
+         * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_LIMIT_RARE_MS = DEFAULT_HPJ_LIMIT_RARE_MS;
+        public long EJ_LIMIT_RARE_MS = DEFAULT_EJ_LIMIT_RARE_MS;
 
         /**
-         * The total session limit of the particular standby bucket. Apps in this standby bucket
-         * can
-         * only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-         * HPJs).
+         * The total expedited job session limit of the particular standby bucket. Apps in this
+         * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_LIMIT_RESTRICTED_MS = DEFAULT_HPJ_LIMIT_RESTRICTED_MS;
+        public long EJ_LIMIT_RESTRICTED_MS = DEFAULT_EJ_LIMIT_RESTRICTED_MS;
 
         /**
-         * The period of time used to calculate HPJ sessions. Apps can only have HPJ sessions
-         * totalling HPJ_LIMIT_<bucket>_MS within this period of time (without factoring in any
-         * rewards or free HPJs).
+         * The period of time used to calculate expedited job sessions. Apps can only have expedited
+         * job sessions totalling EJ_LIMIT_<bucket>_MS within this period of time (without factoring
+         * in any rewards or free EJs).
          */
-        public long HPJ_WINDOW_SIZE_MS = DEFAULT_HPJ_WINDOW_SIZE_MS;
+        public long EJ_WINDOW_SIZE_MS = DEFAULT_EJ_WINDOW_SIZE_MS;
 
         /**
          * Length of time used to split an app's top time into chunks.
          */
-        public long HPJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS;
+        public long EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS;
 
         /**
-         * How much HPJ quota to give back to an app based on the number of top app time chunks it
+         * How much EJ quota to give back to an app based on the number of top app time chunks it
          * had.
          */
-        public long HPJ_REWARD_TOP_APP_MS = DEFAULT_HPJ_REWARD_TOP_APP_MS;
+        public long EJ_REWARD_TOP_APP_MS = DEFAULT_EJ_REWARD_TOP_APP_MS;
 
         /**
-         * How much HPJ quota to give back to an app based on each non-top user interaction.
+         * How much EJ quota to give back to an app based on each non-top user interaction.
          */
-        public long HPJ_REWARD_INTERACTION_MS = DEFAULT_HPJ_REWARD_INTERACTION_MS;
+        public long EJ_REWARD_INTERACTION_MS = DEFAULT_EJ_REWARD_INTERACTION_MS;
 
         /**
-         * How much HPJ quota to give back to an app based on each notification seen event.
+         * How much EJ quota to give back to an app based on each notification seen event.
          */
-        public long HPJ_REWARD_NOTIFICATION_SEEN_MS = DEFAULT_HPJ_REWARD_NOTIFICATION_SEEN_MS;
+        public long EJ_REWARD_NOTIFICATION_SEEN_MS = DEFAULT_EJ_REWARD_NOTIFICATION_SEEN_MS;
 
         public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
                 @NonNull String key) {
@@ -3011,13 +3024,13 @@
                     updateRateLimitingConstantsLocked();
                     break;
 
-                case KEY_HPJ_LIMIT_ACTIVE_MS:
-                case KEY_HPJ_LIMIT_WORKING_MS:
-                case KEY_HPJ_LIMIT_FREQUENT_MS:
-                case KEY_HPJ_LIMIT_RARE_MS:
-                case KEY_HPJ_LIMIT_RESTRICTED_MS:
-                case KEY_HPJ_WINDOW_SIZE_MS:
-                    updateHpjLimitConstantsLocked();
+                case KEY_EJ_LIMIT_ACTIVE_MS:
+                case KEY_EJ_LIMIT_WORKING_MS:
+                case KEY_EJ_LIMIT_FREQUENT_MS:
+                case KEY_EJ_LIMIT_RARE_MS:
+                case KEY_EJ_LIMIT_RESTRICTED_MS:
+                case KEY_EJ_WINDOW_SIZE_MS:
+                    updateEJLimitConstantsLocked();
                     break;
 
                 case KEY_MAX_JOB_COUNT_ACTIVE:
@@ -3130,63 +3143,63 @@
                     mInQuotaAlarmListener.setMinQuotaCheckDelayMs(
                             Math.min(15 * MINUTE_IN_MILLIS, Math.max(0, MIN_QUOTA_CHECK_DELAY_MS)));
                     break;
-                case KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS:
+                case KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS:
                     // We don't need to re-evaluate execution stats or constraint status for this.
-                    HPJ_TOP_APP_TIME_CHUNK_SIZE_MS =
-                            properties.getLong(key, DEFAULT_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS);
+                    EJ_TOP_APP_TIME_CHUNK_SIZE_MS =
+                            properties.getLong(key, DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS);
                     // Limit chunking to be in the range [1 millisecond, 15 minutes] per event.
                     long newChunkSizeMs = Math.min(15 * MINUTE_IN_MILLIS,
-                            Math.max(1, HPJ_TOP_APP_TIME_CHUNK_SIZE_MS));
-                    if (mHpjTopAppTimeChunkSizeMs != newChunkSizeMs) {
-                        mHpjTopAppTimeChunkSizeMs = newChunkSizeMs;
-                        if (mHpjTopAppTimeChunkSizeMs < mHpjRewardTopAppMs) {
+                            Math.max(1, EJ_TOP_APP_TIME_CHUNK_SIZE_MS));
+                    if (mEJTopAppTimeChunkSizeMs != newChunkSizeMs) {
+                        mEJTopAppTimeChunkSizeMs = newChunkSizeMs;
+                        if (mEJTopAppTimeChunkSizeMs < mEJRewardTopAppMs) {
                             // Not making chunk sizes and top rewards to be the upper/lower
                             // limits of the other to allow trying different policies. Just log
                             // the discrepancy.
-                            Slog.w(TAG, "HPJ top app time chunk less than reward: "
-                                    + mHpjTopAppTimeChunkSizeMs + " vs " + mHpjRewardTopAppMs);
+                            Slog.w(TAG, "EJ top app time chunk less than reward: "
+                                    + mEJTopAppTimeChunkSizeMs + " vs " + mEJRewardTopAppMs);
                         }
                     }
                     break;
-                case KEY_HPJ_REWARD_TOP_APP_MS:
+                case KEY_EJ_REWARD_TOP_APP_MS:
                     // We don't need to re-evaluate execution stats or constraint status for this.
-                    HPJ_REWARD_TOP_APP_MS =
-                            properties.getLong(key, DEFAULT_HPJ_REWARD_TOP_APP_MS);
+                    EJ_REWARD_TOP_APP_MS =
+                            properties.getLong(key, DEFAULT_EJ_REWARD_TOP_APP_MS);
                     // Limit top reward to be in the range [10 seconds, 15 minutes] per event.
                     long newTopReward = Math.min(15 * MINUTE_IN_MILLIS,
-                            Math.max(10 * SECOND_IN_MILLIS, HPJ_REWARD_TOP_APP_MS));
-                    if (mHpjRewardTopAppMs != newTopReward) {
-                        mHpjRewardTopAppMs = newTopReward;
-                        if (mHpjTopAppTimeChunkSizeMs < mHpjRewardTopAppMs) {
+                            Math.max(10 * SECOND_IN_MILLIS, EJ_REWARD_TOP_APP_MS));
+                    if (mEJRewardTopAppMs != newTopReward) {
+                        mEJRewardTopAppMs = newTopReward;
+                        if (mEJTopAppTimeChunkSizeMs < mEJRewardTopAppMs) {
                             // Not making chunk sizes and top rewards to be the upper/lower
                             // limits of the other to allow trying different policies. Just log
                             // the discrepancy.
-                            Slog.w(TAG, "HPJ top app time chunk less than reward: "
-                                    + mHpjTopAppTimeChunkSizeMs + " vs " + mHpjRewardTopAppMs);
+                            Slog.w(TAG, "EJ top app time chunk less than reward: "
+                                    + mEJTopAppTimeChunkSizeMs + " vs " + mEJRewardTopAppMs);
                         }
                     }
                     break;
-                case KEY_HPJ_REWARD_INTERACTION_MS:
+                case KEY_EJ_REWARD_INTERACTION_MS:
                     // We don't need to re-evaluate execution stats or constraint status for this.
-                    HPJ_REWARD_INTERACTION_MS =
-                            properties.getLong(key, DEFAULT_HPJ_REWARD_INTERACTION_MS);
+                    EJ_REWARD_INTERACTION_MS =
+                            properties.getLong(key, DEFAULT_EJ_REWARD_INTERACTION_MS);
                     // Limit interaction reward to be in the range [5 seconds, 15 minutes] per
                     // event.
                     long newInteractionReward = Math.min(15 * MINUTE_IN_MILLIS,
-                            Math.max(5 * SECOND_IN_MILLIS, HPJ_REWARD_INTERACTION_MS));
-                    if (mHpjRewardInteractionMs != newInteractionReward) {
-                        mHpjRewardInteractionMs = newInteractionReward;
+                            Math.max(5 * SECOND_IN_MILLIS, EJ_REWARD_INTERACTION_MS));
+                    if (mEJRewardInteractionMs != newInteractionReward) {
+                        mEJRewardInteractionMs = newInteractionReward;
                     }
                     break;
-                case KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS:
+                case KEY_EJ_REWARD_NOTIFICATION_SEEN_MS:
                     // We don't need to re-evaluate execution stats or constraint status for this.
-                    HPJ_REWARD_NOTIFICATION_SEEN_MS =
-                            properties.getLong(key, DEFAULT_HPJ_REWARD_NOTIFICATION_SEEN_MS);
+                    EJ_REWARD_NOTIFICATION_SEEN_MS =
+                            properties.getLong(key, DEFAULT_EJ_REWARD_NOTIFICATION_SEEN_MS);
                     // Limit notification seen reward to be in the range [0, 5] minutes per event.
                     long newNotiSeenReward = Math.min(5 * MINUTE_IN_MILLIS,
-                            Math.max(0, HPJ_REWARD_NOTIFICATION_SEEN_MS));
-                    if (mHpjRewardNotificationSeenMs != newNotiSeenReward) {
-                        mHpjRewardNotificationSeenMs = newNotiSeenReward;
+                            Math.max(0, EJ_REWARD_NOTIFICATION_SEEN_MS));
+                    if (mEJRewardNotificationSeenMs != newNotiSeenReward) {
+                        mEJRewardNotificationSeenMs = newNotiSeenReward;
                     }
             }
         }
@@ -3328,71 +3341,71 @@
             }
         }
 
-        private void updateHpjLimitConstantsLocked() {
-            if (mHpjLimitConstantsUpdated) {
+        private void updateEJLimitConstantsLocked() {
+            if (mEJLimitConstantsUpdated) {
                 return;
             }
-            mHpjLimitConstantsUpdated = true;
+            mEJLimitConstantsUpdated = true;
 
             // Query the values as an atomic set.
             final DeviceConfig.Properties properties = DeviceConfig.getProperties(
                     DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    KEY_HPJ_LIMIT_ACTIVE_MS, KEY_HPJ_LIMIT_WORKING_MS,
-                    KEY_HPJ_LIMIT_FREQUENT_MS, KEY_HPJ_LIMIT_RARE_MS,
-                    KEY_HPJ_LIMIT_RESTRICTED_MS, KEY_HPJ_WINDOW_SIZE_MS);
-            HPJ_LIMIT_ACTIVE_MS = properties.getLong(
-                    KEY_HPJ_LIMIT_ACTIVE_MS, DEFAULT_HPJ_LIMIT_ACTIVE_MS);
-            HPJ_LIMIT_WORKING_MS = properties.getLong(
-                    KEY_HPJ_LIMIT_WORKING_MS, DEFAULT_HPJ_LIMIT_WORKING_MS);
-            HPJ_LIMIT_FREQUENT_MS = properties.getLong(
-                    KEY_HPJ_LIMIT_FREQUENT_MS, DEFAULT_HPJ_LIMIT_FREQUENT_MS);
-            HPJ_LIMIT_RARE_MS = properties.getLong(
-                    KEY_HPJ_LIMIT_RARE_MS, DEFAULT_HPJ_LIMIT_RARE_MS);
-            HPJ_LIMIT_RESTRICTED_MS = properties.getLong(
-                    KEY_HPJ_LIMIT_RESTRICTED_MS, DEFAULT_HPJ_LIMIT_RESTRICTED_MS);
-            HPJ_WINDOW_SIZE_MS = properties.getLong(
-                    KEY_HPJ_WINDOW_SIZE_MS, DEFAULT_HPJ_WINDOW_SIZE_MS);
+                    KEY_EJ_LIMIT_ACTIVE_MS, KEY_EJ_LIMIT_WORKING_MS,
+                    KEY_EJ_LIMIT_FREQUENT_MS, KEY_EJ_LIMIT_RARE_MS,
+                    KEY_EJ_LIMIT_RESTRICTED_MS, KEY_EJ_WINDOW_SIZE_MS);
+            EJ_LIMIT_ACTIVE_MS = properties.getLong(
+                    KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS);
+            EJ_LIMIT_WORKING_MS = properties.getLong(
+                    KEY_EJ_LIMIT_WORKING_MS, DEFAULT_EJ_LIMIT_WORKING_MS);
+            EJ_LIMIT_FREQUENT_MS = properties.getLong(
+                    KEY_EJ_LIMIT_FREQUENT_MS, DEFAULT_EJ_LIMIT_FREQUENT_MS);
+            EJ_LIMIT_RARE_MS = properties.getLong(
+                    KEY_EJ_LIMIT_RARE_MS, DEFAULT_EJ_LIMIT_RARE_MS);
+            EJ_LIMIT_RESTRICTED_MS = properties.getLong(
+                    KEY_EJ_LIMIT_RESTRICTED_MS, DEFAULT_EJ_LIMIT_RESTRICTED_MS);
+            EJ_WINDOW_SIZE_MS = properties.getLong(
+                    KEY_EJ_WINDOW_SIZE_MS, DEFAULT_EJ_WINDOW_SIZE_MS);
 
             // The window must be in the range [1 hour, 24 hours].
             long newWindowSizeMs = Math.max(HOUR_IN_MILLIS,
-                    Math.min(MAX_PERIOD_MS, HPJ_WINDOW_SIZE_MS));
-            if (mHpjLimitWindowSizeMs != newWindowSizeMs) {
-                mHpjLimitWindowSizeMs = newWindowSizeMs;
+                    Math.min(MAX_PERIOD_MS, EJ_WINDOW_SIZE_MS));
+            if (mEJLimitWindowSizeMs != newWindowSizeMs) {
+                mEJLimitWindowSizeMs = newWindowSizeMs;
                 mShouldReevaluateConstraints = true;
             }
             // The limit must be in the range [15 minutes, window size].
             long newActiveLimitMs = Math.max(15 * MINUTE_IN_MILLIS,
-                    Math.min(newWindowSizeMs, HPJ_LIMIT_ACTIVE_MS));
-            if (mHpjLimitsMs[ACTIVE_INDEX] != newActiveLimitMs) {
-                mHpjLimitsMs[ACTIVE_INDEX] = newActiveLimitMs;
+                    Math.min(newWindowSizeMs, EJ_LIMIT_ACTIVE_MS));
+            if (mEJLimitsMs[ACTIVE_INDEX] != newActiveLimitMs) {
+                mEJLimitsMs[ACTIVE_INDEX] = newActiveLimitMs;
                 mShouldReevaluateConstraints = true;
             }
             // The limit must be in the range [15 minutes, active limit].
             long newWorkingLimitMs = Math.max(15 * MINUTE_IN_MILLIS,
-                    Math.min(newActiveLimitMs, HPJ_LIMIT_WORKING_MS));
-            if (mHpjLimitsMs[WORKING_INDEX] != newWorkingLimitMs) {
-                mHpjLimitsMs[WORKING_INDEX] = newWorkingLimitMs;
+                    Math.min(newActiveLimitMs, EJ_LIMIT_WORKING_MS));
+            if (mEJLimitsMs[WORKING_INDEX] != newWorkingLimitMs) {
+                mEJLimitsMs[WORKING_INDEX] = newWorkingLimitMs;
                 mShouldReevaluateConstraints = true;
             }
             // The limit must be in the range [10 minutes, working limit].
             long newFrequentLimitMs = Math.max(10 * MINUTE_IN_MILLIS,
-                    Math.min(newWorkingLimitMs, HPJ_LIMIT_FREQUENT_MS));
-            if (mHpjLimitsMs[FREQUENT_INDEX] != newFrequentLimitMs) {
-                mHpjLimitsMs[FREQUENT_INDEX] = newFrequentLimitMs;
+                    Math.min(newWorkingLimitMs, EJ_LIMIT_FREQUENT_MS));
+            if (mEJLimitsMs[FREQUENT_INDEX] != newFrequentLimitMs) {
+                mEJLimitsMs[FREQUENT_INDEX] = newFrequentLimitMs;
                 mShouldReevaluateConstraints = true;
             }
             // The limit must be in the range [10 minutes, frequent limit].
             long newRareLimitMs = Math.max(10 * MINUTE_IN_MILLIS,
-                    Math.min(newFrequentLimitMs, HPJ_LIMIT_RARE_MS));
-            if (mHpjLimitsMs[RARE_INDEX] != newRareLimitMs) {
-                mHpjLimitsMs[RARE_INDEX] = newRareLimitMs;
+                    Math.min(newFrequentLimitMs, EJ_LIMIT_RARE_MS));
+            if (mEJLimitsMs[RARE_INDEX] != newRareLimitMs) {
+                mEJLimitsMs[RARE_INDEX] = newRareLimitMs;
                 mShouldReevaluateConstraints = true;
             }
             // The limit must be in the range [0 minutes, rare limit].
             long newRestrictedLimitMs = Math.max(0,
-                    Math.min(newRareLimitMs, HPJ_LIMIT_RESTRICTED_MS));
-            if (mHpjLimitsMs[RESTRICTED_INDEX] != newRestrictedLimitMs) {
-                mHpjLimitsMs[RESTRICTED_INDEX] = newRestrictedLimitMs;
+                    Math.min(newRareLimitMs, EJ_LIMIT_RESTRICTED_MS));
+            if (mEJLimitsMs[RESTRICTED_INDEX] != newRestrictedLimitMs) {
+                mEJLimitsMs[RESTRICTED_INDEX] = newRestrictedLimitMs;
                 mShouldReevaluateConstraints = true;
             }
         }
@@ -3428,17 +3441,16 @@
                     TIMING_SESSION_COALESCING_DURATION_MS).println();
             pw.print(KEY_MIN_QUOTA_CHECK_DELAY_MS, MIN_QUOTA_CHECK_DELAY_MS).println();
 
-            pw.print(KEY_HPJ_LIMIT_ACTIVE_MS, HPJ_LIMIT_ACTIVE_MS).println();
-            pw.print(KEY_HPJ_LIMIT_WORKING_MS, HPJ_LIMIT_WORKING_MS).println();
-            pw.print(KEY_HPJ_LIMIT_FREQUENT_MS, HPJ_LIMIT_FREQUENT_MS).println();
-            pw.print(KEY_HPJ_LIMIT_RARE_MS, HPJ_LIMIT_RARE_MS).println();
-            pw.print(KEY_HPJ_LIMIT_RESTRICTED_MS, HPJ_LIMIT_RESTRICTED_MS).println();
-            pw.print(KEY_HPJ_WINDOW_SIZE_MS, HPJ_WINDOW_SIZE_MS).println();
-            pw.print(KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS, HPJ_TOP_APP_TIME_CHUNK_SIZE_MS).println();
-            pw.print(KEY_HPJ_REWARD_TOP_APP_MS, HPJ_REWARD_TOP_APP_MS).println();
-            pw.print(KEY_HPJ_REWARD_INTERACTION_MS, HPJ_REWARD_INTERACTION_MS).println();
-            pw.print(KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS,
-                    HPJ_REWARD_NOTIFICATION_SEEN_MS).println();
+            pw.print(KEY_EJ_LIMIT_ACTIVE_MS, EJ_LIMIT_ACTIVE_MS).println();
+            pw.print(KEY_EJ_LIMIT_WORKING_MS, EJ_LIMIT_WORKING_MS).println();
+            pw.print(KEY_EJ_LIMIT_FREQUENT_MS, EJ_LIMIT_FREQUENT_MS).println();
+            pw.print(KEY_EJ_LIMIT_RARE_MS, EJ_LIMIT_RARE_MS).println();
+            pw.print(KEY_EJ_LIMIT_RESTRICTED_MS, EJ_LIMIT_RESTRICTED_MS).println();
+            pw.print(KEY_EJ_WINDOW_SIZE_MS, EJ_WINDOW_SIZE_MS).println();
+            pw.print(KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, EJ_TOP_APP_TIME_CHUNK_SIZE_MS).println();
+            pw.print(KEY_EJ_REWARD_TOP_APP_MS, EJ_REWARD_TOP_APP_MS).println();
+            pw.print(KEY_EJ_REWARD_INTERACTION_MS, EJ_REWARD_INTERACTION_MS).println();
+            pw.print(KEY_EJ_REWARD_NOTIFICATION_SEEN_MS, EJ_REWARD_NOTIFICATION_SEEN_MS).println();
 
             pw.decreaseIndent();
         }
@@ -3488,22 +3500,26 @@
             proto.write(ConstantsProto.QuotaController.MIN_QUOTA_CHECK_DELAY_MS,
                     MIN_QUOTA_CHECK_DELAY_MS);
 
-            proto.write(ConstantsProto.QuotaController.HPJ_LIMIT_ACTIVE_MS, HPJ_LIMIT_ACTIVE_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_LIMIT_WORKING_MS, HPJ_LIMIT_WORKING_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_LIMIT_FREQUENT_MS,
-                    HPJ_LIMIT_FREQUENT_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_LIMIT_RARE_MS, HPJ_LIMIT_RARE_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_LIMIT_RESTRICTED_MS,
-                    HPJ_LIMIT_RESTRICTED_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_WINDOW_SIZE_MS, HPJ_WINDOW_SIZE_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_TOP_APP_TIME_CHUNK_SIZE_MS,
-                    HPJ_TOP_APP_TIME_CHUNK_SIZE_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_REWARD_TOP_APP_MS,
-                    HPJ_REWARD_TOP_APP_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_REWARD_INTERACTION_MS,
-                    HPJ_REWARD_INTERACTION_MS);
-            proto.write(ConstantsProto.QuotaController.HPJ_REWARD_NOTIFICATION_SEEN_MS,
-                    HPJ_REWARD_NOTIFICATION_SEEN_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_LIMIT_ACTIVE_MS,
+                    EJ_LIMIT_ACTIVE_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_LIMIT_WORKING_MS,
+                    EJ_LIMIT_WORKING_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_LIMIT_FREQUENT_MS,
+                    EJ_LIMIT_FREQUENT_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_LIMIT_RARE_MS,
+                    EJ_LIMIT_RARE_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_LIMIT_RESTRICTED_MS,
+                    EJ_LIMIT_RESTRICTED_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_WINDOW_SIZE_MS,
+                    EJ_WINDOW_SIZE_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_TOP_APP_TIME_CHUNK_SIZE_MS,
+                    EJ_TOP_APP_TIME_CHUNK_SIZE_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_REWARD_TOP_APP_MS,
+                    EJ_REWARD_TOP_APP_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_REWARD_INTERACTION_MS,
+                    EJ_REWARD_INTERACTION_MS);
+            proto.write(ConstantsProto.QuotaController.EXPEDITED_JOB_REWARD_NOTIFICATION_SEEN_MS,
+                    EJ_REWARD_NOTIFICATION_SEEN_MS);
 
             proto.end(qcToken);
         }
@@ -3548,45 +3564,45 @@
 
     @VisibleForTesting
     @NonNull
-    long[] getHpjLimitsMs() {
-        return mHpjLimitsMs;
+    long[] getEJLimitsMs() {
+        return mEJLimitsMs;
     }
 
     @VisibleForTesting
     @NonNull
-    long getHpjLimitWindowSizeMs() {
-        return mHpjLimitWindowSizeMs;
+    long getEJLimitWindowSizeMs() {
+        return mEJLimitWindowSizeMs;
     }
 
     @VisibleForTesting
     @NonNull
-    long getHpjRewardInteractionMs() {
-        return mHpjRewardInteractionMs;
+    long getEJRewardInteractionMs() {
+        return mEJRewardInteractionMs;
     }
 
     @VisibleForTesting
     @NonNull
-    long getHpjRewardNotificationSeenMs() {
-        return mHpjRewardNotificationSeenMs;
+    long getEJRewardNotificationSeenMs() {
+        return mEJRewardNotificationSeenMs;
     }
 
     @VisibleForTesting
     @NonNull
-    long getHpjRewardTopAppMs() {
-        return mHpjRewardTopAppMs;
+    long getEJRewardTopAppMs() {
+        return mEJRewardTopAppMs;
     }
 
 
     @VisibleForTesting
     @Nullable
-    List<TimingSession> getHpjTimingSessions(int userId, String packageName) {
-        return mHpjTimingSessions.get(userId, packageName);
+    List<TimingSession> getEJTimingSessions(int userId, String packageName) {
+        return mEJTimingSessions.get(userId, packageName);
     }
 
     @VisibleForTesting
     @NonNull
-    long getHpjTopAppTimeChunkSizeMs() {
-        return mHpjTopAppTimeChunkSizeMs;
+    long getEJTopAppTimeChunkSizeMs() {
+        return mEJTopAppTimeChunkSizeMs;
     }
 
     @VisibleForTesting
@@ -3683,18 +3699,18 @@
                 pw.increaseIndent();
                 pw.print(JobStatus.bucketName(js.getEffectiveStandbyBucket()));
                 pw.print(", ");
-                if (js.shouldTreatAsForegroundJob()) {
-                    pw.print("within HPJ quota");
+                if (js.shouldTreatAsExpeditedJob()) {
+                    pw.print("within EJ quota");
                 } else if (js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) {
                     pw.print("within regular quota");
                 } else {
                     pw.print("not within quota");
                 }
                 pw.print(", ");
-                if (js.shouldTreatAsForegroundJob()) {
-                    pw.print(getRemainingHpjExecutionTimeLocked(
+                if (js.shouldTreatAsExpeditedJob()) {
+                    pw.print(getRemainingEJExecutionTimeLocked(
                             js.getSourceUserId(), js.getSourcePackageName()));
-                    pw.print("ms remaining in HPJ quota");
+                    pw.print("ms remaining in EJ quota");
                 } else {
                     pw.print(getRemainingExecutionTimeLocked(js));
                     pw.print("ms remaining in quota");
@@ -3728,13 +3744,13 @@
         }
 
         pw.println();
-        for (int u = 0; u < mHpjPkgTimers.numMaps(); ++u) {
-            final int userId = mHpjPkgTimers.keyAt(u);
-            for (int p = 0; p < mHpjPkgTimers.numElementsForKey(userId); ++p) {
-                final String pkgName = mHpjPkgTimers.keyAt(u, p);
-                mHpjPkgTimers.valueAt(u, p).dump(pw, predicate);
+        for (int u = 0; u < mEJPkgTimers.numMaps(); ++u) {
+            final int userId = mEJPkgTimers.keyAt(u);
+            for (int p = 0; p < mEJPkgTimers.numElementsForKey(userId); ++p) {
+                final String pkgName = mEJPkgTimers.keyAt(u, p);
+                mEJPkgTimers.valueAt(u, p).dump(pw, predicate);
                 pw.println();
-                List<TimingSession> sessions = mHpjTimingSessions.get(userId, pkgName);
+                List<TimingSession> sessions = mEJTimingSessions.get(userId, pkgName);
                 if (sessions != null) {
                     pw.increaseIndent();
                     pw.println("Saved sessions:");
@@ -3778,13 +3794,13 @@
         pw.decreaseIndent();
 
         pw.println();
-        pw.println("HPJ debits:");
+        pw.println("EJ debits:");
         pw.increaseIndent();
-        for (int u = 0; u < mHpjStats.numMaps(); ++u) {
-            final int userId = mHpjStats.keyAt(u);
-            for (int p = 0; p < mHpjStats.numElementsForKey(userId); ++p) {
-                final String pkgName = mHpjStats.keyAt(u, p);
-                ShrinkableDebits debits = mHpjStats.valueAt(u, p);
+        for (int u = 0; u < mEJStats.numMaps(); ++u) {
+            final int userId = mEJStats.keyAt(u);
+            for (int p = 0; p < mEJStats.numElementsForKey(userId); ++p) {
+                final String pkgName = mEJStats.keyAt(u, p);
+                ShrinkableDebits debits = mEJStats.valueAt(u, p);
 
                 pw.print(string(userId, pkgName));
                 pw.print(": ");
@@ -3850,10 +3866,10 @@
                         getRemainingExecutionTimeLocked(js));
                 proto.write(
                         StateControllerProto.QuotaController.TrackedJob.IS_REQUESTED_FOREGROUND_JOB,
-                        js.isRequestedForegroundJob());
+                        js.isRequestedExpeditedJob());
                 proto.write(
                         StateControllerProto.QuotaController.TrackedJob.IS_WITHIN_FG_JOB_QUOTA,
-                        js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+                        js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
                 proto.end(jsToken);
             }
         });
@@ -3867,9 +3883,9 @@
 
                 mPkgTimers.valueAt(u, p).dump(proto,
                         StateControllerProto.QuotaController.PackageStats.TIMER, predicate);
-                final Timer hpjTimer = mHpjPkgTimers.get(userId, pkgName);
-                if (hpjTimer != null) {
-                    hpjTimer.dump(proto,
+                final Timer ejTimer = mEJPkgTimers.get(userId, pkgName);
+                if (ejTimer != null) {
+                    ejTimer.dump(proto,
                             StateControllerProto.QuotaController.PackageStats.FG_JOB_TIMER,
                             predicate);
                 }
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 0b0923a..dd1a0e2 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1770,9 +1770,18 @@
             final int userId = getSendingUserId();
             if (Intent.ACTION_PACKAGE_ADDED.equals(action)
                     || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-                clearCarrierPrivilegedApps();
-                // ACTION_PACKAGE_ADDED is called even for system app downgrades.
-                evaluateSystemAppException(pkgName, userId);
+                final String[] cmpList = intent.getStringArrayExtra(
+                        Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+                // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package
+                // enable/disable event (cmpList is just the package name itself), drop
+                // our carrier privileged app & system-app caches and let them refresh
+                if (cmpList == null
+                        || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) {
+                    clearCarrierPrivilegedApps();
+                    evaluateSystemAppException(pkgName, userId);
+                }
+                // component-level enable/disable can affect bucketing, so we always
+                // reevaluate that for any PACKAGE_CHANGED
                 mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkgName)
                     .sendToTarget();
             }
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index c502867..4bcc165 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -29,8 +29,7 @@
                 ":arctimersrcs",
             ],
         }
-    }
-
+    },
 }
 
 filegroup {
@@ -38,4 +37,8 @@
     srcs: [
         "com_android_server_alarm_AlarmManagerService.cpp",
     ],
+    visibility: [
+        // TODO: remove this
+        "//vendor:__subpackages__",
+    ],
 }
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
new file mode 100644
index 0000000..5f1bd37
--- /dev/null
+++ b/apex/media/Android.bp
@@ -0,0 +1,20 @@
+// 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 {
+    default_visibility: [
+        ":__subpackages__",
+        "//frameworks/av/apex",
+        "//frameworks/av/apex/testing",
+    ],
+}
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index b3c9a9a..811a700 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -48,6 +48,10 @@
         "test_com.android.media",
     ],
     min_sdk_version: "29",
+    visibility: [
+        "//frameworks/av/apex:__subpackages__",
+        "//frameworks/base", // For framework-all
+    ],
 }
 
 filegroup {
@@ -58,6 +62,7 @@
         ":mediaparser-srcs",
         ":mediasession2-java-srcs",
     ],
+    visibility: ["//frameworks/base"],
 }
 
 filegroup {
diff --git a/apex/permission/apex_manifest.json b/apex/permission/apex_manifest.json
index 7960598..6350d54 100644
--- a/apex/permission/apex_manifest.json
+++ b/apex/permission/apex_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.permission",
-  "version": 300000000
+  "version": 309999999
 }
diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp
index c0560f6..36b5dec 100644
--- a/apex/permission/framework/Android.bp
+++ b/apex/permission/framework/Android.bp
@@ -19,6 +19,7 @@
         "java/**/*.aidl",
     ],
     path: "java",
+    visibility: ["//frameworks/base"],
 }
 
 java_sdk_library {
diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp
index b7d8433..f6c3156 100644
--- a/apex/permission/service/Android.bp
+++ b/apex/permission/service/Android.bp
@@ -18,6 +18,7 @@
         "java/**/*.java",
     ],
     path: "java",
+    visibility: ["//frameworks/base/services"],
 }
 
 java_sdk_library {
diff --git a/apex/statsd/.clang-format b/apex/statsd/.clang-format
deleted file mode 100644
index cead3a0..0000000
--- a/apex/statsd/.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/apex/statsd/Android.bp b/apex/statsd/Android.bp
deleted file mode 100644
index f13861e..0000000
--- a/apex/statsd/Android.bp
+++ /dev/null
@@ -1,83 +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.
-
-apex {
-    name: "com.android.os.statsd",
-    defaults: ["com.android.os.statsd-defaults"],
-    manifest: "apex_manifest.json",
-}
-
-apex_defaults {
-    jni_libs: [
-        "libstats_jni",
-    ],
-    native_shared_libs: [
-        "libstatspull",
-        "libstatssocket",
-    ],
-    binaries: ["statsd"],
-    java_libs: [
-        "framework-statsd",
-        "service-statsd",
-    ],
-    compile_multilib: "both",
-    prebuilts: ["com.android.os.statsd.init.rc"],
-    name: "com.android.os.statsd-defaults",
-    updatable: true,
-    min_sdk_version: "30",
-    key: "com.android.os.statsd.key",
-    certificate: ":com.android.os.statsd.certificate",
-}
-
-apex_key {
-    name: "com.android.os.statsd.key",
-    public_key: "com.android.os.statsd.avbpubkey",
-    private_key: "com.android.os.statsd.pem",
-}
-
-android_app_certificate {
-    name: "com.android.os.statsd.certificate",
-    // This will use com.android.os.statsd.x509.pem (the cert) and
-    // com.android.os.statsd.pk8 (the private key)
-    certificate: "com.android.os.statsd",
-}
-
-prebuilt_etc {
-    name: "com.android.os.statsd.init.rc",
-    src: "statsd.rc",
-    filename: "init.rc",
-    installable: false,
-}
-
-// JNI library for StatsLog.write
-cc_library_shared {
-    name: "libstats_jni",
-    srcs: ["jni/**/*.cpp"],
-    header_libs: ["libnativehelper_header_only"],
-    shared_libs: [
-        "liblog",  // Has a stable abi - should not be copied into apex.
-        "libstatssocket",
-    ],
-    stl: "libc++_static",
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-        "-Wno-unused-parameter",
-    ],
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/OWNERS b/apex/statsd/OWNERS
deleted file mode 100644
index bed9600..0000000
--- a/apex/statsd/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-jeffreyhuang@google.com
-joeo@google.com
-jtnguyen@google.com
-muhammadq@google.com
-ruchirr@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
\ No newline at end of file
diff --git a/apex/statsd/TEST_MAPPING b/apex/statsd/TEST_MAPPING
deleted file mode 100644
index 331fe77..0000000
--- a/apex/statsd/TEST_MAPPING
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "presubmit" : [
-    {
-      "name" : "FrameworkStatsdTest"
-    },
-    {
-      "name" : "LibStatsPullTests"
-    }
-  ],
-
-  "postsubmit" : [
-    {
-      "name" : "CtsStatsdHostTestCases"
-    },
-    {
-      "name" : "GtsStatsdHostTestCases"
-    }
-  ]
-}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
deleted file mode 100644
index f66cf7c..0000000
--- a/apex/statsd/aidl/Android.bp
+++ /dev/null
@@ -1,52 +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.
-//
-filegroup {
-    name: "framework-statsd-aidl-sources",
-    srcs: ["**/*.aidl"],
-}
-
-aidl_interface {
-    name: "statsd-aidl",
-    unstable: true,
-    srcs: [
-        "android/os/IPendingIntentRef.aidl",
-        "android/os/IPullAtomCallback.aidl",
-        "android/os/IPullAtomResultReceiver.aidl",
-        "android/os/IStatsCompanionService.aidl",
-        "android/os/IStatsd.aidl",
-        "android/os/StatsDimensionsValueParcel.aidl",
-        "android/util/StatsEventParcel.aidl",
-    ],
-    host_supported: true,
-    backend: {
-        java: {
-            enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources
-        },
-        cpp: {
-            enabled: false,
-        },
-        ndk: {
-            enabled: true,
-            apex_available: [
-                // TODO(b/145923087): Remove this once statsd binary is in apex
-                "//apex_available:platform",
-
-                "com.android.os.statsd",
-                "test_com.android.os.statsd",
-            ],
-        },
-    }
-}
diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
deleted file mode 100644
index 000a699..0000000
--- a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.StatsDimensionsValueParcel;
-
-/**
-  * Binder interface to hold a PendingIntent for StatsCompanionService.
-  * {@hide}
-  */
-interface IPendingIntentRef {
-
-    /**
-     * Sends a broadcast to the specified PendingIntent that it should getData now.
-     * This should be only called from StatsCompanionService.
-     */
-     oneway void sendDataBroadcast(long lastReportTimeNs);
-
-    /**
-     * Send a broadcast to the specified PendingIntent notifying it that the list of active configs
-     * has changed. This should be only called from StatsCompanionService.
-     */
-     oneway void sendActiveConfigsChangedBroadcast(in long[] configIds);
-
-     /**
-      * Send a broadcast to the specified PendingIntent, along with the other information
-      * specified. This should only be called from StatsCompanionService.
-      */
-     oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
-                                         long subscriptionRuleId, in String[] cookies,
-                                         in StatsDimensionsValueParcel dimensionsValueParcel);
-}
diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
deleted file mode 100644
index ff0b97b..0000000
--- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.IPullAtomResultReceiver;
-
-/**
-  * Binder interface to pull atoms for the stats service.
-  * {@hide}
-  */
-interface IPullAtomCallback {
-    /**
-     * Initiate a request for a pull for an atom.
-     */
-     oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
-
-}
diff --git a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl b/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
deleted file mode 100644
index 00d026e..0000000
--- a/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
+++ /dev/null
@@ -1,32 +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.os;
-
-import android.util.StatsEventParcel;
-
-/**
-  * Binder interface to pull atoms for the stats service.
-  * {@hide}
-  */
-interface IPullAtomResultReceiver {
-
-    /**
-     * Indicate that a pull request for an atom is complete.
-     */
-     oneway void pullFinished(int atomTag, boolean success, in StatsEventParcel[] output);
-
-}
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
deleted file mode 100644
index d56a4bd..0000000
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
-  * Binder interface to communicate with the Java-based statistics service helper.
-  * {@hide}
-  */
-interface IStatsCompanionService {
-    /**
-     * Tell statscompanion that stastd is up and running.
-     */
-    oneway void statsdReady();
-
-    /**
-      * Register a repeating alarm for pulling to fire at the given timestamp and every
-      * intervalMs thereafter (in ms since epoch).
-      * If polling alarm had already been registered, it will be replaced by new one.
-      * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately,
-      * and alarm is inexact.
-      */
-    oneway void setPullingAlarm(long nextPullTimeMs);
-
-    /** Cancel any repeating pulling alarm. */
-    oneway void cancelPullingAlarm();
-
-    /**
-      * Register an alarm when we want to trigger subscribers at the given
-      * timestamp (in ms since epoch).
-      * If an alarm had already been registered, it will be replaced by new one.
-      */
-    oneway void setAlarmForSubscriberTriggering(long timestampMs);
-
-    /** Cancel any alarm for the purpose of subscriber triggering. */
-    oneway void cancelAlarmForSubscriberTriggering();
-
-    /**
-     * Ask StatsCompanionService if the given permission is allowed for a particular process
-     * and user ID. statsd is incapable of doing this check itself because checkCallingPermission
-     * is not currently supported by libbinder_ndk.
-     */
-    boolean checkPermission(String permission, int pid, int uid);
-}
diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
deleted file mode 100644
index b59a97e..0000000
--- a/apex/statsd/aidl/android/os/IStatsManagerService.aidl
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * Copyright (c) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.app.PendingIntent;
-import android.os.IPullAtomCallback;
-
-/**
-  * Binder interface to communicate with the Java-based statistics service helper.
-  * Contains parcelable objects available only in Java.
-  * {@hide}
-  */
-interface IStatsManagerService {
-
-    /**
-     * Registers the given pending intent for this config key. This intent is invoked when the
-     * memory consumed by the metrics for this configuration approach the pre-defined limits. There
-     * can be at most one listener per config key.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void setDataFetchOperation(long configId, in PendingIntent pendingIntent,
-        in String packageName);
-
-    /**
-     * Removes the data fetch operation for the specified configuration.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeDataFetchOperation(long configId, in String packageName);
-
-    /**
-     * Registers the given pending intent for this packagename. This intent is invoked when the
-     * active status of any of the configs sent by this package changes and will contain a list of
-     * config ids that are currently active. It also returns the list of configs that are currently
-     * active. There can be at most one active configs changed listener per package.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName);
-
-    /**
-     * Removes the active configs changed operation for the specified package name.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeActiveConfigsChangedOperation(in String packageName);
-
-    /**
-     * Set the PendingIntent to be used when broadcasting subscriber
-     * information to the given subscriberId within the given config.
-     *
-     * Suppose that the calling uid has added a config with key configKey, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     *
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent,
-                                in String packageName);
-
-    /**
-     * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
-     * Any broadcasts associated with subscriberId will henceforth not be sent.
-     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntent.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
-
-    /**
-     * Returns the most recently registered experiment IDs.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] getRegisteredExperimentIds();
-
-    /**
-     * Fetches metadata across statsd. Returns byte array representing wire-encoded proto.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    byte[] getMetadata(in String packageName);
-
-    /**
-     * Fetches data for the specified configuration key. Returns a byte array representing proto
-     * wire-encoded of ConfigMetricsReportList.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    byte[] getData(in long key, in String packageName);
-
-    /**
-     * Sets a configuration with the specified config id and subscribes to updates for this
-     * configuration id. Broadcasts will be sent if this configuration needs to be collected.
-     * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is
-     * registered in a separate function.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void addConfiguration(in long configId, in byte[] config, in String packageName);
-
-    /**
-     * Removes the configuration with the matching config id. No-op if this config id does not
-     * exist.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeConfiguration(in long configId, in String packageName);
-
-    /** Tell StatsManagerService to register a puller for the given atom tag with statsd. */
-    oneway void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-            in int[] additiveFields, IPullAtomCallback pullerCallback);
-
-    /** Tell StatsManagerService to unregister the pulller for the given atom tag from statsd. */
-    oneway void unregisterPullAtomCallback(int atomTag);
-}
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
deleted file mode 100644
index 066412a..0000000
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ /dev/null
@@ -1,230 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.IPendingIntentRef;
-import android.os.IPullAtomCallback;
-import android.os.ParcelFileDescriptor;
-
-/**
-  * Binder interface to communicate with the statistics management service.
-  * {@hide}
-  */
-interface IStatsd {
-    /**
-     * Tell the stats daemon that the android system server is up and running.
-     */
-    oneway void systemRunning();
-
-    /**
-     * Tell the stats daemon that the android system has finished booting.
-     */
-    oneway void bootCompleted();
-
-    /**
-     * Tell the stats daemon that the StatsCompanionService is up and running.
-     * Two-way binder call so that caller knows message received.
-     */
-    void statsCompanionReady();
-
-    /**
-     * Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
-     * what stats to poll and initiating the polling.
-     * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
-     */
-    void informPollAlarmFired();
-
-    /**
-     * Tells statsd that it is time to handle periodic alarms. Statsd will be responsible for
-     * determing what alarm subscriber to trigger.
-     * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
-     */
-    void informAlarmForSubscriberTriggeringFired();
-
-    /**
-     * Tells statsd that the device is about to shutdown.
-     */
-    void informDeviceShutdown();
-
-    /**
-     * Inform statsd about a file descriptor for a pipe through which we will pipe version
-     * and package information for each uid.
-     * Versions and package information are supplied via UidData proto where info for each app
-     * is captured in its own element of a repeated ApplicationInfo message.
-     */
-    oneway void informAllUidData(in ParcelFileDescriptor fd);
-
-    /**
-     * Inform statsd what the uid, version, version_string, and installer are for one app that was
-     * updated.
-     */
-    oneway void informOnePackage(in String app, in int uid, in long version,
-        in String version_string, in String installer);
-
-    /**
-     * Inform stats that an app was removed.
-     */
-    oneway void informOnePackageRemoved(in String app, in int uid);
-
-    /**
-     * Fetches data for the specified configuration key. Returns a byte array representing proto
-     * wire-encoded of ConfigMetricsReportList.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    byte[] getData(in long key, int callingUid);
-
-    /**
-     * Fetches metadata across statsd. Returns byte array representing wire-encoded proto.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    byte[] getMetadata();
-
-    /**
-     * Sets a configuration with the specified config id and subscribes to updates for this
-     * configuration key. Broadcasts will be sent if this configuration needs to be collected.
-     * The configuration must be a wire-encoded StatsdConfig. The receiver for this data is
-     * registered in a separate function.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void addConfiguration(in long configId, in byte[] config, in int callingUid);
-
-    /**
-     * Registers the given pending intent for this config key. This intent is invoked when the
-     * memory consumed by the metrics for this configuration approach the pre-defined limits. There
-     * can be at most one listener per config key.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void setDataFetchOperation(long configId, in IPendingIntentRef pendingIntentRef,
-                               int callingUid);
-
-    /**
-     * Removes the data fetch operation for the specified configuration.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void removeDataFetchOperation(long configId, int callingUid);
-
-    /**
-     * Registers the given pending intent for this packagename. This intent is invoked when the
-     * active status of any of the configs sent by this package changes and will contain a list of
-     * config ids that are currently active. It also returns the list of configs that are currently
-     * active. There can be at most one active configs changed listener per package.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    long[] setActiveConfigsChangedOperation(in IPendingIntentRef pendingIntentRef, int callingUid);
-
-    /**
-     * Removes the active configs changed operation for the specified package name.
-     *
-     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
-     */
-    void removeActiveConfigsChangedOperation(int callingUid);
-
-    /**
-     * Removes the configuration with the matching config id. No-op if this config id does not
-     * exist.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void removeConfiguration(in long configId, in int callingUid);
-
-    /**
-     * Set the PendingIntentRef to be used when broadcasting subscriber
-     * information to the given subscriberId within the given config.
-     *
-     * Suppose that the calling uid has added a config with key configId, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     *
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir,
-                                int callingUid);
-
-    /**
-     * Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair.
-     * Any broadcasts associated with subscriberId will henceforth not be sent.
-     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef.
-     *
-     * Requires Manifest.permission.DUMP.
-     */
-    void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid);
-
-    /**
-     * Tell the stats daemon that all the pullers registered during boot have been sent.
-     */
-    oneway void allPullersFromBootRegistered();
-
-    /**
-     * Registers a puller callback function that, when invoked, pulls the data
-     * for the specified atom tag.
-     */
-    oneway void registerPullAtomCallback(int uid, int atomTag, long coolDownMillis,
-                                         long timeoutMillis,in int[] additiveFields,
-                                         IPullAtomCallback pullerCallback);
-
-    /**
-     * Registers a puller callback function that, when invoked, pulls the data
-     * for the specified atom tag.
-     *
-     * Enforces the REGISTER_STATS_PULL_ATOM permission.
-     */
-    oneway void registerNativePullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-                           in int[] additiveFields, IPullAtomCallback pullerCallback);
-
-    /**
-     * Unregisters any pullAtomCallback for the given uid/atom.
-     */
-    oneway void unregisterPullAtomCallback(int uid, int atomTag);
-
-    /**
-     * Unregisters any pullAtomCallback for the given atom + caller.
-     *
-     * Enforces the REGISTER_STATS_PULL_ATOM permission.
-     */
-    oneway void unregisterNativePullAtomCallback(int atomTag);
-
-    /**
-     * The install requires staging.
-     */
-    const int FLAG_REQUIRE_STAGING = 0x01;
-
-    /**
-     * Rollback is enabled with this install.
-     */
-    const int FLAG_ROLLBACK_ENABLED = 0x02;
-
-    /**
-     * Requires low latency monitoring.
-     */
-    const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04;
-
-    /**
-     * Returns the most recently registered experiment IDs.
-     */
-    long[] getRegisteredExperimentIds();
-}
diff --git a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl b/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
deleted file mode 100644
index 05f78d0..0000000
--- a/apex/statsd/aidl/android/os/StatsDimensionsValueParcel.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-package android.os;
-
-/**
- * @hide
- */
-parcelable StatsDimensionsValueParcel {
-    // Field equals atomTag for top level StatsDimensionsValueParcels or
-    // positions in depth (1-indexed) for lower level parcels.
-    int field;
-
-    // Indicator for which type of value is stored. Should be set to one
-    // of the constants in StatsDimensionsValue.java.
-    int valueType;
-
-    String stringValue;
-    int intValue;
-    long longValue;
-    boolean boolValue;
-    float floatValue;
-    StatsDimensionsValueParcel[] tupleValue;
-}
diff --git a/apex/statsd/aidl/android/util/StatsEventParcel.aidl b/apex/statsd/aidl/android/util/StatsEventParcel.aidl
deleted file mode 100644
index add8bfb..0000000
--- a/apex/statsd/aidl/android/util/StatsEventParcel.aidl
+++ /dev/null
@@ -1,8 +0,0 @@
-package android.util;
-
-/**
- * @hide
- */
-parcelable StatsEventParcel {
-    byte[] buffer;
-}
diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json
deleted file mode 100644
index 1d029c6..0000000
--- a/apex/statsd/apex_manifest.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "com.android.os.statsd",
-  "version": 309999900
-}
-
diff --git a/apex/statsd/com.android.os.statsd.avbpubkey b/apex/statsd/com.android.os.statsd.avbpubkey
deleted file mode 100644
index d78af8b..0000000
--- a/apex/statsd/com.android.os.statsd.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apex/statsd/com.android.os.statsd.pem b/apex/statsd/com.android.os.statsd.pem
deleted file mode 100644
index 558e17f..0000000
--- a/apex/statsd/com.android.os.statsd.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA893bbpkivKEiNgfknYBSlzC0csaKU/ddBm5Pb4ZFuab+LQSR
-9DDc5JrsmxyrsrvuwL/zAtMbkyYWzEiUxJtx/w0bw8rC90GoPRSCmxyI0ZK8FuPy
-IAQ7UeNfTWZ485mAUaTSasGIfQ3DY4F0P+aUSijeG3NUY02nALHDMqJX7lXR+mL1
-DUYDg05KB0jxQwlYqBeujTPPiAzEqm3PlBoHuan8/qgK2wdQMTVg/fieUD3lupmV
-Wj2dRZgqfBPA16ZbV4Uo0j0bZSf+fQLiXlU2VJGb5i/FQfjLqMKGABDI0MgK7Sc2
-m4ySpV4g4XKDv/vw6Dw4kwWC7mATEVAkH+q6V7uiZeN6a7w30UMtPI8fPaUvAP3L
-VBjCBIv/3m+CKkWcNxOZ3sQBQl5bS05dxcfiVsBvBLYbvQgC+Wy0Sc3b+1pXFT/E
-uAsbZ4CyVsi1+PAdx3h5e2QAyNCXgZDOcvTUyxY6JLTE0LOVHmI4fJEujBex//Oz
-PCRHvC8K+KiljyQWf/NYrLSD3QGYAjVMtQh7yu2yhzWzgBUxyhuv3rY4ATXsN3bJ
-wW4w7/L/RSLSW5+lp/NoJOD9utbsKTyGMHOY6K8JLOmhv3ORoAEmLYlFTI+FqBi9
-AH1HQEKCyh8Z/bYHLUzGWl6FqAMtcnuintv40BbKyt0/D1ItdbSNKmOZ5rkCAwEA
-AQKCAgAY7ll8mRNADYkd1Pi+UVwgMM6B3WJO6z8LZUOhtyxxqmzZ1VnGiShMBrqh
-sPCsuSHTeswxQbvT81TpVZI/91RUKtbn0VbVSFUWyX4AtY4XPtUT0gHy2/vkh0Y6
-93ruDIdd0Wfhmh+GCV4sUhO8ZKpMWpk6XTQHYuzr2UCHcKlkqElrO6qpzLqXNe3D
-iOWBYPc7WBB0RxO0aPnCIq/SCEc55/MBZdSWR80e+sILtNsagPl3djQaoanub3wI
-a0yPv2YfMHHX7H9cfBY8WYsi8bs4MhqqEcAs2m6XtitU3mJpVcooLJYcmOZ1GYZr
-BfYKLouWcnGmNi4IiLHqVzMaQDkEhAZsRaAXCkoVVrFBedLlmLPpiUIQlINF4vxe
-3IcekTKWyMzkU6h+K8T15MU5mLSqeL2Gji1JIwKJno51FZ9uc++pUJVtfYQmNny8
-8RKvQ1hv/S5yLQKgN+VkNbaWlUoMP73dtUe3m/At71/2Dj7xB0KtcgT1lEMrM1GR
-oynJAJLz/d0n5RUUREwkZZMcA4fQVC7Db6vpK69jPiQMShpZ3JKCEjfYLUuN0slt
-FPhjiR175E0vTRuLoIj4kXNwLLswH0c9zqrKM2S92SCxAV3E4JJGKhUZalvT9s1g
-LrPhMCl6CsOES98T87d3RyAIK0iVRCnRUG3bc+8rzyRd4fzkAQKCAQEA/UjmCSm3
-H46t/1w7YBZPew7SFQOAJe81iDzbonc3fNPD2R8lxtD3MwdvrQ5f9fhT4+uveWNr
-dyBX7ppnissyM3LZRN+7BdeIVVeIPVen6Ou9W2i7q18ZoQx9IpRcZEw5tGJFZaGx
-EmyPN4i1K0ccUkGbBvbXXQ/tcG3wElRpBAc5/TQ8vrpUgHll2/MbYhowx6P9uHv5
-thoyG98X+7Fbg8ikzw5GtyuedXfyX1CpJ7yUQVS2PEaOMXOkZdx2bbWRAYYCpsqB
-dMmjs2PsFhZHu6CpLhlocHbfUiRztCUCaMZJPQXFSVmy8QDMvZEdVLvad9Poi8ny
-lmHVRgxaNbAtIQKCAQEA9nscqRaaO7hIX9bOUxcDbI0486Ws4H0hAFApIN+6/LP4
-hkxey3xWArTYWrvSG1d5GkJAdn99ayWzo2PevmJlrhIJiO1QqYBAk+87cnhwSCmB
-kb0sGkNWcc/xNRy7eqdhyCmVhaUnIbORee+cD6qiu/l2BAclTf2ZARFOGXjhQkvt
-cDbc/9ZR467ceXbiTIU34Be4xnNAY1mo59jvwl9eqxgpefYTqPhcZ7OmlDli77Hd
-XuRfuxLZCscv7A9M5Enc2zwOEP5VwRNwYzYtMm2Yh9CQZxNWC7JVh1Gw5MPFzsGl
-sgEdb4WGneN6PPLQHK7NF0f7wYSNnF0i3XSME9MumQKCAQEA0qMbWydr+TyJC0LC
-xigHtUkgAQXGPsXuePxTk4sdhBwAVcKHgg4qZi+a+gpoV4BLE9LfPU4nAwzM08to
-rI5Lk2nBsnt1Z2hVItQGoy0QoK3b7fbti5ktETf3oRhMtcSGgLLxD5ImVjId8Isq
-T3F15hpVOLdzZxtl1Qg4jKXSJ91yplYY5mzC9Yz/3qkQbsdlJcIFsLS5eG3UmkUw
-Bsr6VmA4X1F6Eb6eqwYzdHz6D+fOS36NhxcODaYkY+myO46xptixv8/NVTiTgQ5q
-OfwRb8Iur/3FUzIoioFyD7Bvjn7ITY1NArEsFS0bF9Nk1yDakKiUThyGN/Xojbac
-FuYKwQKCAQEAxOWJ+qU8phJLdowBHC0ZJiEWasRhep9auoZOpJ01IWOfV6EwZLs5
-dkYDQ1Agwoi5DDn6hu7HQM3IV/CS4mF2OnzcMw7ozc7PR53nTkVZ5LuLbuHAlmZO
-avKjDDucpJmLqjtV34IT5X8t6kt3zqgQAbuBBCy1Jz07ebfaPMzsnWpMDcU1/AW4
-OvrX0wweMOSGwzQP/i/ZMsRQAo2w0gQfeuv9Thk+kU99ebXwjx3co//hCEnFE4s1
-6L8/0AJU+VTr4hJyZi7WUDt4HzkLF+qm22/Hux+eMA/Q9R1UAxtFLCpTdAQiAJGY
-/Q3X+1I434DgAwYU3f1Gpq9cB65vq/KamQKCAQEAjIub5wde/ttHlLALvnOXrbqe
-nUIfWHExMzhul/rkr8fFEJwij2nZUuN2EWUGzBWQQoNXw5QKHLZyPsyFUOa/P2BS
-osnffAa+sumL4k36E71xFdTVV5ExyTXZVB49sPmUpivP9gEucFFqDHKjGsF45dBF
-+DZdykLUIv+/jQUzXGkZ5Wv/r52YUNho4EZdwnlJ2so7cxnsYnjW+c1nlp17tkq5
-DfwktkeD9iFzlaZ66vLoO44luaBm+lC3xM2sHinOTwbk0gvhJAIoLfkOYhpmGc8A
-4W/E1OHfVz6xqVDsMBFhRbQpHNkf8XZNqkIoqHVMTaMOJJlM+lb0+A9B8Bm/XA==
------END RSA PRIVATE KEY-----
diff --git a/apex/statsd/com.android.os.statsd.pk8 b/apex/statsd/com.android.os.statsd.pk8
deleted file mode 100644
index 49910f8..0000000
--- a/apex/statsd/com.android.os.statsd.pk8
+++ /dev/null
Binary files differ
diff --git a/apex/statsd/com.android.os.statsd.x509.pem b/apex/statsd/com.android.os.statsd.x509.pem
deleted file mode 100644
index e7b16b2..0000000
--- a/apex/statsd/com.android.os.statsd.x509.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFDTCCAvWgAwIBAgIUCnta1LAl5fMMLLQx//4zWz9A2A8wDQYJKoZIhvcNAQEL
-BQAwFTETMBEGA1UECgwKR29vZ2xlIExMQzAgFw0xOTA4MTIyMjM5MzBaGA80NzU3
-MDcwODIyMzkzMFowFTETMBEGA1UECgwKR29vZ2xlIExMQzCCAiIwDQYJKoZIhvcN
-AQEBBQADggIPADCCAgoCggIBAOranWZ19jkXCF9WIlXv01tUUvLKMHWKV7X9Earw
-cL7/aax0pFbNJutgyBUiOszbR+0T7quZxz6jACu+6y7iaMJnvMluZsfTi+p2UvQt
-y6Ql7ZUOQ7bVluCFIW5hZ+8d9RrLmZdvX1r4YfF6HufDBkAbj+os+y6407OezJAV
-8EATpemc9gsCC4RJZpwzTs1RUXMD4UoNrLZAE8+7iaJZeBxmz0MAPj92pYc9M7/d
-xInzYvOR08/uEpHt8jlMdVgSQS/FaRlIOIqcGBk3cjkjDlpVATQ4Hyjy+IPQPjTD
-bJUmDJiYeBCyY/pYZQvTQjl8s+fvykTsF9Lfb+E+PhZ0+N8pRi7sUSpisZHSiqaN
-W3oxYWc0YQSuzygHHog8HH/azHX5L805g/+Rwfb/cUF9eJgjq0vrkFnsz4UKgKNV
-hHL90mfqpbc2UvJ8VY8BvIjbsHQ77LrBKlqI9VMPorttpTOuwHHJPKsyN972F0Ul
-lRB6CwFE8csVGWXoNaDZWBv7xTDdbdirmlKDNueg9pw6ksYV2Is9Dv8PxmsZvb+4
-oftC/hb4X1Pudn01PPs9Tx44CwHuVLENUwlDEVzG5zNetsv9kAuCYt3VRVF+NYqj
-NAfLbxCKLe25wGzJrZUEJ1YrYIjpUbfwnttEad/9Pu13DAS7HZwn5vwqEKB/1LlT
-NSUXAgMBAAGjUzBRMB0GA1UdDgQWBBSKElkhJSbzgh8+iysye8SrkmJ62DAfBgNV
-HSMEGDAWgBSKElkhJSbzgh8+iysye8SrkmJ62DAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBCwUAA4ICAQANFGnc2wJBrFbh2nzhl06g4TjPKGRCw365vZ1A3T9O
-jXP0lToHDxB33TpKk6d7zszR1uPphQQxgzhSVZB/jx8q4kWSSoKoF9Dlx7h8rAt+
-2TM5DaBvxrwu5mqOALwQuF81wap1Pl2L2fFHvygCm8b+Ci4iS5vcr0axNnp1rK1b
-vUtRWY4mfxTjJYcgeCVUGskqTb+cCxQZ6Icno6VTKajT1FybRmD3KZJaUuLbNEN+
-IE4nGTMG2WZ5Hl2vR8JJp1sYYn8T3ElMAb0MSNFkqsfI+tToEwGsuJDgYEdtEnzf
-lTycQvn5NhrIZRRN3pqSyWpAU7p9mmyTK0PHMz2D/Rtfb7lE692vXzxCmZND51mc
-YXCCoanV6eZZ7Sbqzh60+5QV38hgFBst5l8CcFaWWSFK9nBWdzS5lhs9lmQ4aiYd
-IE0qsNZgMob+TTP1VW39hu4EDjNmOrKfimM9J2tcPZ5QP01DgETPvAsB7vn2Xz9J
-HGt5ntiSV4W2izDP8viQ1M5NvfdBaUhcnNsE6/sxfU0USRs2hrEp1oiqrv4p6V0P
-qOt7C2/YtJzkrxfsHZAxBUSRHa7LwtzgeiJDUivHn94VnAzSAH8MLx6CzDPQ8HWN
-NiZFxTKfMVyjEmbQ2PalHWB8pWtpdEh7X4rzaqhnLBTis3pGssASgo3ArLIYleAU
-+g==
------END CERTIFICATE-----
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
deleted file mode 100644
index e4299f5..0000000
--- a/apex/statsd/framework/Android.bp
+++ /dev/null
@@ -1,85 +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 {
-    default_visibility: [ ":__pkg__" ]
-}
-
-genrule {
-    name: "statslog-statsd-java-gen",
-    tools: ["stats-log-api-gen"],
-    cmd: "$(location stats-log-api-gen) --java $(out) --module statsd" +
-         " --javaPackage com.android.internal.statsd --javaClass StatsdStatsLog",
-    out: ["com/android/internal/statsd/StatsdStatsLog.java"],
-}
-
-java_library_static {
-    name: "statslog-statsd",
-    srcs: [
-        ":statslog-statsd-java-gen",
-    ],
-    visibility: [
-        "//cts/hostsidetests/statsd/apps:__subpackages__",
-        "//vendor:__subpackages__",
-    ],
-}
-
-filegroup {
-    name: "framework-statsd-sources",
-    srcs: [
-        "java/**/*.java",
-        ":framework-statsd-aidl-sources",
-        ":statslog-statsd-java-gen",
-    ],
-    visibility: [
-        "//frameworks/base", // For the "global" stubs.
-        "//frameworks/base/apex/statsd:__subpackages__",
-        "//packages/modules/StatsD/apex:__subpackages__",
-    ],
-}
-java_sdk_library {
-    name: "framework-statsd",
-    defaults: ["framework-module-defaults"],
-    installable: true,
-
-    srcs: [
-        ":framework-statsd-sources",
-    ],
-
-    permitted_packages: [
-        "android.app",
-        "android.os",
-        "android.util",
-        // From :statslog-statsd-java-gen
-        "com.android.internal.statsd",
-    ],
-
-    api_packages: [
-        "android.app",
-        "android.os",
-        "android.util",
-    ],
-
-    hostdex: true, // for hiddenapi check
-
-    impl_library_visibility: [
-        "//frameworks/base/apex/statsd/framework/test:__subpackages__",
-        "//packages/modules/StatsD/apex/framework/test:__subpackages__",
-    ],
-
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt
deleted file mode 100644
index a655693..0000000
--- a/apex/statsd/framework/api/current.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-// Signature format: 2.0
-package android.util {
-
-  public final class StatsLog {
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]);
-    method public static boolean logEvent(int);
-    method public static boolean logStart(int);
-    method public static boolean logStop(int);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/module-lib-current.txt b/apex/statsd/framework/api/module-lib-current.txt
deleted file mode 100644
index 8b6e217..0000000
--- a/apex/statsd/framework/api/module-lib-current.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Signature format: 2.0
-package android.os {
-
-  public class StatsFrameworkInitializer {
-    method public static void registerServiceWrappers();
-    method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/module-lib-removed.txt b/apex/statsd/framework/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/api/removed.txt b/apex/statsd/framework/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/api/system-current.txt b/apex/statsd/framework/api/system-current.txt
deleted file mode 100644
index 3ea5724..0000000
--- a/apex/statsd/framework/api/system-current.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-// Signature format: 2.0
-package android.app {
-
-  public final class StatsManager {
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
-    method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void clearPullAtomCallback(int);
-    method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getData(long);
-    method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getMetadata();
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] getRegisteredExperimentIds() throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent);
-    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException;
-    method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void setPullAtomCallback(int, @Nullable android.app.StatsManager.PullAtomMetadata, @NonNull java.util.concurrent.Executor, @NonNull android.app.StatsManager.StatsPullAtomCallback);
-    field public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
-    field public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = "android.app.extra.STATS_ACTIVE_CONFIG_KEYS";
-    field public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
-    field public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
-    field public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
-    field public static final String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE";
-    field public static final String EXTRA_STATS_SUBSCRIPTION_ID = "android.app.extra.STATS_SUBSCRIPTION_ID";
-    field public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
-    field public static final int PULL_SKIP = 1; // 0x1
-    field public static final int PULL_SUCCESS = 0; // 0x0
-  }
-
-  public static class StatsManager.PullAtomMetadata {
-    method @Nullable public int[] getAdditiveFields();
-    method public long getCoolDownMillis();
-    method public long getTimeoutMillis();
-  }
-
-  public static class StatsManager.PullAtomMetadata.Builder {
-    ctor public StatsManager.PullAtomMetadata.Builder();
-    method @NonNull public android.app.StatsManager.PullAtomMetadata build();
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setAdditiveFields(@NonNull int[]);
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setCoolDownMillis(long);
-    method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setTimeoutMillis(long);
-  }
-
-  public static interface StatsManager.StatsPullAtomCallback {
-    method public int onPullAtom(int, @NonNull java.util.List<android.util.StatsEvent>);
-  }
-
-  public static class StatsManager.StatsUnavailableException extends android.util.AndroidException {
-    ctor public StatsManager.StatsUnavailableException(String);
-    ctor public StatsManager.StatsUnavailableException(String, Throwable);
-  }
-
-}
-
-package android.os {
-
-  public final class StatsDimensionsValue implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getBooleanValue();
-    method public int getField();
-    method public float getFloatValue();
-    method public int getIntValue();
-    method public long getLongValue();
-    method public String getStringValue();
-    method public java.util.List<android.os.StatsDimensionsValue> getTupleValueList();
-    method public int getValueType();
-    method public boolean isValueType(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BOOLEAN_VALUE_TYPE = 5; // 0x5
-    field @NonNull public static final android.os.Parcelable.Creator<android.os.StatsDimensionsValue> CREATOR;
-    field public static final int FLOAT_VALUE_TYPE = 6; // 0x6
-    field public static final int INT_VALUE_TYPE = 3; // 0x3
-    field public static final int LONG_VALUE_TYPE = 4; // 0x4
-    field public static final int STRING_VALUE_TYPE = 2; // 0x2
-    field public static final int TUPLE_VALUE_TYPE = 7; // 0x7
-  }
-
-}
-
-package android.util {
-
-  public final class StatsEvent {
-    method @NonNull public static android.util.StatsEvent.Builder newBuilder();
-  }
-
-  public static final class StatsEvent.Builder {
-    method @NonNull public android.util.StatsEvent.Builder addBooleanAnnotation(byte, boolean);
-    method @NonNull public android.util.StatsEvent.Builder addIntAnnotation(byte, int);
-    method @NonNull public android.util.StatsEvent build();
-    method @NonNull public android.util.StatsEvent.Builder setAtomId(int);
-    method @NonNull public android.util.StatsEvent.Builder usePooledBuffer();
-    method @NonNull public android.util.StatsEvent.Builder writeAttributionChain(@NonNull int[], @NonNull String[]);
-    method @NonNull public android.util.StatsEvent.Builder writeBoolean(boolean);
-    method @NonNull public android.util.StatsEvent.Builder writeByteArray(@NonNull byte[]);
-    method @NonNull public android.util.StatsEvent.Builder writeFloat(float);
-    method @NonNull public android.util.StatsEvent.Builder writeInt(int);
-    method @NonNull public android.util.StatsEvent.Builder writeKeyValuePairs(@Nullable android.util.SparseIntArray, @Nullable android.util.SparseLongArray, @Nullable android.util.SparseArray<java.lang.String>, @Nullable android.util.SparseArray<java.lang.Float>);
-    method @NonNull public android.util.StatsEvent.Builder writeLong(long);
-    method @NonNull public android.util.StatsEvent.Builder writeString(@NonNull String);
-  }
-
-  public final class StatsLog {
-    method public static void write(@NonNull android.util.StatsEvent);
-    method public static void writeRaw(@NonNull byte[], int);
-  }
-
-}
-
diff --git a/apex/statsd/framework/api/system-removed.txt b/apex/statsd/framework/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/statsd/framework/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java
deleted file mode 100644
index 41803cf..0000000
--- a/apex/statsd/framework/java/android/app/StatsManager.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.app;
-
-import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IPullAtomCallback;
-import android.os.IPullAtomResultReceiver;
-import android.os.IStatsManagerService;
-import android.os.RemoteException;
-import android.os.StatsFrameworkInitializer;
-import android.util.AndroidException;
-import android.util.Log;
-import android.util.StatsEvent;
-import android.util.StatsEventParcel;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * API for statsd clients to send configurations and retrieve data.
- *
- * @hide
- */
-@SystemApi
-public final class StatsManager {
-    private static final String TAG = "StatsManager";
-    private static final boolean DEBUG = false;
-
-    private static final Object sLock = new Object();
-    private final Context mContext;
-
-    @GuardedBy("sLock")
-    private IStatsManagerService mStatsManagerService;
-
-    /**
-     * Long extra of uid that added the relevant stats config.
-     */
-    public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
-    /**
-     * Long extra of the relevant stats config's configKey.
-     */
-    public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
-    /**
-     * Long extra of the relevant statsd_config.proto's Subscription.id.
-     */
-    public static final String EXTRA_STATS_SUBSCRIPTION_ID =
-            "android.app.extra.STATS_SUBSCRIPTION_ID";
-    /**
-     * Long extra of the relevant statsd_config.proto's Subscription.rule_id.
-     */
-    public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID =
-            "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
-    /**
-     *   List<String> of the relevant statsd_config.proto's BroadcastSubscriberDetails.cookie.
-     *   Obtain using {@link android.content.Intent#getStringArrayListExtra(String)}.
-     */
-    public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES =
-            "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
-    /**
-     * Extra of a {@link android.os.StatsDimensionsValue} representing sliced dimension value
-     * information.
-     */
-    public static final String EXTRA_STATS_DIMENSIONS_VALUE =
-            "android.app.extra.STATS_DIMENSIONS_VALUE";
-    /**
-     * Long array extra of the active configs for the uid that added those configs.
-     */
-    public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS =
-            "android.app.extra.STATS_ACTIVE_CONFIG_KEYS";
-
-    /**
-     * Broadcast Action: Statsd has started.
-     * Configurations and PendingIntents can now be sent to it.
-     */
-    public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
-
-    // Pull atom callback return codes.
-    /**
-     * Value indicating that this pull was successful and that the result should be used.
-     *
-     **/
-    public static final int PULL_SUCCESS = 0;
-
-    /**
-     * Value indicating that this pull was unsuccessful and that the result should not be used.
-     **/
-    public static final int PULL_SKIP = 1;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting public static final long DEFAULT_COOL_DOWN_MILLIS = 1_000L; // 1 second.
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting public static final long DEFAULT_TIMEOUT_MILLIS = 2_000L; // 2 seconds.
-
-    /**
-     * Constructor for StatsManagerClient.
-     *
-     * @hide
-     */
-    public StatsManager(Context context) {
-        mContext = context;
-    }
-
-    /**
-     * Adds the given configuration and associates it with the given configKey. If a config with the
-     * given configKey already exists for the caller's uid, it is replaced with the new one.
-     *
-     * @param configKey An arbitrary integer that allows clients to track the configuration.
-     * @param config    Wire-encoded StatsdConfig proto that specifies metrics (and all
-     *                  dependencies eg, conditions and matchers).
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     * @throws IllegalArgumentException if config is not a wire-encoded StatsdConfig proto
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void addConfig(long configKey, byte[] config) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                // can throw IllegalArgumentException
-                service.addConfiguration(configKey, config, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when adding configuration");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to addConfig in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #addConfig(long, byte[])}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean addConfiguration(long configKey, byte[] config) {
-        try {
-            addConfig(configKey, config);
-            return true;
-        } catch (StatsUnavailableException | IllegalArgumentException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Remove a configuration from logging.
-     *
-     * @param configKey Configuration key to remove.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void removeConfig(long configKey) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                service.removeConfiguration(configKey, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when removing configuration");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to removeConfig in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #removeConfig(long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean removeConfiguration(long configKey) {
-        try {
-            removeConfig(configKey);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Set the PendingIntent to be used when broadcasting subscriber information to the given
-     * subscriberId within the given config.
-     * <p>
-     * Suppose that the calling uid has added a config with key configKey, and that in this config
-     * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
-     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
-     * when the anomaly is detected.
-     * <p>
-     * When statsd sends the broadcast, the PendingIntent will used to send an intent with
-     * information of
-     * {@link #EXTRA_STATS_CONFIG_UID},
-     * {@link #EXTRA_STATS_CONFIG_KEY},
-     * {@link #EXTRA_STATS_SUBSCRIPTION_ID},
-     * {@link #EXTRA_STATS_SUBSCRIPTION_RULE_ID},
-     * {@link #EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES}, and
-     * {@link #EXTRA_STATS_DIMENSIONS_VALUE}.
-     * <p>
-     * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. The config must have been added first (via {@link #addConfig}).
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it undoes any previous setting of this subscriberId.
-     * @param configKey     The integer naming the config to which this subscriber is attached.
-     * @param subscriberId  ID of the subscriber, as used in the config.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void setBroadcastSubscriber(
-            PendingIntent pendingIntent, long configKey, long subscriberId)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent != null) {
-                    service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent,
-                            mContext.getOpPackageName());
-                } else {
-                    service.unsetBroadcastSubscriber(configKey, subscriberId,
-                            mContext.getOpPackageName());
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when adding broadcast subscriber",
-                        e);
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean setBroadcastSubscriber(
-            long configKey, long subscriberId, PendingIntent pendingIntent) {
-        try {
-            setBroadcastSubscriber(pendingIntent, configKey, subscriberId);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Registers the operation that is called to retrieve the metrics data. This must be called
-     * each time statsd starts. The config must have been added first (via {@link #addConfig},
-     * although addConfig could have been called on a previous boot). This operation allows
-     * statsd to send metrics data whenever statsd determines that the metrics in memory are
-     * approaching the memory limits. The fetch operation should call {@link #getReports} to fetch
-     * the data, which also deletes the retrieved metrics from statsd's memory.
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it removes any associated pending intent with this configKey.
-     * @param configKey     The integer naming the config to which this operation is attached.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public void setFetchReportsOperation(PendingIntent pendingIntent, long configKey)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent == null) {
-                    service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
-                } else {
-                    service.setDataFetchOperation(configKey, pendingIntent,
-                            mContext.getOpPackageName());
-                }
-
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when registering data listener.");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    /**
-     * Registers the operation that is called whenever there is a change in which configs are
-     * active. This must be called each time statsd starts. This operation allows
-     * statsd to inform clients that they should pull data of the configs that are currently
-     * active. The activeConfigsChangedOperation should set periodic alarms to pull data of configs
-     * that are active and stop pulling data of configs that are no longer active.
-     *
-     * @param pendingIntent the PendingIntent to use when broadcasting info to the subscriber
-     *                      associated with the given subscriberId. May be null, in which case
-     *                      it removes any associated pending intent for this client.
-     * @return A list of configs that are currently active for this client. If the pendingIntent is
-     *         null, this will be an empty list.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @NonNull long[] setActiveConfigsChangedOperation(@Nullable PendingIntent pendingIntent)
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                if (pendingIntent == null) {
-                    service.removeActiveConfigsChangedOperation(mContext.getOpPackageName());
-                    return new long[0];
-                } else {
-                    return service.setActiveConfigsChangedOperation(pendingIntent,
-                            mContext.getOpPackageName());
-                }
-
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager "
-                        + "when registering active configs listener.");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
-        try {
-            setFetchReportsOperation(pendingIntent, configKey);
-            return true;
-        } catch (StatsUnavailableException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Request the data collected for the given configKey.
-     * This getter is destructive - it also clears the retrieved metrics from statsd's memory.
-     *
-     * @param configKey Configuration key to retrieve data from.
-     * @return Serialized ConfigMetricsReportList proto.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public byte[] getReports(long configKey) throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getData(configKey, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when getting data");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getReports in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #getReports(long)}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @Nullable byte[] getData(long configKey) {
-        try {
-            return getReports(configKey);
-        } catch (StatsUnavailableException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Clients can request metadata for statsd. Will contain stats across all configurations but not
-     * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}.
-     * This getter is not destructive and will not reset any metrics/counters.
-     *
-     * @return Serialized StatsdStatsReport proto.
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public byte[] getStatsMetadata() throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getMetadata(mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to connect to statsmanager when getting metadata");
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (SecurityException e) {
-                throw new StatsUnavailableException(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getStatsMetadata in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    // TODO: Temporary for backwards compatibility. Remove.
-    /**
-     * @deprecated Use {@link #getStatsMetadata()}
-     */
-    @Deprecated
-    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
-    public @Nullable byte[] getMetadata() {
-        try {
-            return getStatsMetadata();
-        } catch (StatsUnavailableException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the experiments IDs registered with statsd, or an empty array if there aren't any.
-     *
-     * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
-     */
-    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
-    public long[] getRegisteredExperimentIds()
-            throws StatsUnavailableException {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                return service.getRegisteredExperimentIds();
-            } catch (RemoteException e) {
-                if (DEBUG) {
-                    Log.d(TAG,
-                            "Failed to connect to StatsManagerService when getting "
-                                    + "registered experiment IDs");
-                }
-                throw new StatsUnavailableException("could not connect", e);
-            } catch (IllegalStateException e) {
-                Log.e(TAG, "Failed to getRegisteredExperimentIds in statsmanager");
-                throw new StatsUnavailableException(e.getMessage(), e);
-            }
-        }
-    }
-
-    /**
-     * Sets a callback for an atom when that atom is to be pulled. The stats service will
-     * invoke pullData in the callback when the stats service determines that this atom needs to be
-     * pulled. This method should not be called by third-party apps.
-     *
-     * @param atomTag           The tag of the atom for this puller callback.
-     * @param metadata          Optional metadata specifying the timeout, cool down time, and
-     *                          additive fields for mapping isolated to host uids.
-     * @param executor          The executor in which to run the callback.
-     * @param callback          The callback to be invoked when the stats service pulls the atom.
-     *
-     */
-    @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM)
-    public void setPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull StatsPullAtomCallback callback) {
-        long coolDownMillis =
-                metadata == null ? DEFAULT_COOL_DOWN_MILLIS : metadata.mCoolDownMillis;
-        long timeoutMillis = metadata == null ? DEFAULT_TIMEOUT_MILLIS : metadata.mTimeoutMillis;
-        int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields;
-        if (additiveFields == null) {
-            additiveFields = new int[0];
-        }
-
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                PullAtomCallbackInternal rec =
-                    new PullAtomCallbackInternal(atomTag, callback, executor);
-                service.registerPullAtomCallback(
-                        atomTag, coolDownMillis, timeoutMillis, additiveFields, rec);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Unable to register pull callback", e);
-            }
-        }
-    }
-
-    /**
-     * Clears a callback for an atom when that atom is to be pulled. Note that any ongoing
-     * pulls will still occur. This method should not be called by third-party apps.
-     *
-     * @param atomTag           The tag of the atom of which to unregister
-     *
-     */
-    @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM)
-    public void clearPullAtomCallback(int atomTag) {
-        synchronized (sLock) {
-            try {
-                IStatsManagerService service = getIStatsManagerServiceLocked();
-                service.unregisterPullAtomCallback(atomTag);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Unable to unregister pull atom callback");
-            }
-        }
-    }
-
-    private static class PullAtomCallbackInternal extends IPullAtomCallback.Stub {
-        public final int mAtomId;
-        public final StatsPullAtomCallback mCallback;
-        public final Executor mExecutor;
-
-        PullAtomCallbackInternal(int atomId, StatsPullAtomCallback callback, Executor executor) {
-            mAtomId = atomId;
-            mCallback = callback;
-            mExecutor = executor;
-        }
-
-        @Override
-        public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> {
-                    List<StatsEvent> data = new ArrayList<>();
-                    int successInt = mCallback.onPullAtom(atomTag, data);
-                    boolean success = successInt == PULL_SUCCESS;
-                    StatsEventParcel[] parcels = new StatsEventParcel[data.size()];
-                    for (int i = 0; i < data.size(); i++) {
-                        parcels[i] = new StatsEventParcel();
-                        parcels[i].buffer = data.get(i).getBytes();
-                    }
-                    try {
-                        resultReceiver.pullFinished(atomTag, success, parcels);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId
-                                + " due to TransactionTooLarge. Calling pullFinish with no data");
-                        StatsEventParcel[] emptyData = new StatsEventParcel[0];
-                        try {
-                            resultReceiver.pullFinished(atomTag, /*success=*/false, emptyData);
-                        } catch (RemoteException nestedException) {
-                            Log.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId
-                                    + " with empty payload");
-                        }
-                    }
-                });
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-
-    /**
-     * Metadata required for registering a StatsPullAtomCallback.
-     * All fields are optional, and defaults will be used for fields that are unspecified.
-     *
-     */
-    public static class PullAtomMetadata {
-        private final long mCoolDownMillis;
-        private final long mTimeoutMillis;
-        private final int[] mAdditiveFields;
-
-        // Private Constructor for builder
-        private PullAtomMetadata(long coolDownMillis, long timeoutMillis, int[] additiveFields) {
-            mCoolDownMillis = coolDownMillis;
-            mTimeoutMillis = timeoutMillis;
-            mAdditiveFields = additiveFields;
-        }
-
-        /**
-         *  Builder for PullAtomMetadata.
-         */
-        public static class Builder {
-            private long mCoolDownMillis;
-            private long mTimeoutMillis;
-            private int[] mAdditiveFields;
-
-            /**
-             * Returns a new PullAtomMetadata.Builder object for constructing PullAtomMetadata for
-             * StatsManager#registerPullAtomCallback
-             */
-            public Builder() {
-                mCoolDownMillis = DEFAULT_COOL_DOWN_MILLIS;
-                mTimeoutMillis = DEFAULT_TIMEOUT_MILLIS;
-                mAdditiveFields = null;
-            }
-
-            /**
-             * Set the cool down time of the pull in milliseconds. If two successive pulls are
-             * issued within the cool down, a cached version of the first pull will be used for the
-             * second pull. The minimum allowed cool down is 1 second.
-             */
-            @NonNull
-            public Builder setCoolDownMillis(long coolDownMillis) {
-                mCoolDownMillis = coolDownMillis;
-                return this;
-            }
-
-            /**
-             * Set the maximum time the pull can take in milliseconds. The maximum allowed timeout
-             * is 10 seconds.
-             */
-            @NonNull
-            public Builder setTimeoutMillis(long timeoutMillis) {
-                mTimeoutMillis = timeoutMillis;
-                return this;
-            }
-
-            /**
-             * Set the additive fields of this pulled atom.
-             *
-             * This is only applicable for atoms which have a uid field. When tasks are run in
-             * isolated processes, the data will be attributed to the host uid. Additive fields
-             * will be combined when the non-additive fields are the same.
-             */
-            @NonNull
-            public Builder setAdditiveFields(@NonNull int[] additiveFields) {
-                mAdditiveFields = additiveFields;
-                return this;
-            }
-
-            /**
-             * Builds and returns a PullAtomMetadata object with the values set in the builder and
-             * defaults for unset fields.
-             */
-            @NonNull
-            public PullAtomMetadata build() {
-                return new PullAtomMetadata(mCoolDownMillis, mTimeoutMillis, mAdditiveFields);
-            }
-        }
-
-        /**
-         * Return the cool down time of this pull in milliseconds.
-         */
-        public long getCoolDownMillis() {
-            return mCoolDownMillis;
-        }
-
-        /**
-         * Return the maximum amount of time this pull can take in milliseconds.
-         */
-        public long getTimeoutMillis() {
-            return mTimeoutMillis;
-        }
-
-        /**
-         * Return the additive fields of this pulled atom.
-         *
-         * This is only applicable for atoms that have a uid field. When tasks are run in
-         * isolated processes, the data will be attributed to the host uid. Additive fields
-         * will be combined when the non-additive fields are the same.
-         */
-        @Nullable
-        public int[] getAdditiveFields() {
-            return mAdditiveFields;
-        }
-    }
-
-    /**
-     * Callback interface for pulling atoms requested by the stats service.
-     *
-     */
-    public interface StatsPullAtomCallback {
-        /**
-         * Pull data for the specified atom tag, filling in the provided list of StatsEvent data.
-         * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not.
-         */
-        int onPullAtom(int atomTag, @NonNull List<StatsEvent> data);
-    }
-
-    @GuardedBy("sLock")
-    private IStatsManagerService getIStatsManagerServiceLocked() {
-        if (mStatsManagerService != null) {
-            return mStatsManagerService;
-        }
-        mStatsManagerService = IStatsManagerService.Stub.asInterface(
-                StatsFrameworkInitializer
-                .getStatsServiceManager()
-                .getStatsManagerServiceRegisterer()
-                .get());
-        return mStatsManagerService;
-    }
-
-    /**
-     * Exception thrown when communication with the stats service fails (eg if it is not available).
-     * This might be thrown early during boot before the stats service has started or if it crashed.
-     */
-    public static class StatsUnavailableException extends AndroidException {
-        public StatsUnavailableException(String reason) {
-            super("Failed to connect to statsd: " + reason);
-        }
-
-        public StatsUnavailableException(String reason, Throwable e) {
-            super("Failed to connect to statsd: " + reason, e);
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java b/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
deleted file mode 100644
index 7d9349c..0000000
--- a/apex/statsd/framework/java/android/os/StatsDimensionsValue.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.os;
-
-import android.annotation.SystemApi;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Container for statsd dimension value information, corresponding to a
- * stats_log.proto's DimensionValue.
- *
- * This consists of a field (an int representing a statsd atom field)
- * and a value (which may be one of a number of types).
- *
- * <p>
- * Only a single value is held, and it is necessarily one of the following types:
- * {@link String}, int, long, boolean, float,
- * or tuple (i.e. {@link List} of {@code StatsDimensionsValue}).
- *
- * The type of value held can be retrieved using {@link #getValueType()}, which returns one of the
- * following ints, depending on the type of value:
- * <ul>
- *  <li>{@link #STRING_VALUE_TYPE}</li>
- *  <li>{@link #INT_VALUE_TYPE}</li>
- *  <li>{@link #LONG_VALUE_TYPE}</li>
- *  <li>{@link #BOOLEAN_VALUE_TYPE}</li>
- *  <li>{@link #FLOAT_VALUE_TYPE}</li>
- *  <li>{@link #TUPLE_VALUE_TYPE}</li>
- * </ul>
- * Alternatively, this can be determined using {@link #isValueType(int)} with one of these constants
- * as a parameter.
- * The value itself can be retrieved using the correct get...Value() function for its type.
- *
- * <p>
- * The field is always an int, and always exists; it can be obtained using {@link #getField()}.
- *
- *
- * @hide
- */
-@SystemApi
-public final class StatsDimensionsValue implements Parcelable {
-    private static final String TAG = "StatsDimensionsValue";
-
-    // Values of the value type correspond to stats_log.proto's DimensionValue fields.
-    // Keep constants in sync with frameworks/base/cmds/statsd/src/HashableDimensionKey.cpp.
-    /** Indicates that this holds a String. */
-    public static final int STRING_VALUE_TYPE = 2;
-    /** Indicates that this holds an int. */
-    public static final int INT_VALUE_TYPE = 3;
-    /** Indicates that this holds a long. */
-    public static final int LONG_VALUE_TYPE = 4;
-    /** Indicates that this holds a boolean. */
-    public static final int BOOLEAN_VALUE_TYPE = 5;
-    /** Indicates that this holds a float. */
-    public static final int FLOAT_VALUE_TYPE = 6;
-    /** Indicates that this holds a List of StatsDimensionsValues. */
-    public static final int TUPLE_VALUE_TYPE = 7;
-
-    private final StatsDimensionsValueParcel mInner;
-
-    /**
-     * Creates a {@code StatsDimensionValue} from a parcel.
-     *
-     * @hide
-     */
-    public StatsDimensionsValue(Parcel in) {
-        mInner = StatsDimensionsValueParcel.CREATOR.createFromParcel(in);
-    }
-
-    /**
-     * Creates a {@code StatsDimensionsValue} from a StatsDimensionsValueParcel
-     *
-     * @hide
-     */
-    public StatsDimensionsValue(StatsDimensionsValueParcel parcel) {
-        mInner = parcel;
-    }
-
-    /**
-     * Return the field, i.e. the tag of a statsd atom.
-     *
-     * @return the field
-     */
-    public int getField() {
-        return mInner.field;
-    }
-
-    /**
-     * Retrieve the String held, if any.
-     *
-     * @return the {@link String} held if {@link #getValueType()} == {@link #STRING_VALUE_TYPE},
-     *         null otherwise
-     */
-    public String getStringValue() {
-        if (mInner.valueType == STRING_VALUE_TYPE) {
-            return mInner.stringValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not string.");
-            return null;
-        }
-    }
-
-    /**
-     * Retrieve the int held, if any.
-     *
-     * @return the int held if {@link #getValueType()} == {@link #INT_VALUE_TYPE}, 0 otherwise
-     */
-    public int getIntValue() {
-        if (mInner.valueType == INT_VALUE_TYPE) {
-            return mInner.intValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not int.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the long held, if any.
-     *
-     * @return the long held if {@link #getValueType()} == {@link #LONG_VALUE_TYPE}, 0 otherwise
-     */
-    public long getLongValue() {
-        if (mInner.valueType == LONG_VALUE_TYPE) {
-            return mInner.longValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not long.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the boolean held, if any.
-     *
-     * @return the boolean held if {@link #getValueType()} == {@link #BOOLEAN_VALUE_TYPE},
-     *         false otherwise
-     */
-    public boolean getBooleanValue() {
-        if (mInner.valueType == BOOLEAN_VALUE_TYPE) {
-            return mInner.boolValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not boolean.");
-            return false;
-        }
-    }
-
-    /**
-     * Retrieve the float held, if any.
-     *
-     * @return the float held if {@link #getValueType()} == {@link #FLOAT_VALUE_TYPE}, 0 otherwise
-     */
-    public float getFloatValue() {
-        if (mInner.valueType == FLOAT_VALUE_TYPE) {
-            return mInner.floatValue;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not float.");
-            return 0;
-        }
-    }
-
-    /**
-     * Retrieve the tuple, in the form of a {@link List} of {@link StatsDimensionsValue}, held,
-     * if any.
-     *
-     * @return the {@link List} of {@link StatsDimensionsValue} held
-     *         if {@link #getValueType()} == {@link #TUPLE_VALUE_TYPE},
-     *         null otherwise
-     */
-    public List<StatsDimensionsValue> getTupleValueList() {
-        if (mInner.valueType == TUPLE_VALUE_TYPE) {
-            int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length;
-            List<StatsDimensionsValue> tupleValues = new ArrayList<>(length);
-            for (int i = 0; i < length; i++) {
-                tupleValues.add(new StatsDimensionsValue(mInner.tupleValue[i]));
-            }
-            return tupleValues;
-        } else {
-            Log.w(TAG, "Value type is " + getValueTypeAsString() + ", not tuple.");
-            return null;
-        }
-    }
-
-    /**
-     * Returns the constant representing the type of value stored, namely one of
-     * <ul>
-     *   <li>{@link #STRING_VALUE_TYPE}</li>
-     *   <li>{@link #INT_VALUE_TYPE}</li>
-     *   <li>{@link #LONG_VALUE_TYPE}</li>
-     *   <li>{@link #BOOLEAN_VALUE_TYPE}</li>
-     *   <li>{@link #FLOAT_VALUE_TYPE}</li>
-     *   <li>{@link #TUPLE_VALUE_TYPE}</li>
-     * </ul>
-     *
-     * @return the constant representing the type of value stored
-     */
-    public int getValueType() {
-        return mInner.valueType;
-    }
-
-    /**
-     * Returns whether the type of value stored is equal to the given type.
-     *
-     * @param valueType int representing the type of value stored, as used in {@link #getValueType}
-     * @return true if {@link #getValueType()} is equal to {@code valueType}.
-     */
-    public boolean isValueType(int valueType) {
-        return mInner.valueType == valueType;
-    }
-
-    /**
-     * Returns a String representing the information in this StatsDimensionValue.
-     * No guarantees are made about the format of this String.
-     *
-     * @return String representation
-     *
-     * @hide
-     */
-    // Follows the format of statsd's dimension.h toString.
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(mInner.field);
-        sb.append(":");
-        switch (mInner.valueType) {
-            case STRING_VALUE_TYPE:
-                sb.append(mInner.stringValue);
-                break;
-            case INT_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.intValue));
-                break;
-            case LONG_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.longValue));
-                break;
-            case BOOLEAN_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.boolValue));
-                break;
-            case FLOAT_VALUE_TYPE:
-                sb.append(String.valueOf(mInner.floatValue));
-                break;
-            case TUPLE_VALUE_TYPE:
-                sb.append("{");
-                int length = (mInner.tupleValue == null) ? 0 : mInner.tupleValue.length;
-                for (int i = 0; i < length; i++) {
-                    StatsDimensionsValue child = new StatsDimensionsValue(mInner.tupleValue[i]);
-                    sb.append(child.toString());
-                    sb.append("|");
-                }
-                sb.append("}");
-                break;
-            default:
-                Log.w(TAG, "Incorrect value type");
-                break;
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Parcelable Creator for StatsDimensionsValue.
-     */
-    public static final @android.annotation.NonNull
-            Parcelable.Creator<StatsDimensionsValue> CREATOR = new
-            Parcelable.Creator<StatsDimensionsValue>() {
-                public StatsDimensionsValue createFromParcel(Parcel in) {
-                    return new StatsDimensionsValue(in);
-                }
-
-                public StatsDimensionsValue[] newArray(int size) {
-                    return new StatsDimensionsValue[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        mInner.writeToParcel(out, flags);
-    }
-
-    /**
-     * Returns a string representation of the type of value stored.
-     */
-    private String getValueTypeAsString() {
-        switch (mInner.valueType) {
-            case STRING_VALUE_TYPE:
-                return "string";
-            case INT_VALUE_TYPE:
-                return "int";
-            case LONG_VALUE_TYPE:
-                return "long";
-            case BOOLEAN_VALUE_TYPE:
-                return "boolean";
-            case FLOAT_VALUE_TYPE:
-                return "float";
-            case TUPLE_VALUE_TYPE:
-                return "tuple";
-            default:
-                return "unknown";
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java b/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
deleted file mode 100644
index 8dc9123..0000000
--- a/apex/statsd/framework/java/android/os/StatsFrameworkInitializer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.os;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.SystemApi.Client;
-import android.app.StatsManager;
-import android.app.SystemServiceRegistry;
-import android.content.Context;
-
-/**
- * Class for performing registration for all stats services
- *
- * @hide
- */
-@SystemApi(client = Client.MODULE_LIBRARIES)
-public class StatsFrameworkInitializer {
-    private StatsFrameworkInitializer() {
-    }
-
-    private static volatile StatsServiceManager sStatsServiceManager;
-
-    /**
-     * Sets an instance of {@link StatsServiceManager} that allows
-     * the statsd mainline module to register/obtain stats binder services. This is called
-     * by the platform during the system initialization.
-     *
-     * @param statsServiceManager instance of {@link StatsServiceManager} that allows
-     * the statsd mainline module to register/obtain statsd binder services.
-     */
-    public static void setStatsServiceManager(
-            @NonNull StatsServiceManager statsServiceManager) {
-        if (sStatsServiceManager != null) {
-            throw new IllegalStateException("setStatsServiceManager called twice!");
-        }
-
-        if (statsServiceManager == null) {
-            throw new NullPointerException("statsServiceManager is null");
-        }
-
-        sStatsServiceManager = statsServiceManager;
-    }
-
-    /** @hide */
-    public static StatsServiceManager getStatsServiceManager() {
-        return sStatsServiceManager;
-    }
-
-    /**
-     * Called by {@link SystemServiceRegistry}'s static initializer and registers all statsd
-     * services to {@link Context}, so that {@link Context#getSystemService} can return them.
-     *
-     * @throws IllegalStateException if this is called from anywhere besides
-     * {@link SystemServiceRegistry}
-     */
-    public static void registerServiceWrappers() {
-        SystemServiceRegistry.registerContextAwareService(
-                Context.STATS_MANAGER,
-                StatsManager.class,
-                context -> new StatsManager(context)
-        );
-    }
-}
diff --git a/apex/statsd/framework/java/android/util/StatsEvent.java b/apex/statsd/framework/java/android/util/StatsEvent.java
deleted file mode 100644
index 8be5c63..0000000
--- a/apex/statsd/framework/java/android/util/StatsEvent.java
+++ /dev/null
@@ -1,879 +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.util;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.SystemClock;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
-
-/**
- * StatsEvent builds and stores the buffer sent over the statsd socket.
- * This class defines and encapsulates the socket protocol.
- *
- * <p>Usage:</p>
- * <pre>
- *      // Pushed event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .usePooledBuffer()
- *          .build();
- *      StatsLog.write(statsEvent);
- *
- *      // Pulled event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .build();
- * </pre>
- * @hide
- **/
-@SystemApi
-public final class StatsEvent {
-    // Type Ids.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_INT = 0x00;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LONG = 0x01;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_STRING = 0x02;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LIST = 0x03;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_FLOAT = 0x04;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BOOLEAN = 0x05;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BYTE_ARRAY = 0x06;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_OBJECT = 0x07;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ERRORS = 0x0F;
-
-    // Error flags.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_TIMESTAMP = 0x1;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_ATOM_ID = 0x2;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_OVERFLOW = 0x4;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_FIELDS = 0x200;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000;
-
-    // Size limits.
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ANNOTATION_COUNT = 15;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ATTRIBUTION_NODES = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_NUM_ELEMENTS = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_KEY_VALUE_PAIRS = 127;
-
-    private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
-
-    // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
-    // See android_util_StatsLog.cpp.
-    private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
-
-    private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB
-
-    private final int mAtomId;
-    private final byte[] mPayload;
-    private Buffer mBuffer;
-    private final int mNumBytes;
-
-    private StatsEvent(final int atomId, @Nullable final Buffer buffer,
-            @NonNull final byte[] payload, final int numBytes) {
-        mAtomId = atomId;
-        mBuffer = buffer;
-        mPayload = payload;
-        mNumBytes = numBytes;
-    }
-
-    /**
-     * Returns a new StatsEvent.Builder for building StatsEvent object.
-     **/
-    @NonNull
-    public static StatsEvent.Builder newBuilder() {
-        return new StatsEvent.Builder(Buffer.obtain());
-    }
-
-    /**
-     * Get the atom Id of the atom encoded in this StatsEvent object.
-     *
-     * @hide
-     **/
-    public int getAtomId() {
-        return mAtomId;
-    }
-
-    /**
-     * Get the byte array that contains the encoded payload that can be sent to statsd.
-     *
-     * @hide
-     **/
-    @NonNull
-    public byte[] getBytes() {
-        return mPayload;
-    }
-
-    /**
-     * Get the number of bytes used to encode the StatsEvent payload.
-     *
-     * @hide
-     **/
-    public int getNumBytes() {
-        return mNumBytes;
-    }
-
-    /**
-     * Recycle resources used by this StatsEvent object.
-     * No actions should be taken on this StatsEvent after release() is called.
-     *
-     * @hide
-     **/
-    public void release() {
-        if (mBuffer != null) {
-            mBuffer.release();
-            mBuffer = null;
-        }
-    }
-
-    /**
-     * Builder for constructing a StatsEvent object.
-     *
-     * <p>This class defines and encapsulates the socket encoding for the buffer.
-     * The write methods must be called in the same order as the order of fields in the
-     * atom definition.</p>
-     *
-     * <p>setAtomId() can be called anytime before build().</p>
-     *
-     * <p>Example:</p>
-     * <pre>
-     *     // Atom definition.
-     *     message MyAtom {
-     *         optional int32 field1 = 1;
-     *         optional int64 field2 = 2;
-     *         optional string field3 = 3 [(annotation1) = true];
-     *     }
-     *
-     *     // StatsEvent construction for pushed event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .usePooledBuffer()
-     *         .build();
-     *
-     *     // StatsEvent construction for pulled event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .build();
-     * </pre>
-     **/
-    public static final class Builder {
-        // Fixed positions.
-        private static final int POS_NUM_ELEMENTS = 1;
-        private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
-        private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
-
-        private final Buffer mBuffer;
-        private long mTimestampNs;
-        private int mAtomId;
-        private byte mCurrentAnnotationCount;
-        private int mPos;
-        private int mPosLastField;
-        private byte mLastType;
-        private int mNumElements;
-        private int mErrorMask;
-        private boolean mUsePooledBuffer = false;
-
-        private Builder(final Buffer buffer) {
-            mBuffer = buffer;
-            mCurrentAnnotationCount = 0;
-            mAtomId = 0;
-            mTimestampNs = SystemClock.elapsedRealtimeNanos();
-            mNumElements = 0;
-
-            // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
-            mPos = 0;
-            writeTypeId(TYPE_OBJECT);
-
-            // Write timestamp.
-            mPos = POS_TIMESTAMP_NS;
-            writeLong(mTimestampNs);
-        }
-
-        /**
-         * Sets the atom id for this StatsEvent.
-         *
-         * This should be called immediately after StatsEvent.newBuilder()
-         * and should only be called once.
-         * Not calling setAtomId will result in ERROR_NO_ATOM_ID.
-         * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION.
-         **/
-        @NonNull
-        public Builder setAtomId(final int atomId) {
-            if (0 == mAtomId) {
-                mAtomId = atomId;
-
-                if (1 == mNumElements) { // Only timestamp is written so far.
-                    writeInt(atomId);
-                } else {
-                    // setAtomId called out of order.
-                    mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION;
-                }
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a boolean field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeBoolean(final boolean value) {
-            // Write boolean typeId byte followed by boolean byte representation.
-            writeTypeId(TYPE_BOOLEAN);
-            mPos += mBuffer.putBoolean(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write an integer field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeInt(final int value) {
-            // Write integer typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_INT);
-            mPos += mBuffer.putInt(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a long field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeLong(final long value) {
-            // Write long typeId byte followed by 8-byte representation of value.
-            writeTypeId(TYPE_LONG);
-            mPos += mBuffer.putLong(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a float field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeFloat(final float value) {
-            // Write float typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_FLOAT);
-            mPos += mBuffer.putFloat(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a String field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeString(@NonNull final String value) {
-            // Write String typeId byte, followed by 4-byte representation of number of bytes
-            // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
-            final byte[] valueBytes = stringToBytes(value);
-            writeByteArray(valueBytes, TYPE_STRING);
-            return this;
-        }
-
-        /**
-         * Write a byte array field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeByteArray(@NonNull final byte[] value) {
-            // Write byte array typeId byte, followed by 4-byte representation of number of bytes
-            // in value, followed by the actual byte array.
-            writeByteArray(value, TYPE_BYTE_ARRAY);
-            return this;
-        }
-
-        private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
-            writeTypeId(typeId);
-            final int numBytes = value.length;
-            mPos += mBuffer.putInt(mPos, numBytes);
-            mPos += mBuffer.putByteArray(mPos, value);
-            mNumElements++;
-        }
-
-        /**
-         * Write an attribution chain field to this StatsEvent.
-         *
-         * The sizes of uids and tags must be equal. The AttributionNode at position i is
-         * made up of uids[i] and tags[i].
-         *
-         * @param uids array of uids in the attribution nodes.
-         * @param tags array of tags in the attribution nodes.
-         **/
-        @NonNull
-        public Builder writeAttributionChain(
-                @NonNull final int[] uids, @NonNull final String[] tags) {
-            final byte numUids = (byte) uids.length;
-            final byte numTags = (byte) tags.length;
-
-            if (numUids != numTags) {
-                mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
-            } else if (numUids > MAX_ATTRIBUTION_NODES) {
-                mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
-            } else {
-                // Write attribution chain typeId byte, followed by 1-byte representation of
-                // number of attribution nodes, followed by encoding of each attribution node.
-                writeTypeId(TYPE_ATTRIBUTION_CHAIN);
-                mPos += mBuffer.putByte(mPos, numUids);
-                for (int i = 0; i < numUids; i++) {
-                    // Each uid is encoded as 4-byte representation of its int value.
-                    mPos += mBuffer.putInt(mPos, uids[i]);
-
-                    // Each tag is encoded as 4-byte representation of number of bytes in its
-                    // UTF-8 encoding, followed by the actual UTF-8 bytes.
-                    final byte[] tagBytes = stringToBytes(tags[i]);
-                    mPos += mBuffer.putInt(mPos, tagBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, tagBytes);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write KeyValuePairsAtom entries to this StatsEvent.
-         *
-         * @param intMap Integer key-value pairs.
-         * @param longMap Long key-value pairs.
-         * @param stringMap String key-value pairs.
-         * @param floatMap Float key-value pairs.
-         **/
-        @NonNull
-        public Builder writeKeyValuePairs(
-                @Nullable final SparseIntArray intMap,
-                @Nullable final SparseLongArray longMap,
-                @Nullable final SparseArray<String> stringMap,
-                @Nullable final SparseArray<Float> floatMap) {
-            final int intMapSize = null == intMap ? 0 : intMap.size();
-            final int longMapSize = null == longMap ? 0 : longMap.size();
-            final int stringMapSize = null == stringMap ? 0 : stringMap.size();
-            final int floatMapSize = null == floatMap ? 0 : floatMap.size();
-            final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
-
-            if (totalCount > MAX_KEY_VALUE_PAIRS) {
-                mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
-            } else {
-                writeTypeId(TYPE_KEY_VALUE_PAIRS);
-                mPos += mBuffer.putByte(mPos, (byte) totalCount);
-
-                for (int i = 0; i < intMapSize; i++) {
-                    final int key = intMap.keyAt(i);
-                    final int value = intMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_INT);
-                    mPos += mBuffer.putInt(mPos, value);
-                }
-
-                for (int i = 0; i < longMapSize; i++) {
-                    final int key = longMap.keyAt(i);
-                    final long value = longMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_LONG);
-                    mPos += mBuffer.putLong(mPos, value);
-                }
-
-                for (int i = 0; i < stringMapSize; i++) {
-                    final int key = stringMap.keyAt(i);
-                    final String value = stringMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_STRING);
-                    final byte[] valueBytes = stringToBytes(value);
-                    mPos += mBuffer.putInt(mPos, valueBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, valueBytes);
-                }
-
-                for (int i = 0; i < floatMapSize; i++) {
-                    final int key = floatMap.keyAt(i);
-                    final float value = floatMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_FLOAT);
-                    mPos += mBuffer.putFloat(mPos, value);
-                }
-
-                mNumElements++;
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a boolean annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addBooleanAnnotation(
-                final byte annotationId, final boolean value) {
-            // Ensure there's a field written to annotate.
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
-                mPos += mBuffer.putBoolean(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Write an integer annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addIntAnnotation(final byte annotationId, final int value) {
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
-         * This should be called for pushed events to reduce memory allocations and garbage
-         * collections.
-         **/
-        @NonNull
-        public Builder usePooledBuffer() {
-            mUsePooledBuffer = true;
-            mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos);
-            return this;
-        }
-
-        /**
-         * Builds a StatsEvent object with values entered in this Builder.
-         **/
-        @NonNull
-        public StatsEvent build() {
-            if (0L == mTimestampNs) {
-                mErrorMask |= ERROR_NO_TIMESTAMP;
-            }
-            if (0 == mAtomId) {
-                mErrorMask |= ERROR_NO_ATOM_ID;
-            }
-            if (mBuffer.hasOverflowed()) {
-                mErrorMask |= ERROR_OVERFLOW;
-            }
-            if (mNumElements > MAX_NUM_ELEMENTS) {
-                mErrorMask |= ERROR_TOO_MANY_FIELDS;
-            }
-
-            if (0 == mErrorMask) {
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
-            } else {
-                // Write atom id and error mask. Overwrite any annotations for atom Id.
-                mPos = POS_ATOM_ID;
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, mAtomId);
-                mPos += mBuffer.putByte(mPos, TYPE_ERRORS);
-                mPos += mBuffer.putInt(mPos, mErrorMask);
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
-            }
-
-            final int size = mPos;
-
-            if (mUsePooledBuffer) {
-                return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
-            } else {
-                // Create a copy of the buffer with the required number of bytes.
-                final byte[] payload = new byte[size];
-                System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);
-
-                // Return Buffer instance to the pool.
-                mBuffer.release();
-
-                return new StatsEvent(mAtomId, null, payload, size);
-            }
-        }
-
-        private void writeTypeId(final byte typeId) {
-            mPosLastField = mPos;
-            mLastType = typeId;
-            mCurrentAnnotationCount = 0;
-            final byte encodedId = (byte) (typeId & 0x0F);
-            mPos += mBuffer.putByte(mPos, encodedId);
-        }
-
-        private void writeAnnotationCount() {
-            // Use first 4 bits for annotation count and last 4 bits for typeId.
-            final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
-            mBuffer.putByte(mPosLastField, encodedId);
-        }
-
-        @NonNull
-        private static byte[] stringToBytes(@Nullable final String value) {
-            return (null == value ? "" : value).getBytes(UTF_8);
-        }
-    }
-
-    private static final class Buffer {
-        private static Object sLock = new Object();
-
-        @GuardedBy("sLock")
-        private static Buffer sPool;
-
-        private byte[] mBytes = new byte[MAX_PUSH_PAYLOAD_SIZE];
-        private boolean mOverflow = false;
-        private int mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-
-        @NonNull
-        private static Buffer obtain() {
-            final Buffer buffer;
-            synchronized (sLock) {
-                buffer = null == sPool ? new Buffer() : sPool;
-                sPool = null;
-            }
-            buffer.reset();
-            return buffer;
-        }
-
-        private Buffer() {
-        }
-
-        @NonNull
-        private byte[] getBytes() {
-            return mBytes;
-        }
-
-        private void release() {
-            // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under.
-            if (mBytes.length <= MAX_PUSH_PAYLOAD_SIZE) {
-                synchronized (sLock) {
-                    if (null == sPool) {
-                        sPool = this;
-                    }
-                }
-            }
-        }
-
-        private void reset() {
-            mOverflow = false;
-            mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-        }
-
-        private void setMaxSize(final int maxSize, final int numBytesWritten) {
-            mMaxSize = maxSize;
-            if (numBytesWritten > maxSize) {
-                mOverflow = true;
-            }
-        }
-
-        private boolean hasOverflowed() {
-            return mOverflow;
-        }
-
-        /**
-         * Checks for available space in the byte array.
-         *
-         * @param index starting position in the buffer to start the check.
-         * @param numBytes number of bytes to check from index.
-         * @return true if space is available, false otherwise.
-         **/
-        private boolean hasEnoughSpace(final int index, final int numBytes) {
-            final int totalBytesNeeded = index + numBytes;
-
-            if (totalBytesNeeded > mMaxSize) {
-                mOverflow = true;
-                return false;
-            }
-
-            // Expand buffer if needed.
-            if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) {
-                int newSize = mBytes.length;
-                do {
-                    newSize *= 2;
-                } while (newSize <= totalBytesNeeded);
-
-                if (newSize > mMaxSize) {
-                    newSize = mMaxSize;
-                }
-
-                mBytes = Arrays.copyOf(mBytes, newSize);
-            }
-
-            return true;
-        }
-
-        /**
-         * Writes a byte into the buffer.
-         *
-         * @param index position in the buffer where the byte is written.
-         * @param value the byte to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByte(final int index, final byte value) {
-            if (hasEnoughSpace(index, Byte.BYTES)) {
-                mBytes[index] = (byte) (value);
-                return Byte.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a boolean into the buffer.
-         *
-         * @param index position in the buffer where the boolean is written.
-         * @param value the boolean to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putBoolean(final int index, final boolean value) {
-            return putByte(index, (byte) (value ? 1 : 0));
-        }
-
-        /**
-         * Writes an integer into the buffer.
-         *
-         * @param index position in the buffer where the integer is written.
-         * @param value the integer to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putInt(final int index, final int value) {
-            if (hasEnoughSpace(index, Integer.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                return Integer.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a long into the buffer.
-         *
-         * @param index position in the buffer where the long is written.
-         * @param value the long to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putLong(final int index, final long value) {
-            if (hasEnoughSpace(index, Long.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                mBytes[index + 4] = (byte) (value >> 32);
-                mBytes[index + 5] = (byte) (value >> 40);
-                mBytes[index + 6] = (byte) (value >> 48);
-                mBytes[index + 7] = (byte) (value >> 56);
-                return Long.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a float into the buffer.
-         *
-         * @param index position in the buffer where the float is written.
-         * @param value the float to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putFloat(final int index, final float value) {
-            return putInt(index, Float.floatToIntBits(value));
-        }
-
-        /**
-         * Copies a byte array into the buffer.
-         *
-         * @param index position in the buffer where the byte array is copied.
-         * @param value the byte array to copy.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByteArray(final int index, @NonNull final byte[] value) {
-            final int numBytes = value.length;
-            if (hasEnoughSpace(index, numBytes)) {
-                System.arraycopy(value, 0, mBytes, index, numBytes);
-                return numBytes;
-            }
-            return 0;
-        }
-    }
-}
diff --git a/apex/statsd/framework/java/android/util/StatsLog.java b/apex/statsd/framework/java/android/util/StatsLog.java
deleted file mode 100644
index 0a9f4eb..0000000
--- a/apex/statsd/framework/java/android/util/StatsLog.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.os.IStatsd;
-import android.os.Process;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.statsd.StatsdStatsLog;
-
-/**
- * StatsLog provides an API for developers to send events to statsd. The events can be used to
- * define custom metrics inside statsd.
- */
-public final class StatsLog {
-
-    // Load JNI library
-    static {
-        System.loadLibrary("stats_jni");
-    }
-    private static final String TAG = "StatsLog";
-    private static final boolean DEBUG = false;
-    private static final int EXPERIMENT_IDS_FIELD_ID = 1;
-
-    private StatsLog() {
-    }
-
-    /**
-     * Logs a start event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStart(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START);
-        return true;
-    }
-
-    /**
-     * Logs a stop event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStop(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP);
-        return true;
-    }
-
-    /**
-     * Logs an event that does not represent a start or stop boundary.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logEvent(int label) {
-        int callingUid = Process.myUid();
-        StatsdStatsLog.write(
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-                callingUid,
-                label,
-                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
-        return true;
-    }
-
-    /**
-     * Logs an event for binary push for module updates.
-     *
-     * @param trainName        name of install train.
-     * @param trainVersionCode version code of the train.
-     * @param options          optional flags about this install.
-     *                         The last 3 bits indicate options:
-     *                             0x01: FLAG_REQUIRE_STAGING
-     *                             0x02: FLAG_ROLLBACK_ENABLED
-     *                             0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR
-     * @param state            current install state. Defined as State enums in
-     *                         BinaryPushStateChanged atom in
-     *                         frameworks/base/cmds/statsd/src/atoms.proto
-     * @param experimentIds    experiment ids.
-     * @return True if the log request was sent to statsd.
-     */
-    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
-    public static boolean logBinaryPushStateChanged(@NonNull String trainName,
-            long trainVersionCode, int options, int state,
-            @NonNull long[] experimentIds) {
-        ProtoOutputStream proto = new ProtoOutputStream();
-        for (long id : experimentIds) {
-            proto.write(
-                    ProtoOutputStream.FIELD_TYPE_INT64
-                    | ProtoOutputStream.FIELD_COUNT_REPEATED
-                    | EXPERIMENT_IDS_FIELD_ID,
-                    id);
-        }
-        StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED,
-                trainName,
-                trainVersionCode,
-                (options & IStatsd.FLAG_REQUIRE_STAGING) > 0,
-                (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0,
-                (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0,
-                state,
-                proto.getBytes(),
-                0,
-                0,
-                false);
-        return true;
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @hide
-     */
-    // TODO(b/144935988): Mark deprecated.
-    @SystemApi
-    public static void writeRaw(@NonNull byte[] buffer, int size) {
-        // TODO(b/144935988): make this no-op once clients have migrated to StatsEvent.
-        writeImpl(buffer, size, 0);
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @param atomId    The id of the atom to which the event belongs.
-     */
-    private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
-
-    /**
-     * Write an event to stats log using the raw format encapsulated in StatsEvent.
-     * After writing to stats log, release() is called on the StatsEvent object.
-     * No further action should be taken on the StatsEvent object following this call.
-     *
-     * @param statsEvent    The StatsEvent object containing the encoded buffer of data to write.
-     * @hide
-     */
-    @SystemApi
-    public static void write(@NonNull final StatsEvent statsEvent) {
-        writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
-        statsEvent.release();
-    }
-
-    private static void enforceDumpCallingPermission(Context context) {
-        context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission.");
-    }
-
-    private static void enforcesageStatsCallingPermission(Context context) {
-        context.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
-                "Need PACKAGE_USAGE_STATS permission.");
-    }
-}
diff --git a/apex/statsd/framework/test/Android.bp b/apex/statsd/framework/test/Android.bp
deleted file mode 100644
index 5cc5647..0000000
--- a/apex/statsd/framework/test/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-android_test {
-    name: "FrameworkStatsdTest",
-    sdk_version: "module_current",
-    srcs: [ "**/*.java" ],
-    manifest: "AndroidManifest.xml",
-    static_libs: [
-        "androidx.test.rules",
-        "truth-prebuilt",
-    ],
-    libs: [
-        "android.test.runner.stubs",
-        "android.test.base.stubs",
-        "framework-statsd.impl",
-    ],
-    test_suites: [
-        "device-tests",
-        "mts",
-    ],
-}
diff --git a/apex/statsd/framework/test/AndroidManifest.xml b/apex/statsd/framework/test/AndroidManifest.xml
deleted file mode 100644
index 8f89d23..0000000
--- a/apex/statsd/framework/test/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.os.statsd.framework.test"
-        >
-
-    <instrumentation
-            android:name="androidx.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.os.statsd.framework.test"
-            android:label="Framework Statsd Tests" />
-
-</manifest>
diff --git a/apex/statsd/framework/test/AndroidTest.xml b/apex/statsd/framework/test/AndroidTest.xml
deleted file mode 100644
index fb51915..0000000
--- a/apex/statsd/framework/test/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs Tests for Statsd.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="FrameworkStatsdTest.apk" />
-        <option name="install-arg" value="-g" />
-    </target_preparer>
-
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="mts" />
-    <option name="test-tag" value="FrameworkStatsdTest" />
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.os.statsd.framework.test" />
-        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
-        <option name="hidden-api-checks" value="false"/>
-    </test>
-
-    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
-        <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
-    </object>
-</configuration>
\ No newline at end of file
diff --git a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java b/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java
deleted file mode 100644
index fd386bd..0000000
--- a/apex/statsd/framework/test/src/android/app/PullAtomMetadataTest.java
+++ /dev/null
@@ -1,85 +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.app;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager.PullAtomMetadata;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class PullAtomMetadataTest {
-
-    @Test
-    public void testEmpty() {
-        PullAtomMetadata metadata = new PullAtomMetadata.Builder().build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetTimeoutMillis() {
-        long timeoutMillis = 500L;
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setTimeoutMillis(timeoutMillis).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetCoolDownMillis() {
-        long coolDownMillis = 10_000L;
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setCoolDownMillis(coolDownMillis).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis);
-        assertThat(metadata.getAdditiveFields()).isNull();
-    }
-
-    @Test
-    public void testSetAdditiveFields() {
-        int[] fields = {2, 4, 6};
-        PullAtomMetadata metadata =
-                new PullAtomMetadata.Builder().setAdditiveFields(fields).build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_MILLIS);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_MILLIS);
-        assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
-    }
-
-    @Test
-    public void testSetAllElements() {
-        long timeoutMillis = 300L;
-        long coolDownMillis = 9572L;
-        int[] fields = {3, 2};
-        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
-                .setTimeoutMillis(timeoutMillis)
-                .setCoolDownMillis(coolDownMillis)
-                .setAdditiveFields(fields)
-                .build();
-        assertThat(metadata.getTimeoutMillis()).isEqualTo(timeoutMillis);
-        assertThat(metadata.getCoolDownMillis()).isEqualTo(coolDownMillis);
-        assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
-    }
-}
diff --git a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java b/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java
deleted file mode 100644
index db25911..0000000
--- a/apex/statsd/framework/test/src/android/os/StatsDimensionsValueTest.java
+++ /dev/null
@@ -1,115 +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.os;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public final class StatsDimensionsValueTest {
-
-    @Test
-    public void testConversionFromStructuredParcel() {
-        int tupleField = 100; // atom id
-        String stringValue = "Hello";
-        int intValue = 123;
-        long longValue = 123456789L;
-        float floatValue = 1.1f;
-        boolean boolValue = true;
-
-        // Construct structured parcel
-        StatsDimensionsValueParcel sdvp = new StatsDimensionsValueParcel();
-        sdvp.field = tupleField;
-        sdvp.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE;
-        sdvp.tupleValue = new StatsDimensionsValueParcel[5];
-
-        for (int i = 0; i < 5; i++) {
-            sdvp.tupleValue[i] = new StatsDimensionsValueParcel();
-            sdvp.tupleValue[i].field = i + 1;
-        }
-
-        sdvp.tupleValue[0].valueType = StatsDimensionsValue.STRING_VALUE_TYPE;
-        sdvp.tupleValue[1].valueType = StatsDimensionsValue.INT_VALUE_TYPE;
-        sdvp.tupleValue[2].valueType = StatsDimensionsValue.LONG_VALUE_TYPE;
-        sdvp.tupleValue[3].valueType = StatsDimensionsValue.FLOAT_VALUE_TYPE;
-        sdvp.tupleValue[4].valueType = StatsDimensionsValue.BOOLEAN_VALUE_TYPE;
-
-        sdvp.tupleValue[0].stringValue = stringValue;
-        sdvp.tupleValue[1].intValue = intValue;
-        sdvp.tupleValue[2].longValue = longValue;
-        sdvp.tupleValue[3].floatValue = floatValue;
-        sdvp.tupleValue[4].boolValue = boolValue;
-
-        // Convert to StatsDimensionsValue and check result
-        StatsDimensionsValue sdv = new StatsDimensionsValue(sdvp);
-
-        assertThat(sdv.getField()).isEqualTo(tupleField);
-        assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE);
-        List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList();
-        assertThat(sdvChildren.size()).isEqualTo(5);
-
-        for (int i = 0; i < 5; i++) {
-            assertThat(sdvChildren.get(i).getField()).isEqualTo(i + 1);
-        }
-
-        assertThat(sdvChildren.get(0).getValueType())
-              .isEqualTo(StatsDimensionsValue.STRING_VALUE_TYPE);
-        assertThat(sdvChildren.get(1).getValueType())
-              .isEqualTo(StatsDimensionsValue.INT_VALUE_TYPE);
-        assertThat(sdvChildren.get(2).getValueType())
-              .isEqualTo(StatsDimensionsValue.LONG_VALUE_TYPE);
-        assertThat(sdvChildren.get(3).getValueType())
-              .isEqualTo(StatsDimensionsValue.FLOAT_VALUE_TYPE);
-        assertThat(sdvChildren.get(4).getValueType())
-              .isEqualTo(StatsDimensionsValue.BOOLEAN_VALUE_TYPE);
-
-        assertThat(sdvChildren.get(0).getStringValue()).isEqualTo(stringValue);
-        assertThat(sdvChildren.get(1).getIntValue()).isEqualTo(intValue);
-        assertThat(sdvChildren.get(2).getLongValue()).isEqualTo(longValue);
-        assertThat(sdvChildren.get(3).getFloatValue()).isEqualTo(floatValue);
-        assertThat(sdvChildren.get(4).getBooleanValue()).isEqualTo(boolValue);
-
-        // Ensure that StatsDimensionsValue and StatsDimensionsValueParcel are
-        // parceled equivalently
-        Parcel sdvpParcel = Parcel.obtain();
-        Parcel sdvParcel = Parcel.obtain();
-        sdvp.writeToParcel(sdvpParcel, 0);
-        sdv.writeToParcel(sdvParcel, 0);
-        assertThat(sdvpParcel.dataSize()).isEqualTo(sdvParcel.dataSize());
-    }
-
-    @Test
-    public void testNullTupleArray() {
-        int tupleField = 100; // atom id
-
-        StatsDimensionsValueParcel parcel = new StatsDimensionsValueParcel();
-        parcel.field = tupleField;
-        parcel.valueType = StatsDimensionsValue.TUPLE_VALUE_TYPE;
-        parcel.tupleValue = null;
-
-        StatsDimensionsValue sdv = new StatsDimensionsValue(parcel);
-        assertThat(sdv.getField()).isEqualTo(tupleField);
-        assertThat(sdv.getValueType()).isEqualTo(StatsDimensionsValue.TUPLE_VALUE_TYPE);
-        List<StatsDimensionsValue> sdvChildren = sdv.getTupleValueList();
-        assertThat(sdvChildren.size()).isEqualTo(0);
-    }
-}
diff --git a/apex/statsd/framework/test/src/android/util/StatsEventTest.java b/apex/statsd/framework/test/src/android/util/StatsEventTest.java
deleted file mode 100644
index 8d26369..0000000
--- a/apex/statsd/framework/test/src/android/util/StatsEventTest.java
+++ /dev/null
@@ -1,818 +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.util;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.os.SystemClock;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.google.common.collect.Range;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Random;
-
-/**
- * Internal tests for {@link StatsEvent}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class StatsEventTest {
-
-    @Test
-    public void testNoFields() {
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        final int expectedAtomId = 0;
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask")
-                .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testOnlyAtomId() {
-        final int expectedAtomId = 109;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(2);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testIntBooleanIntInt() {
-        final int expectedAtomId = 109;
-        final int field1 = 1;
-        final boolean field2 = true;
-        final int field3 = 3;
-        final int field4 = 4;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeInt(field1)
-                .writeBoolean(field2)
-                .writeInt(field3)
-                .writeInt(field4)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(6);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-
-        assertWithMessage("Second field is not Boolean")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(1);
-
-        assertWithMessage("Third field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 3")
-                .that(buffer.getInt()).isEqualTo(field3);
-
-        assertWithMessage("Fourth field is not Int")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect field 4")
-                .that(buffer.getInt()).isEqualTo(field4);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testStringFloatByteArray() {
-        final int expectedAtomId = 109;
-        final String field1 = "Str 1";
-        final float field2 = 9.334f;
-        final byte[] field3 = new byte[] { 56, 23, 89, -120 };
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeString(field1)
-                .writeFloat(field2)
-                .writeByteArray(field3)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(5);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not String")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
-
-        final String field1Actual = getStringFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 1")
-                .that(field1Actual).isEqualTo(field1);
-
-        assertWithMessage("Second field is not Float")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.getFloat()).isEqualTo(field2);
-
-        assertWithMessage("Third field is not byte array")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
-
-        final byte[] field3Actual = getByteArrayFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 3")
-                .that(field3Actual).isEqualTo(field3);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testAttributionChainLong() {
-        final int expectedAtomId = 109;
-        final int[] uids = new int[] { 1, 2, 3, 4, 5 };
-        final String[] tags = new String[] { "1", "2", "3", "4", "5" };
-        final long field2 = -230909823L;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeAttributionChain(uids, tags)
-                .writeLong(field2)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not Attribution Chain")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN);
-
-        assertWithMessage("Incorrect number of attribution nodes")
-                .that(buffer.get()).isEqualTo((byte) uids.length);
-
-        for (int i = 0; i < tags.length; i++) {
-            assertWithMessage("Incorrect uid in Attribution Chain")
-                    .that(buffer.getInt()).isEqualTo(uids[i]);
-
-            final String tag = getStringFromByteBuffer(buffer);
-            assertWithMessage("Incorrect tag in Attribution Chain")
-                    .that(tag).isEqualTo(tags[i]);
-        }
-
-        assertWithMessage("Second field is not Long")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.getLong()).isEqualTo(field2);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testKeyValuePairs() {
-        final int expectedAtomId = 109;
-        final SparseIntArray intMap = new SparseIntArray();
-        final SparseLongArray longMap = new SparseLongArray();
-        final SparseArray<String> stringMap = new SparseArray<>();
-        final SparseArray<Float> floatMap = new SparseArray<>();
-        intMap.put(1, -1);
-        intMap.put(2, -2);
-        stringMap.put(3, "abc");
-        stringMap.put(4, "2h");
-        floatMap.put(9, -234.344f);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("First field is not KeyValuePairs")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS);
-
-        assertWithMessage("Incorrect number of key value pairs")
-                .that(buffer.get()).isEqualTo(
-                        (byte) (intMap.size() + longMap.size() + stringMap.size()
-                                + floatMap.size()));
-
-        for (int i = 0; i < intMap.size(); i++) {
-            assertWithMessage("Incorrect key in intMap")
-                    .that(buffer.getInt()).isEqualTo(intMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_INT in intMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-            assertWithMessage("Incorrect value in intMap")
-                    .that(buffer.getInt()).isEqualTo(intMap.valueAt(i));
-        }
-
-        for (int i = 0; i < longMap.size(); i++) {
-            assertWithMessage("Incorrect key in longMap")
-                    .that(buffer.getInt()).isEqualTo(longMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_LONG in longMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-            assertWithMessage("Incorrect value in longMap")
-                    .that(buffer.getLong()).isEqualTo(longMap.valueAt(i));
-        }
-
-        for (int i = 0; i < stringMap.size(); i++) {
-            assertWithMessage("Incorrect key in stringMap")
-                    .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_STRING in stringMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
-            final String value = getStringFromByteBuffer(buffer);
-            assertWithMessage("Incorrect value in stringMap")
-                    .that(value).isEqualTo(stringMap.valueAt(i));
-        }
-
-        for (int i = 0; i < floatMap.size(); i++) {
-            assertWithMessage("Incorrect key in floatMap")
-                    .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i));
-            assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap")
-                    .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
-            assertWithMessage("Incorrect value in floatMap")
-                    .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i));
-        }
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testSingleAnnotations() {
-        final int expectedAtomId = 109;
-        final int field1 = 1;
-        final byte field1AnnotationId = 45;
-        final boolean field1AnnotationValue = false;
-        final boolean field2 = true;
-        final byte field2AnnotationId = 1;
-        final int field2AnnotationValue = 23;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .writeInt(field1)
-                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
-                .writeBoolean(field2)
-                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        final byte field1Header = buffer.get();
-        final int field1AnnotationValueCount = field1Header >> 4;
-        final byte field1Type = (byte) (field1Header & 0x0F);
-        assertWithMessage("First field is not Int")
-                .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("First field annotation count is wrong")
-                .that(field1AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-        assertWithMessage("First field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationId);
-        assertWithMessage("First field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("First field's annotation value is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
-
-        final byte field2Header = buffer.get();
-        final int field2AnnotationValueCount = field2Header >> 4;
-        final byte field2Type = (byte) (field2Header & 0x0F);
-        assertWithMessage("Second field is not boolean")
-                .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("Second field annotation count is wrong")
-                .that(field2AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
-        assertWithMessage("Second field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field2AnnotationId);
-        assertWithMessage("Second field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Second field's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testAtomIdAnnotations() {
-        final int expectedAtomId = 109;
-        final byte atomAnnotationId = 84;
-        final int atomAnnotationValue = 9;
-        final int field1 = 1;
-        final byte field1AnnotationId = 45;
-        final boolean field1AnnotationValue = false;
-        final boolean field2 = true;
-        final byte field2AnnotationId = 1;
-        final int field2AnnotationValue = 23;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .setAtomId(expectedAtomId)
-                .addIntAnnotation(atomAnnotationId, atomAnnotationValue)
-                .writeInt(field1)
-                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
-                .writeBoolean(field2)
-                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(4);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        final byte atomIdHeader = buffer.get();
-        final int atomIdAnnotationValueCount = atomIdHeader >> 4;
-        final byte atomIdValueType = (byte) (atomIdHeader & 0x0F);
-        assertWithMessage("Second element is not atom id")
-                .that(atomIdValueType).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Atom id annotation count is wrong")
-                .that(atomIdAnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-        assertWithMessage("Atom id's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(atomAnnotationId);
-        assertWithMessage("Atom id's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Atom id's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(atomAnnotationValue);
-
-        final byte field1Header = buffer.get();
-        final int field1AnnotationValueCount = field1Header >> 4;
-        final byte field1Type = (byte) (field1Header & 0x0F);
-        assertWithMessage("First field is not Int")
-                .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("First field annotation count is wrong")
-                .that(field1AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 1")
-                .that(buffer.getInt()).isEqualTo(field1);
-        assertWithMessage("First field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationId);
-        assertWithMessage("First field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("First field's annotation value is wrong")
-                .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
-
-        final byte field2Header = buffer.get();
-        final int field2AnnotationValueCount = field2Header >> 4;
-        final byte field2Type = (byte) (field2Header & 0x0F);
-        assertWithMessage("Second field is not boolean")
-                .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
-        assertWithMessage("Second field annotation count is wrong")
-                .that(field2AnnotationValueCount).isEqualTo(1);
-        assertWithMessage("Incorrect field 2")
-                .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
-        assertWithMessage("Second field's annotation id is wrong")
-                .that(buffer.get()).isEqualTo(field2AnnotationId);
-        assertWithMessage("Second field's annotation type is wrong")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-        assertWithMessage("Second field's annotation value is wrong")
-                .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testSetAtomIdNotCalledImmediately() {
-        final int expectedAtomId = 109;
-        final int field1 = 25;
-        final boolean field2 = true;
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                .writeInt(field1)
-                .setAtomId(expectedAtomId)
-                .writeBoolean(field2)
-                .usePooledBuffer()
-                .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get()).isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id")
-                .that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_ATOM_ID_INVALID_POSITION should be the only error in the mask")
-                .that(errorMask).isEqualTo(StatsEvent.ERROR_ATOM_ID_INVALID_POSITION);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testLargePulledEvent() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[10 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent =
-                StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not byte array")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
-
-        final byte[] field1Actual = getByteArrayFromByteBuffer(buffer);
-        assertWithMessage("Incorrect field 1").that(field1Actual).isEqualTo(field1);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testPulledEventOverflow() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[50 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent =
-                StatsEvent.newBuilder().setAtomId(expectedAtomId).writeByteArray(field1).build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask")
-                .that(errorMask)
-                .isEqualTo(StatsEvent.ERROR_OVERFLOW);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    @Test
-    public void testPushedEventOverflow() {
-        final int expectedAtomId = 10_020;
-        byte[] field1 = new byte[10 * 1024];
-        new Random().nextBytes(field1);
-
-        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
-        final StatsEvent statsEvent = StatsEvent.newBuilder()
-                                              .setAtomId(expectedAtomId)
-                                              .writeByteArray(field1)
-                                              .usePooledBuffer()
-                                              .build();
-        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
-
-        assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
-
-        final ByteBuffer buffer =
-                ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
-
-        assertWithMessage("Root element in buffer is not TYPE_OBJECT")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_OBJECT);
-
-        assertWithMessage("Incorrect number of elements in root object")
-                .that(buffer.get())
-                .isEqualTo(3);
-
-        assertWithMessage("First element is not timestamp")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_LONG);
-
-        assertWithMessage("Incorrect timestamp")
-                .that(buffer.getLong())
-                .isIn(Range.closed(minTimestamp, maxTimestamp));
-
-        assertWithMessage("Second element is not atom id")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_INT);
-
-        assertWithMessage("Incorrect atom id").that(buffer.getInt()).isEqualTo(expectedAtomId);
-
-        assertWithMessage("Third element is not errors type")
-                .that(buffer.get())
-                .isEqualTo(StatsEvent.TYPE_ERRORS);
-
-        final int errorMask = buffer.getInt();
-
-        assertWithMessage("ERROR_OVERFLOW should be the only error in the error mask")
-                .that(errorMask)
-                .isEqualTo(StatsEvent.ERROR_OVERFLOW);
-
-        assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
-
-        statsEvent.release();
-    }
-
-    private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) {
-        final int numBytes = buffer.getInt();
-        byte[] bytes = new byte[numBytes];
-        buffer.get(bytes);
-        return bytes;
-    }
-
-    private static String getStringFromByteBuffer(final ByteBuffer buffer) {
-        final byte[] bytes = getByteArrayFromByteBuffer(buffer);
-        return new String(bytes, UTF_8);
-    }
-}
diff --git a/apex/statsd/jni/android_util_StatsLog.cpp b/apex/statsd/jni/android_util_StatsLog.cpp
deleted file mode 100644
index 71ce949..0000000
--- a/apex/statsd/jni/android_util_StatsLog.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_NAMESPACE "StatsLog.tag."
-#define LOG_TAG "StatsLog_println"
-
-#include <jni.h>
-#include <log/log.h>
-#include <nativehelper/scoped_local_ref.h>
-#include "stats_buffer_writer.h"
-
-namespace android {
-
-static void android_util_StatsLog_write(JNIEnv* env, jobject clazz, jbyteArray buf, jint size,
-        jint atomId) {
-    if (buf == NULL) {
-        return;
-    }
-    jint actualSize = env->GetArrayLength(buf);
-    if (actualSize < size) {
-        return;
-    }
-
-    jbyte* bufferArray = env->GetByteArrayElements(buf, NULL);
-    if (bufferArray == NULL) {
-        return;
-    }
-
-    write_buffer_to_statsd((void*) bufferArray, size, atomId);
-
-    env->ReleaseByteArrayElements(buf, bufferArray, 0);
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "writeImpl", "([BII)V", (void*) android_util_StatsLog_write },
-};
-
-int register_android_util_StatsLog(JNIEnv* env)
-{
-    static const char* kStatsLogClass = "android/util/StatsLog";
-
-    ScopedLocalRef<jclass> cls(env, env->FindClass(kStatsLogClass));
-    if (cls.get() == nullptr) {
-        ALOGE("jni statsd registration failure, class not found '%s'", kStatsLogClass);
-        return JNI_ERR;
-    }
-
-    const jint count = sizeof(gMethods) / sizeof(gMethods[0]);
-    int status = env->RegisterNatives(cls.get(), gMethods, count);
-    if (status < 0) {
-        ALOGE("jni statsd registration failure, status: %d", status);
-        return JNI_ERR;
-    }
-    return JNI_VERSION_1_4;
-}
-
-}; // namespace android
-
-/*
- * JNI Initialization
- */
-jint JNI_OnLoad(JavaVM* jvm, void* reserved) {
-    JNIEnv* e;
-
-    ALOGV("statsd : loading JNI\n");
-    // Check JNI version
-    if (jvm->GetEnv((void**)&e, JNI_VERSION_1_4)) {
-        ALOGE("JNI version mismatch error");
-        return JNI_ERR;
-    }
-
-    return android::register_android_util_StatsLog(e);
-}
diff --git a/apex/statsd/service/Android.bp b/apex/statsd/service/Android.bp
deleted file mode 100644
index df0ccfc..0000000
--- a/apex/statsd/service/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-filegroup {
-    name: "service-statsd-sources",
-    srcs: [
-        "java/**/*.java",
-    ],
-}
-
-java_library {
-    name: "service-statsd",
-    srcs: [ ":service-statsd-sources" ],
-    sdk_version: "system_server_current",
-    libs: [
-        "framework-annotations-lib",
-        "framework-statsd",
-    ],
-    plugins: ["java_api_finder"],
-    apex_available: [
-        "com.android.os.statsd",
-        "test_com.android.os.statsd",
-    ],
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
deleted file mode 100644
index dc477a5..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.stats;
-
-import android.app.PendingIntent;
-import android.app.StatsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IPendingIntentRef;
-import android.os.Process;
-import android.os.StatsDimensionsValue;
-import android.os.StatsDimensionsValueParcel;
-import android.util.Log;
-
-import com.android.server.SystemService;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * @hide
- */
-public class StatsCompanion {
-    private static final String TAG = "StatsCompanion";
-    private static final boolean DEBUG = false;
-
-    private static final int AID_STATSD = 1066;
-
-    private static final String STATS_COMPANION_SERVICE = "statscompanion";
-    private static final String STATS_MANAGER_SERVICE = "statsmanager";
-
-    static void enforceStatsdCallingUid() {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return;
-        }
-        if (Binder.getCallingUid() != AID_STATSD) {
-            throw new SecurityException("Not allowed to access StatsCompanion");
-        }
-    }
-
-    /**
-     * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}.
-     */
-    public static final class Lifecycle extends SystemService {
-        private StatsCompanionService mStatsCompanionService;
-        private StatsManagerService mStatsManagerService;
-
-        public Lifecycle(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onStart() {
-            mStatsCompanionService = new StatsCompanionService(getContext());
-            mStatsManagerService = new StatsManagerService(getContext());
-            mStatsCompanionService.setStatsManagerService(mStatsManagerService);
-            mStatsManagerService.setStatsCompanionService(mStatsCompanionService);
-
-            try {
-                publishBinderService(STATS_COMPANION_SERVICE, mStatsCompanionService);
-                if (DEBUG) Log.d(TAG, "Published " + STATS_COMPANION_SERVICE);
-                publishBinderService(STATS_MANAGER_SERVICE, mStatsManagerService);
-                if (DEBUG) Log.d(TAG, "Published " + STATS_MANAGER_SERVICE);
-            } catch (Exception e) {
-                Log.e(TAG, "Failed to publishBinderService", e);
-            }
-        }
-
-        @Override
-        public void onBootPhase(int phase) {
-            super.onBootPhase(phase);
-            if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
-                mStatsCompanionService.systemReady();
-            }
-            if (phase == PHASE_BOOT_COMPLETED) {
-                mStatsCompanionService.bootCompleted();
-            }
-        }
-    }
-
-    /**
-     * Wrapper for {@link PendingIntent}. Allows Statsd to send PendingIntents.
-     */
-    public static class PendingIntentRef extends IPendingIntentRef.Stub {
-
-        private static final String TAG = "PendingIntentRef";
-
-        /**
-         * The last report time is provided with each intent registered to
-         * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
-         * statsd is requesting the client to retrieve the same statsd data. The last report time
-         * corresponds to the last_report_elapsed_nanos that will provided in the current
-         * ConfigMetricsReport, and this timestamp also corresponds to the
-         * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport.
-         */
-        private static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
-        private static final int CODE_DATA_BROADCAST = 1;
-        private static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
-        private static final int CODE_SUBSCRIBER_BROADCAST = 1;
-
-        private final PendingIntent mPendingIntent;
-        private final Context mContext;
-
-        public PendingIntentRef(PendingIntent pendingIntent, Context context) {
-            mPendingIntent = pendingIntent;
-            mContext = context;
-        }
-
-        @Override
-        public void sendDataBroadcast(long lastReportTimeNs) {
-            enforceStatsdCallingUid();
-            Intent intent = new Intent();
-            intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
-            try {
-                mPendingIntent.send(mContext, CODE_DATA_BROADCAST, intent, null, null);
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "Unable to send PendingIntent");
-            }
-        }
-
-        @Override
-        public void sendActiveConfigsChangedBroadcast(long[] configIds) {
-            enforceStatsdCallingUid();
-            Intent intent = new Intent();
-            intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
-            try {
-                mPendingIntent.send(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
-                if (DEBUG) {
-                    Log.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
-                }
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "Unable to send active configs changed broadcast using PendingIntent");
-            }
-        }
-
-        @Override
-        public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
-                long subscriptionRuleId, String[] cookies,
-                StatsDimensionsValueParcel dimensionsValueParcel) {
-            enforceStatsdCallingUid();
-            StatsDimensionsValue dimensionsValue = new StatsDimensionsValue(dimensionsValueParcel);
-            Intent intent =
-                    new Intent()
-                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
-                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configId)
-                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
-                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID,
-                                    subscriptionRuleId)
-                            .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
-
-            ArrayList<String> cookieList = new ArrayList<>(cookies.length);
-            cookieList.addAll(Arrays.asList(cookies));
-            intent.putStringArrayListExtra(
-                    StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
-
-            if (DEBUG) {
-                Log.d(TAG,
-                        String.format(
-                                "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
-                                configUid, configId, subscriptionId, subscriptionRuleId,
-                                Arrays.toString(cookies),
-                                dimensionsValue));
-            }
-            try {
-                mPendingIntent.send(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
-            } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG,
-                        "Unable to send using PendingIntent from uid " + configUid
-                                + "; presumably it had been cancelled.");
-            }
-        }
-    }
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
deleted file mode 100644
index fbda86f..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ /dev/null
@@ -1,770 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.stats;
-
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
-
-import android.app.AlarmManager;
-import android.app.AlarmManager.OnAlarmListener;
-import android.app.StatsManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IStatsCompanionService;
-import android.os.IStatsd;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.StatsFrameworkInitializer;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Helper service for statsd (the native stats management service in cmds/statsd/).
- * Used for registering and receiving alarms on behalf of statsd.
- *
- * @hide
- */
-public class StatsCompanionService extends IStatsCompanionService.Stub {
-
-    private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
-
-    public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
-    public static final String CONFIG_DIR = "/data/misc/stats-service";
-
-    static final String TAG = "StatsCompanionService";
-    static final boolean DEBUG = false;
-    /**
-     * Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto
-     * to be used in ProtoOutputStream.
-     */
-    private static final int APPLICATION_INFO_FIELD_ID = 1;
-    private static final int UID_FIELD_ID = 1;
-    private static final int VERSION_FIELD_ID = 2;
-    private static final int VERSION_STRING_FIELD_ID = 3;
-    private static final int PACKAGE_NAME_FIELD_ID = 4;
-    private static final int INSTALLER_FIELD_ID = 5;
-
-    public static final int DEATH_THRESHOLD = 10;
-
-    static final class CompanionHandler extends Handler {
-        CompanionHandler(Looper looper) {
-            super(looper);
-        }
-    }
-
-    private final Context mContext;
-    private final AlarmManager mAlarmManager;
-    @GuardedBy("sStatsdLock")
-    private static IStatsd sStatsd;
-    private static final Object sStatsdLock = new Object();
-
-    private final OnAlarmListener mPullingAlarmListener;
-    private final OnAlarmListener mPeriodicAlarmListener;
-
-    private StatsManagerService mStatsManagerService;
-
-    @GuardedBy("sStatsdLock")
-    private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
-    @GuardedBy("sStatsdLock")
-    private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
-    private final CompanionHandler mHandler;
-
-    // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle.
-    private AtomicBoolean mBootCompleted = new AtomicBoolean(false);
-
-    public StatsCompanionService(Context context) {
-        super();
-        mContext = context;
-        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
-        HandlerThread handlerThread = new HandlerThread(TAG);
-        handlerThread.start();
-        mHandler = new CompanionHandler(handlerThread.getLooper());
-
-        mPullingAlarmListener = new PullingAlarmListener(context);
-        mPeriodicAlarmListener = new PeriodicAlarmListener(context);
-    }
-
-    private final static int[] toIntArray(List<Integer> list) {
-        int[] ret = new int[list.size()];
-        for (int i = 0; i < ret.length; i++) {
-            ret[i] = list.get(i);
-        }
-        return ret;
-    }
-
-    private final static long[] toLongArray(List<Long> list) {
-        long[] ret = new long[list.size()];
-        for (int i = 0; i < ret.length; i++) {
-            ret[i] = list.get(i);
-        }
-        return ret;
-    }
-
-    /**
-     * Non-blocking call to retrieve a reference to statsd
-     *
-     * @return IStatsd object if statsd is ready, null otherwise.
-     */
-    private static IStatsd getStatsdNonblocking() {
-        synchronized (sStatsdLock) {
-            return sStatsd;
-        }
-    }
-
-    private static void informAllUids(Context context) {
-        ParcelFileDescriptor[] fds;
-        try {
-            fds = ParcelFileDescriptor.createPipe();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to create a pipe to send uid map data.", e);
-            return;
-        }
-        HandlerThread backgroundThread = new HandlerThread(
-                "statsCompanionService.bg", THREAD_PRIORITY_BACKGROUND);
-        backgroundThread.start();
-        Handler handler = new Handler(backgroundThread.getLooper());
-        handler.post(() -> {
-            UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-            PackageManager pm = context.getPackageManager();
-            final List<UserHandle> users = um.getUserHandles(true);
-            if (DEBUG) {
-                Log.d(TAG, "Iterating over " + users.size() + " userHandles.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                return;
-            }
-            try {
-                statsd.informAllUidData(fds[0]);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send uid map to statsd");
-            }
-            try {
-                fds[0].close();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to close the read side of the pipe.", e);
-            }
-            final ParcelFileDescriptor writeFd = fds[1];
-            FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd);
-            try {
-                ProtoOutputStream output = new ProtoOutputStream(fout);
-                int numRecords = 0;
-                // Add in all the apps for every user/profile.
-                for (UserHandle userHandle : users) {
-                    List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle);
-                    for (int j = 0; j < packagesPlusApex.size(); j++) {
-                        if (packagesPlusApex.get(j).applicationInfo != null) {
-                            String installer;
-                            try {
-                                installer = pm.getInstallerPackageName(
-                                        packagesPlusApex.get(j).packageName);
-                            } catch (IllegalArgumentException e) {
-                                installer = "";
-                            }
-                            long applicationInfoToken =
-                                    output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
-                                            | ProtoOutputStream.FIELD_COUNT_REPEATED
-                                            | APPLICATION_INFO_FIELD_ID);
-                            output.write(ProtoOutputStream.FIELD_TYPE_INT32
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
-                                    packagesPlusApex.get(j).applicationInfo.uid);
-                            output.write(ProtoOutputStream.FIELD_TYPE_INT64
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | VERSION_FIELD_ID,
-                                    packagesPlusApex.get(j).getLongVersionCode());
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | VERSION_STRING_FIELD_ID,
-                                    packagesPlusApex.get(j).versionName);
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                    | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                    | PACKAGE_NAME_FIELD_ID, packagesPlusApex.get(j).packageName);
-                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
-                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
-                                            | INSTALLER_FIELD_ID,
-                                    installer == null ? "" : installer);
-                            numRecords++;
-                            output.end(applicationInfoToken);
-                        }
-                    }
-                }
-                output.flush();
-                if (DEBUG) {
-                    Log.d(TAG, "Sent data for " + numRecords + " apps");
-                }
-            } finally {
-                FileUtils.closeQuietly(fout);
-                backgroundThread.quit();
-                backgroundThread.interrupt();
-            }
-        });
-    }
-
-    private static List<PackageInfo> getAllPackagesWithApex(PackageManager pm,
-            UserHandle userHandle) {
-        // We want all the uninstalled packages because uninstalled package uids can still be logged
-        // to statsd.
-        List<PackageInfo> allPackages = new ArrayList<>(
-                pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
-                                | PackageManager.MATCH_ANY_USER,
-                        userHandle.getIdentifier()));
-        // We make a second query to package manager for the apex modules because package manager
-        // returns both installed and uninstalled apexes with
-        // PackageManager.MATCH_UNINSTALLED_PACKAGES flag. We only want active apexes because
-        // inactive apexes can conflict with active ones.
-        for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.MATCH_APEX)) {
-            if (packageInfo.isApex) {
-                allPackages.add(packageInfo);
-            }
-        }
-        return allPackages;
-    }
-
-    private static class WakelockThread extends Thread {
-        private final PowerManager.WakeLock mWl;
-        private final Runnable mRunnable;
-
-        WakelockThread(Context context, String wakelockName, Runnable runnable) {
-            PowerManager powerManager = (PowerManager)
-                    context.getSystemService(Context.POWER_SERVICE);
-            mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName);
-            mRunnable = runnable;
-        }
-        @Override
-        public void run() {
-            try {
-                mRunnable.run();
-            } finally {
-                mWl.release();
-            }
-        }
-        @Override
-        public void start() {
-            mWl.acquire();
-            super.start();
-        }
-    }
-
-    private final static class AppUpdateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            /**
-             * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
-             * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
-             * If we can't find the value for EXTRA_REPLACING, we default to false.
-             */
-            if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)
-                    && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-                return; // Keep only replacing or normal add and remove.
-            }
-            if (DEBUG) Log.d(TAG, "StatsCompanionService noticed an app was updated.");
-            synchronized (sStatsdLock) {
-                if (sStatsd == null) {
-                    Log.w(TAG, "Could not access statsd to inform it of an app update");
-                    return;
-                }
-                try {
-                    if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
-                        Bundle b = intent.getExtras();
-                        int uid = b.getInt(Intent.EXTRA_UID);
-                        boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                        if (!replacing) {
-                            // Don't bother sending an update if we're right about to get another
-                            // intent for the new version that's added.
-                            String app = intent.getData().getSchemeSpecificPart();
-                            sStatsd.informOnePackageRemoved(app, uid);
-                        }
-                    } else {
-                        PackageManager pm = context.getPackageManager();
-                        Bundle b = intent.getExtras();
-                        int uid = b.getInt(Intent.EXTRA_UID);
-                        String app = intent.getData().getSchemeSpecificPart();
-                        PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
-                        String installer;
-                        try {
-                            installer = pm.getInstallerPackageName(app);
-                        } catch (IllegalArgumentException e) {
-                            installer = "";
-                        }
-                        sStatsd.informOnePackage(
-                                app,
-                                uid,
-                                pi.getLongVersionCode(),
-                                pi.versionName == null ? "" : pi.versionName,
-                                installer == null ? "" : installer);
-                    }
-                } catch (Exception e) {
-                    Log.w(TAG, "Failed to inform statsd of an app update", e);
-                }
-            }
-        }
-    }
-
-    private static final class UserUpdateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // Pull the latest state of UID->app name, version mapping.
-            // Needed since the new user basically has a version of every app.
-            informAllUids(context);
-        }
-    }
-
-    public final static class PullingAlarmListener implements OnAlarmListener {
-        private final Context mContext;
-
-        PullingAlarmListener(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        public void onAlarm() {
-            if (DEBUG) {
-                Log.d(TAG, "Time to poll something.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
-                return;
-            }
-
-            // Wakelock needs to be retained while calling statsd.
-            Thread thread = new WakelockThread(mContext,
-                    PullingAlarmListener.class.getCanonicalName(), new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                statsd.informPollAlarmFired();
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
-                            }
-                        }
-                    });
-            thread.start();
-        }
-    }
-
-    public final static class PeriodicAlarmListener implements OnAlarmListener {
-        private final Context mContext;
-
-        PeriodicAlarmListener(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        public void onAlarm() {
-            if (DEBUG) {
-                Log.d(TAG, "Time to trigger periodic alarm.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing.");
-                return;
-            }
-
-            // Wakelock needs to be retained while calling statsd.
-            Thread thread = new WakelockThread(mContext,
-                    PeriodicAlarmListener.class.getCanonicalName(), new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                statsd.informAlarmForSubscriberTriggeringFired();
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
-                            }
-                        }
-                    });
-            thread.start();
-        }
-    }
-
-    public final static class ShutdownEventReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            /**
-             * Skip immediately if intent is not relevant to device shutdown.
-             */
-            if (!intent.getAction().equals(Intent.ACTION_REBOOT)
-                    && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
-                    && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
-                return;
-            }
-
-            if (DEBUG) {
-                Log.i(TAG, "StatsCompanionService noticed a shutdown.");
-            }
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd == null) {
-                Log.w(TAG, "Could not access statsd to inform it of a shutdown event.");
-                return;
-            }
-            try {
-                // two way binder call
-                statsd.informDeviceShutdown();
-            } catch (Exception e) {
-                Log.w(TAG, "Failed to inform statsd of a shutdown event.", e);
-            }
-        }
-    }
-
-    @Override // Binder call
-    public void setAlarmForSubscriberTriggering(long timestampMs) {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG,
-                    "Setting periodic alarm in about " + (timestampMs
-                            - SystemClock.elapsedRealtime()));
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
-            // only fire when it awakens.
-            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic",
-                    mPeriodicAlarmListener, mHandler);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void cancelAlarmForSubscriberTriggering() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Cancelling periodic alarm");
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            mAlarmManager.cancel(mPeriodicAlarmListener);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void setPullingAlarm(long nextPullTimeMs) {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Setting pulling alarm in about "
-                    + (nextPullTimeMs - SystemClock.elapsedRealtime()));
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
-            // only fire when it awakens.
-            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull",
-                    mPullingAlarmListener, mHandler);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void cancelPullingAlarm() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "Cancelling pulling alarm");
-        }
-        final long callingToken = Binder.clearCallingIdentity();
-        try {
-            mAlarmManager.cancel(mPullingAlarmListener);
-        } finally {
-            Binder.restoreCallingIdentity(callingToken);
-        }
-    }
-
-    @Override // Binder call
-    public void statsdReady() {
-        StatsCompanion.enforceStatsdCallingUid();
-        if (DEBUG) {
-            Log.d(TAG, "learned that statsdReady");
-        }
-        sayHiToStatsd(); // tell statsd that we're ready too and link to it
-
-        final Intent intent = new Intent(StatsManager.ACTION_STATSD_STARTED);
-        // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts
-        // to wake them up (if they're in background).
-        List<ResolveInfo> resolveInfos =
-                mContext.getPackageManager().queryBroadcastReceiversAsUser(
-                        intent, 0, UserHandle.SYSTEM);
-        if (resolveInfos == null || resolveInfos.isEmpty()) {
-            return; // No need to send broadcast.
-        }
-
-        for (ResolveInfo resolveInfo : resolveInfos) {
-            Intent intentToSend = new Intent(intent);
-            intentToSend.setComponent(new ComponentName(
-                    resolveInfo.activityInfo.applicationInfo.packageName,
-                    resolveInfo.activityInfo.name));
-            mContext.sendBroadcastAsUser(intentToSend, UserHandle.SYSTEM,
-                    android.Manifest.permission.DUMP);
-        }
-    }
-
-    @Override // Binder call
-    public boolean checkPermission(String permission, int pid, int uid) {
-        StatsCompanion.enforceStatsdCallingUid();
-        return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED;
-    }
-
-    // Statsd related code
-
-    /**
-     * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd
-     * instead of returning the cached sStatsd.
-     * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use
-     * the cached sStatsd via {@link #getStatsdNonblocking()}.
-     */
-    private IStatsd fetchStatsdServiceLocked() {
-        sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer
-                .getStatsServiceManager()
-                .getStatsdServiceRegisterer()
-                .get());
-        return sStatsd;
-    }
-
-    private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
-        StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers);
-
-        try {
-            statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed");
-            // Statsd has already died. Unregister receivers ourselves.
-            for (BroadcastReceiver receiver : receivers) {
-                mContext.unregisterReceiver(receiver);
-            }
-            synchronized (sStatsdLock) {
-                if (statsd == sStatsd) {
-                    statsdNotReadyLocked();
-                }
-            }
-        }
-    }
-
-    /**
-     * Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
-     */
-    void systemReady() {
-        if (DEBUG) Log.d(TAG, "Learned that systemReady");
-        sayHiToStatsd();
-    }
-
-    void setStatsManagerService(StatsManagerService statsManagerService) {
-        mStatsManagerService = statsManagerService;
-    }
-
-    /**
-     * Tells statsd that statscompanion is ready. If the binder call returns, link to
-     * statsd.
-     */
-    private void sayHiToStatsd() {
-        IStatsd statsd;
-        synchronized (sStatsdLock) {
-            if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) {
-                Log.e(TAG, "statsd has already been fetched before",
-                        new IllegalStateException("IStatsd object should be null or dead"));
-                return;
-            }
-            statsd = fetchStatsdServiceLocked();
-        }
-
-        if (statsd == null) {
-            Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive.");
-            return;
-        }
-
-        // Cleann up from previous statsd - cancel any alarms that had been set. Do this here
-        // instead of in binder death because statsd can come back and set different alarms, or not
-        // want to set an alarm when it had been set. This guarantees that when we get a new statsd,
-        // we cancel any alarms before it is able to set them.
-        cancelPullingAlarm();
-        cancelAlarmForSubscriberTriggering();
-
-        if (DEBUG) Log.d(TAG, "Saying hi to statsd");
-        mStatsManagerService.statsdReady(statsd);
-        try {
-            statsd.statsCompanionReady();
-
-            BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver();
-            BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver();
-            BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver();
-
-            // Setup broadcast receiver for updates.
-            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
-            filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-            filter.addDataScheme("package");
-            mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null);
-
-            // Setup receiver for user initialize (which happens once for a new user)
-            // and if a user is removed.
-            filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
-            filter.addAction(Intent.ACTION_USER_REMOVED);
-            mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null);
-
-            // Setup receiver for device reboots or shutdowns.
-            filter = new IntentFilter(Intent.ACTION_REBOOT);
-            filter.addAction(Intent.ACTION_SHUTDOWN);
-            mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null);
-
-            // Register death recipient.
-            List<BroadcastReceiver> broadcastReceivers =
-                    List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver);
-            registerStatsdDeathRecipient(statsd, broadcastReceivers);
-
-            // Tell statsd that boot has completed. The signal may have already been sent, but since
-            // the signal-receiving function is idempotent, that's ok.
-            if (mBootCompleted.get()) {
-                statsd.bootCompleted();
-            }
-
-            // Pull the latest state of UID->app name, version mapping when statsd starts.
-            informAllUids(mContext);
-
-            Log.i(TAG, "Told statsd that StatsCompanionService is alive.");
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
-        }
-    }
-
-    private class StatsdDeathRecipient implements IBinder.DeathRecipient {
-
-        private final IStatsd mStatsd;
-        private final List<BroadcastReceiver> mReceiversToUnregister;
-
-        StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
-            mStatsd = statsd;
-            mReceiversToUnregister = receivers;
-        }
-
-        // It is possible for binderDied to be called after a restarted statsd calls statsdReady,
-        // but that's alright because the code does not assume an ordering of the two calls.
-        @Override
-        public void binderDied() {
-            Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers");
-            synchronized (sStatsdLock) {
-                long now = SystemClock.elapsedRealtime();
-                for (Long timeMillis : mDeathTimeMillis) {
-                    long ageMillis = now - timeMillis;
-                    if (ageMillis > MILLIS_IN_A_DAY) {
-                        mDeathTimeMillis.remove(timeMillis);
-                    }
-                }
-                for (Long timeMillis : mDeletedFiles.keySet()) {
-                    long ageMillis = now - timeMillis;
-                    if (ageMillis > MILLIS_IN_A_DAY * 7) {
-                        mDeletedFiles.remove(timeMillis);
-                    }
-                }
-                mDeathTimeMillis.add(now);
-                if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) {
-                    mDeathTimeMillis.clear();
-                    File[] configs = new File(CONFIG_DIR).listFiles();
-                    if (configs != null && configs.length > 0) {
-                        String fileName = configs[0].getName();
-                        if (configs[0].delete()) {
-                            mDeletedFiles.put(now, fileName);
-                        }
-                    }
-                }
-
-                // Unregister receivers on death because receivers can only be unregistered once.
-                // Otherwise, an IllegalArgumentException is thrown.
-                for (BroadcastReceiver receiver: mReceiversToUnregister) {
-                    mContext.unregisterReceiver(receiver);
-                }
-
-                // It's possible for statsd to have restarted and called statsdReady, causing a new
-                // sStatsd binder object to be fetched, before the binderDied callback runs. Only
-                // call #statsdNotReadyLocked if that hasn't happened yet.
-                if (mStatsd == sStatsd) {
-                    statsdNotReadyLocked();
-                }
-            }
-        }
-    }
-
-    private void statsdNotReadyLocked() {
-        sStatsd = null;
-        mStatsManagerService.statsdNotReady();
-    }
-
-    void bootCompleted() {
-        mBootCompleted.set(true);
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            // Statsd is not yet ready.
-            // Delay the boot completed ping to {@link #sayHiToStatsd()}
-            return;
-        }
-        try {
-            statsd.bootCompleted();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to notify statsd that boot completed");
-        }
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-
-        synchronized (sStatsdLock) {
-            writer.println("Number of configuration files deleted: " + mDeletedFiles.size());
-            if (mDeletedFiles.size() > 0) {
-                writer.println("  timestamp, deleted file name");
-            }
-            long lastBootMillis =
-                    SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime();
-            for (Long elapsedMillis : mDeletedFiles.keySet()) {
-                long deletionMillis = lastBootMillis + elapsedMillis;
-                writer.println("  " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis));
-            }
-        }
-    }
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
deleted file mode 100644
index 1e3846b..0000000
--- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.stats;
-
-import static com.android.server.stats.StatsCompanion.PendingIntentRef;
-
-import android.Manifest;
-import android.annotation.Nullable;
-import android.app.AppOpsManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IPullAtomCallback;
-import android.os.IStatsManagerService;
-import android.os.IStatsd;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Service for {@link android.app.StatsManager}.
- *
- * @hide
- */
-public class StatsManagerService extends IStatsManagerService.Stub {
-
-    private static final String TAG = "StatsManagerService";
-    private static final boolean DEBUG = false;
-
-    private static final int STATSD_TIMEOUT_MILLIS = 5000;
-
-    private static final String USAGE_STATS_PERMISSION_OPS = "android:get_usage_stats";
-
-    @GuardedBy("mLock")
-    private IStatsd mStatsd;
-    private final Object mLock = new Object();
-
-    private StatsCompanionService mStatsCompanionService;
-    private Context mContext;
-
-    @GuardedBy("mLock")
-    private ArrayMap<ConfigKey, PendingIntentRef> mDataFetchPirMap = new ArrayMap<>();
-    @GuardedBy("mLock")
-    private ArrayMap<Integer, PendingIntentRef> mActiveConfigsPirMap = new ArrayMap<>();
-    @GuardedBy("mLock")
-    private ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> mBroadcastSubscriberPirMap =
-            new ArrayMap<>();
-
-    public StatsManagerService(Context context) {
-        super();
-        mContext = context;
-    }
-
-    private static class ConfigKey {
-        private final int mUid;
-        private final long mConfigId;
-
-        ConfigKey(int uid, long configId) {
-            mUid = uid;
-            mConfigId = configId;
-        }
-
-        public int getUid() {
-            return mUid;
-        }
-
-        public long getConfigId() {
-            return mConfigId;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mUid, mConfigId);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof ConfigKey) {
-                ConfigKey other = (ConfigKey) obj;
-                return this.mUid == other.getUid() && this.mConfigId == other.getConfigId();
-            }
-            return false;
-        }
-    }
-
-    private static class PullerKey {
-        private final int mUid;
-        private final int mAtomTag;
-
-        PullerKey(int uid, int atom) {
-            mUid = uid;
-            mAtomTag = atom;
-        }
-
-        public int getUid() {
-            return mUid;
-        }
-
-        public int getAtom() {
-            return mAtomTag;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mUid, mAtomTag);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof PullerKey) {
-                PullerKey other = (PullerKey) obj;
-                return this.mUid == other.getUid() && this.mAtomTag == other.getAtom();
-            }
-            return false;
-        }
-    }
-
-    private static class PullerValue {
-        private final long mCoolDownMillis;
-        private final long mTimeoutMillis;
-        private final int[] mAdditiveFields;
-        private final IPullAtomCallback mCallback;
-
-        PullerValue(long coolDownMillis, long timeoutMillis, int[] additiveFields,
-                IPullAtomCallback callback) {
-            mCoolDownMillis = coolDownMillis;
-            mTimeoutMillis = timeoutMillis;
-            mAdditiveFields = additiveFields;
-            mCallback = callback;
-        }
-
-        public long getCoolDownMillis() {
-            return mCoolDownMillis;
-        }
-
-        public long getTimeoutMillis() {
-            return mTimeoutMillis;
-        }
-
-        public int[] getAdditiveFields() {
-            return mAdditiveFields;
-        }
-
-        public IPullAtomCallback getCallback() {
-            return mCallback;
-        }
-    }
-
-    private final ArrayMap<PullerKey, PullerValue> mPullers = new ArrayMap<>();
-
-    @Override
-    public void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
-            int[] additiveFields, IPullAtomCallback pullerCallback) {
-        enforceRegisterStatsPullAtomPermission();
-        if (pullerCallback == null) {
-            Log.w(TAG, "Puller callback is null for atom " + atomTag);
-            return;
-        }
-        int callingUid = Binder.getCallingUid();
-        PullerKey key = new PullerKey(callingUid, atomTag);
-        PullerValue val =
-                new PullerValue(coolDownMillis, timeoutMillis, additiveFields, pullerCallback);
-
-        // Always cache the puller in StatsManagerService. If statsd is down, we will register the
-        // puller when statsd comes back up.
-        synchronized (mLock) {
-            mPullers.put(key, val);
-        }
-
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            statsd.registerPullAtomCallback(callingUid, atomTag, coolDownMillis, timeoutMillis,
-                    additiveFields, pullerCallback);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to access statsd to register puller for atom " + atomTag);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void unregisterPullAtomCallback(int atomTag) {
-        enforceRegisterStatsPullAtomPermission();
-        int callingUid = Binder.getCallingUid();
-        PullerKey key = new PullerKey(callingUid, atomTag);
-
-        // Always remove the puller from StatsManagerService even if statsd is down. When statsd
-        // comes back up, we will not re-register the removed puller.
-        synchronized (mLock) {
-            mPullers.remove(key);
-        }
-
-        IStatsd statsd = getStatsdNonblocking();
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            statsd.unregisterPullAtomCallback(callingUid, atomTag);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to access statsd to unregister puller for atom " + atomTag);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void setDataFetchOperation(long configId, PendingIntent pendingIntent,
-            String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            mDataFetchPirMap.put(key, pir);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.setDataFetchOperation(configId, pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setDataFetchOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void removeDataFetchOperation(long configId, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        synchronized (mLock) {
-            mDataFetchPirMap.remove(key);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.removeDataFetchOperation(configId, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeDataFetchOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
-            String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            mActiveConfigsPirMap.put(callingUid, pir);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                return statsd.setActiveConfigsChangedOperation(pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        return new long[] {};
-    }
-
-    @Override
-    public void removeActiveConfigsChangedOperation(String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        synchronized (mLock) {
-            mActiveConfigsPirMap.remove(callingUid);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.removeActiveConfigsChangedOperation(callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void setBroadcastSubscriber(long configId, long subscriberId,
-            PendingIntent pendingIntent, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        // We add the PIR to a map so we can reregister if statsd is unavailable.
-        synchronized (mLock) {
-            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
-                    .getOrDefault(key, new ArrayMap<>());
-            innerMap.put(subscriberId, pir);
-            mBroadcastSubscriberPirMap.put(key, innerMap);
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.setBroadcastSubscriber(
-                        configId, subscriberId, pir, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to setBroadcastSubscriber with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public void unsetBroadcastSubscriber(long configId, long subscriberId, String packageName) {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        ConfigKey key = new ConfigKey(callingUid, configId);
-        synchronized (mLock) {
-            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
-                    .getOrDefault(key, new ArrayMap<>());
-            innerMap.remove(subscriberId);
-            if (innerMap.isEmpty()) {
-                mBroadcastSubscriberPirMap.remove(key);
-            }
-        }
-        try {
-            IStatsd statsd = getStatsdNonblocking();
-            if (statsd != null) {
-                statsd.unsetBroadcastSubscriber(configId, subscriberId, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to unsetBroadcastSubscriber with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public long[] getRegisteredExperimentIds() throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(null);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getRegisteredExperimentIds();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getRegisteredExperimentIds with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to registerExperimentIds");
-    }
-
-    @Override
-    public byte[] getMetadata(String packageName) throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getMetadata();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getMetadata with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to getMetadata");
-    }
-
-    @Override
-    public byte[] getData(long key, String packageName) throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        PowerManager powerManager = (PowerManager)
-                mContext.getSystemService(Context.POWER_SERVICE);
-        PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
-                /*tag=*/ StatsManagerService.class.getCanonicalName());
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        wl.acquire();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                return statsd.getData(key, callingUid);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to getData with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            wl.release();
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to getData");
-    }
-
-    @Override
-    public void addConfiguration(long configId, byte[] config, String packageName)
-            throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                statsd.addConfiguration(configId, config, callingUid);
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to addConfiguration with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to addConfig");
-    }
-
-    @Override
-    public void removeConfiguration(long configId, String packageName)
-            throws IllegalStateException {
-        enforceDumpAndUsageStatsPermission(packageName);
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        try {
-            IStatsd statsd = waitForStatsd();
-            if (statsd != null) {
-                statsd.removeConfiguration(configId, callingUid);
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to removeConfiguration with statsd");
-            throw new IllegalStateException(e.getMessage(), e);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        throw new IllegalStateException("Failed to connect to statsd to removeConfig");
-    }
-
-    void setStatsCompanionService(StatsCompanionService statsCompanionService) {
-        mStatsCompanionService = statsCompanionService;
-    }
-
-    /**
-     * Checks that the caller has both DUMP and PACKAGE_USAGE_STATS permissions. Also checks that
-     * the caller has USAGE_STATS_PERMISSION_OPS for the specified packageName if it is not null.
-     *
-     * @param packageName The packageName to check USAGE_STATS_PERMISSION_OPS.
-     */
-    private void enforceDumpAndUsageStatsPermission(@Nullable String packageName) {
-        int callingUid = Binder.getCallingUid();
-        int callingPid = Binder.getCallingPid();
-
-        if (callingPid == Process.myPid()) {
-            return;
-        }
-
-        mContext.enforceCallingPermission(Manifest.permission.DUMP, null);
-        mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, null);
-
-        if (packageName == null) {
-            return;
-        }
-        AppOpsManager appOpsManager = (AppOpsManager) mContext
-                .getSystemService(Context.APP_OPS_SERVICE);
-        switch (appOpsManager.noteOp(USAGE_STATS_PERMISSION_OPS,
-                Binder.getCallingUid(), packageName, null, null)) {
-            case AppOpsManager.MODE_ALLOWED:
-            case AppOpsManager.MODE_DEFAULT:
-                break;
-            default:
-                throw new SecurityException(
-                        String.format("UID %d / PID %d lacks app-op %s",
-                                callingUid, callingPid, USAGE_STATS_PERMISSION_OPS)
-                );
-        }
-    }
-
-    private void enforceRegisterStatsPullAtomPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.REGISTER_STATS_PULL_ATOM,
-                "Need REGISTER_STATS_PULL_ATOM permission.");
-    }
-
-
-    /**
-     * Clients should call this if blocking until statsd to be ready is desired
-     *
-     * @return IStatsd object if statsd becomes ready within the timeout, null otherwise.
-     */
-    private IStatsd waitForStatsd() {
-        synchronized (mLock) {
-            if (mStatsd == null) {
-                try {
-                    mLock.wait(STATSD_TIMEOUT_MILLIS);
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "wait for statsd interrupted");
-                }
-            }
-            return mStatsd;
-        }
-    }
-
-    /**
-     * Clients should call this to receive a reference to statsd.
-     *
-     * @return IStatsd object if statsd is ready, null otherwise.
-     */
-    private IStatsd getStatsdNonblocking() {
-        synchronized (mLock) {
-            return mStatsd;
-        }
-    }
-
-    /**
-     * Called from {@link StatsCompanionService}.
-     *
-     * Tells StatsManagerService that Statsd is ready and updates
-     * Statsd with the contents of our local cache.
-     */
-    void statsdReady(IStatsd statsd) {
-        synchronized (mLock) {
-            mStatsd = statsd;
-            mLock.notify();
-        }
-        sayHiToStatsd(statsd);
-    }
-
-    /**
-     * Called from {@link StatsCompanionService}.
-     *
-     * Tells StatsManagerService that Statsd is no longer ready
-     * and we should no longer make binder calls with statsd.
-     */
-    void statsdNotReady() {
-        synchronized (mLock) {
-            mStatsd = null;
-        }
-    }
-
-    private void sayHiToStatsd(IStatsd statsd) {
-        if (statsd == null) {
-            return;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            registerAllPullers(statsd);
-            registerAllDataFetchOperations(statsd);
-            registerAllActiveConfigsChangedOperations(statsd);
-            registerAllBroadcastSubscribers(statsd);
-        } catch (RemoteException e) {
-            Log.e(TAG, "StatsManager failed to (re-)register data with statsd");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllPullers(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<PullerKey, PullerValue> pullersCopy;
-        synchronized (mLock) {
-            pullersCopy = new ArrayMap<>(mPullers);
-        }
-
-        for (Map.Entry<PullerKey, PullerValue> entry : pullersCopy.entrySet()) {
-            PullerKey key = entry.getKey();
-            PullerValue value = entry.getValue();
-            statsd.registerPullAtomCallback(key.getUid(), key.getAtom(), value.getCoolDownMillis(),
-                    value.getTimeoutMillis(), value.getAdditiveFields(), value.getCallback());
-        }
-        statsd.allPullersFromBootRegistered();
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllDataFetchOperations(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy;
-        synchronized (mLock) {
-            dataFetchCopy = new ArrayMap<>(mDataFetchPirMap);
-        }
-
-        for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) {
-            ConfigKey key = entry.getKey();
-            statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid());
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllActiveConfigsChangedOperations(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a copy of the
-        // data with the lock held before iterating through the map.
-        ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy;
-        synchronized (mLock) {
-            activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap);
-        }
-
-        for (Map.Entry<Integer, PendingIntentRef> entry : activeConfigsChangedCopy.entrySet()) {
-            statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey());
-        }
-    }
-
-    // Pre-condition: the Binder calling identity has already been cleared
-    private void registerAllBroadcastSubscribers(IStatsd statsd) throws RemoteException {
-        // Since we do not want to make an IPC with the lock held, we first create a deep copy of
-        // the data with the lock held before iterating through the map.
-        ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy =
-                new ArrayMap<>();
-        synchronized (mLock) {
-            for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry :
-                    mBroadcastSubscriberPirMap.entrySet()) {
-                broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap(entry.getValue()));
-            }
-        }
-
-        for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry :
-                mBroadcastSubscriberPirMap.entrySet()) {
-            ConfigKey configKey = entry.getKey();
-            for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) {
-                statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(),
-                        subscriberEntry.getValue(), configKey.getUid());
-            }
-        }
-    }
-}
diff --git a/apex/statsd/statsd.rc b/apex/statsd/statsd.rc
deleted file mode 100644
index 605da2a..0000000
--- a/apex/statsd/statsd.rc
+++ /dev/null
@@ -1,20 +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.
-
-service statsd /apex/com.android.os.statsd/bin/statsd
-    class main
-    socket statsdw dgram+passcred 0222 statsd statsd
-    user statsd
-    group statsd log
-    writepid /dev/cpuset/system-background/tasks
diff --git a/apex/statsd/testing/Android.bp b/apex/statsd/testing/Android.bp
deleted file mode 100644
index a9cd0cc..0000000
--- a/apex/statsd/testing/Android.bp
+++ /dev/null
@@ -1,25 +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.
-
-apex_test {
-    name: "test_com.android.os.statsd",
-    visibility: [
-        "//system/apex/tests",
-    ],
-    defaults: ["com.android.os.statsd-defaults"],
-    manifest: "test_manifest.json",
-    file_contexts: ":com.android.os.statsd-file_contexts",
-    // Test APEX, should never be installed
-    installable: false,
-}
diff --git a/apex/statsd/testing/test_manifest.json b/apex/statsd/testing/test_manifest.json
deleted file mode 100644
index 57343d3..0000000
--- a/apex/statsd/testing/test_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.os.statsd",
-  "version": 2147483647
-}
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
deleted file mode 100644
index 05b3e04..0000000
--- a/apex/statsd/tests/libstatspull/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-android_test {
-    name: "LibStatsPullTests",
-    static_libs: [
-        "androidx.test.rules",
-        "platformprotoslite",
-        "statsdprotolite",
-        "truth-prebuilt",
-    ],
-    libs: [
-        "android.test.runner.stubs",
-        "android.test.base.stubs",
-    ],
-    jni_libs: [
-        "libstatspull_testhelper",
-    ],
-    srcs: [
-        "src/**/*.java",
-        "protos/**/*.proto",
-        ],
-    test_suites: [
-        "device-tests",
-        "mts",
-    ],
-    platform_apis: true,
-    privileged: true,
-    certificate: "platform",
-    compile_multilib: "both",
-}
-
-cc_library_shared {
-    name: "libstatspull_testhelper",
-    srcs: ["jni/stats_pull_helper.cpp"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    shared_libs: [
-        "libbinder_ndk",
-        "statsd-aidl-ndk_platform",
-    ],
-    static_libs: [
-        "libstatspull_private",
-        "libstatssocket_private",
-        "libutils",
-        "libcutils",
-    ],
-}
diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml
deleted file mode 100644
index 0c669b0..0000000
--- a/apex/statsd/tests/libstatspull/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.internal.os.statsd.libstats" >
-
-
-    <uses-permission android:name="android.permission.DUMP" />
-    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
-    <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" />
-
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.internal.os.statsd.libstats"
-                     android:label="Tests for libstatspull">
-    </instrumentation>
-</manifest>
-
diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
deleted file mode 100644
index 166592d..0000000
--- a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-#include <log/log.h>
-#include <stats_event.h>
-#include <stats_pull_atom_callback.h>
-
-#include <chrono>
-#include <thread>
-
-using std::this_thread::sleep_for;
-
-namespace {
-static int32_t sAtomTag;
-static int32_t sPullReturnVal;
-static int64_t sLatencyMillis;
-static int32_t sAtomsPerPull;
-static int32_t sNumPulls = 0;
-
-static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atomTag, AStatsEventList* data,
-                                                             void* /*cookie*/) {
-    sNumPulls++;
-    sleep_for(std::chrono::milliseconds(sLatencyMillis));
-    for (int i = 0; i < sAtomsPerPull; i++) {
-        AStatsEvent* event = AStatsEventList_addStatsEvent(data);
-        AStatsEvent_setAtomId(event, atomTag);
-        AStatsEvent_writeInt64(event, (int64_t) sNumPulls);
-        AStatsEvent_build(event);
-    }
-    return sPullReturnVal;
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_setStatsPuller(
-        JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutMillis,
-        jlong coolDownMillis, jint pullRetVal, jlong latencyMillis, int atomsPerPull) {
-    sAtomTag = atomTag;
-    sPullReturnVal = pullRetVal;
-    sLatencyMillis = latencyMillis;
-    sAtomsPerPull = atomsPerPull;
-    sNumPulls = 0;
-    AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
-    AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis);
-    AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis);
-
-    AStatsManager_setPullAtomCallback(sAtomTag, metadata, &pullAtomCallback, nullptr);
-    AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_clearStatsPuller(JNIEnv* /*env*/,
-                                                                                jobject /* this */,
-                                                                                jint /*atomTag*/) {
-    AStatsManager_clearPullAtomCallback(sAtomTag);
-}
-} // namespace
diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
deleted file mode 100644
index 56c1b53..0000000
--- a/apex/statsd/tests/libstatspull/protos/test_atoms.proto
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-syntax = "proto2";
-
-package com.android.internal.os.statsd.protos;
-
-option java_package = "com.android.internal.os.statsd.protos";
-option java_outer_classname = "TestAtoms";
-
-message PullCallbackAtomWrapper {
-  optional PullCallbackAtom pull_callback_atom = 150030;
-}
-
-message PullCallbackAtom {
-  optional int64 long_val = 1;
-}
-
-
-
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
deleted file mode 100644
index 6108a32..0000000
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.os.statsd.libstats;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager;
-import android.content.Context;
-import android.util.Log;
-import android.util.StatsLog;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.internal.os.statsd.protos.TestAtoms;
-import com.android.os.AtomsProto.Atom;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * Test puller registration.
- */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class LibStatsPullTests {
-    private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName();
-    private static final int SHORT_SLEEP_MILLIS = 250;
-    private static final int LONG_SLEEP_MILLIS = 1_000;
-    private Context mContext;
-    private static final int PULL_ATOM_TAG = 150030;
-    private static final int APP_BREADCRUMB_LABEL = 3;
-    private static int sPullReturnValue;
-    private static long sConfigId;
-    private static long sPullLatencyMillis;
-    private static long sPullTimeoutMillis;
-    private static long sCoolDownMillis;
-    private static int sAtomsPerPull;
-
-    static {
-        System.loadLibrary("statspull_testhelper");
-    }
-
-    /**
-     * Setup the tests. Initialize shared data.
-     */
-    @Before
-    public void setup() {
-        mContext = InstrumentationRegistry.getTargetContext();
-        assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull();
-        sPullReturnValue = StatsManager.PULL_SUCCESS;
-        sPullLatencyMillis = 0;
-        sPullTimeoutMillis = 10_000L;
-        sCoolDownMillis = 1_000L;
-        sAtomsPerPull = 1;
-    }
-
-    /**
-     * Teardown the tests.
-     */
-    @After
-    public void tearDown() throws Exception {
-        clearStatsPuller(PULL_ATOM_TAG);
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        statsManager.removeConfig(sConfigId);
-    }
-
-    /**
-     * Tests adding a puller callback and that pulls complete successfully.
-     */
-    @Test
-    public void testPullAtomCallbackRegistration() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        // Upload a config that captures that pulled atom.
-        createAndAddConfigToStatsd(statsManager);
-
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(1);
-        TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-        try {
-            atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                    .parseFrom(data.get(0).toByteArray());
-        } catch (Exception e) {
-            Log.e(LOG_TAG, "Failed to parse primitive atoms");
-        }
-        assertThat(atomWrapper).isNotNull();
-        assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-        TestAtoms.PullCallbackAtom atom =
-                atomWrapper.getPullCallbackAtom();
-        assertThat(atom.getLongVal()).isEqualTo(1);
-    }
-
-    /**
-     * Tests that a failed pull is skipped.
-     */
-    @Test
-    public void testPullAtomCallbackFailure() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-        sPullReturnValue = StatsManager.PULL_SKIP;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(0);
-    }
-
-    /**
-     * Tests that a pull that times out is skipped.
-     */
-    @Test
-    public void testPullAtomCallbackTimeout() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-        // The puller will sleep for 1.5 sec.
-        sPullLatencyMillis = 1_500;
-        // 1 second timeout
-        sPullTimeoutMillis = 1_000;
-
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish and the pull timeout.
-        Thread.sleep(sPullLatencyMillis * 2);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(0);
-    }
-
-    /**
-     * Tests that 2 pulls in quick succession use the cache instead of pulling again.
-     */
-    @Test
-    public void testPullAtomCallbackCache() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        createAndAddConfigToStatsd(statsManager);
-
-        // Set the cooldown to 10 seconds
-        sCoolDownMillis = 10_000L;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Pull from cache.
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(2);
-        for (int i = 0; i < data.size(); i++) {
-            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-            try {
-                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                        .parseFrom(data.get(i).toByteArray());
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Failed to parse primitive atoms");
-            }
-            assertThat(atomWrapper).isNotNull();
-            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-            TestAtoms.PullCallbackAtom atom =
-                    atomWrapper.getPullCallbackAtom();
-            assertThat(atom.getLongVal()).isEqualTo(1);
-        }
-    }
-
-    /**
-     * Tests that a pull that returns 1000 stats events works properly.
-     */
-    @Test
-    public void testPullAtomCallbackStress() throws Exception {
-        StatsManager statsManager = (StatsManager) mContext.getSystemService(
-                Context.STATS_MANAGER);
-        // Upload a config that captures that pulled atom.
-        createAndAddConfigToStatsd(statsManager);
-        sAtomsPerPull = 1000;
-        // Add the puller.
-        setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
-                sPullLatencyMillis, sAtomsPerPull);
-
-        Thread.sleep(SHORT_SLEEP_MILLIS);
-        StatsLog.logStart(APP_BREADCRUMB_LABEL);
-        // Let the current bucket finish.
-        Thread.sleep(LONG_SLEEP_MILLIS);
-        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
-        clearStatsPuller(PULL_ATOM_TAG);
-        assertThat(data.size()).isEqualTo(sAtomsPerPull);
-
-        for (int i = 0; i < data.size(); i++) {
-            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
-            try {
-                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
-                        .parseFrom(data.get(i).toByteArray());
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Failed to parse primitive atoms");
-            }
-            assertThat(atomWrapper).isNotNull();
-            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
-            TestAtoms.PullCallbackAtom atom =
-                    atomWrapper.getPullCallbackAtom();
-            assertThat(atom.getLongVal()).isEqualTo(1);
-        }
-    }
-
-    private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
-        sConfigId = System.currentTimeMillis();
-        long triggerMatcherId = sConfigId + 10;
-        long pullerMatcherId = sConfigId + 11;
-        long metricId = sConfigId + 100;
-        StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId)
-                .addAtomMatcher(
-                        StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId,
-                                APP_BREADCRUMB_LABEL))
-                .addAtomMatcher(AtomMatcher.newBuilder()
-                        .setId(pullerMatcherId)
-                        .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
-                                .setAtomId(PULL_ATOM_TAG))
-                )
-                .addGaugeMetric(GaugeMetric.newBuilder()
-                        .setId(metricId)
-                        .setWhat(pullerMatcherId)
-                        .setTriggerEvent(triggerMatcherId)
-                        .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true))
-                        .setBucket(TimeUnit.CTS)
-                        .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
-                        .setMaxNumGaugeAtomsPerBucket(1000)
-                )
-                .addPullAtomPackages(PullAtomPackages.newBuilder()
-                        .setAtomId(PULL_ATOM_TAG)
-                        .addPackages(LibStatsPullTests.class.getPackage().getName()))
-                .build();
-        statsManager.addConfig(sConfigId, config.toByteArray());
-        assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
-    }
-
-    private native void setStatsPuller(int atomTag, long timeoutMillis, long coolDownMillis,
-            int pullReturnVal, long latencyMillis, int atomPerPull);
-
-    private native void clearStatsPuller(int atomTag);
-}
-
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java
deleted file mode 100644
index b5afb94..0000000
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/StatsConfigUtils.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.os.statsd.libstats;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.StatsManager;
-import android.util.Log;
-
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.GaugeBucketInfo;
-import com.android.os.StatsLog.GaugeMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.os.StatsLog.StatsdStatsReport;
-import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Util class for constructing statsd configs.
- */
-public class StatsConfigUtils {
-    public static final String TAG = "statsd.StatsConfigUtils";
-    public static final int SHORT_WAIT = 2_000; // 2 seconds.
-
-    /**
-     * @return An empty StatsdConfig in serialized proto format.
-     */
-    public static StatsdConfig.Builder getSimpleTestConfig(long configId) {
-        return StatsdConfig.newBuilder().setId(configId)
-                .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName());
-    }
-
-
-    public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) {
-        StatsdStatsReport report = null;
-        try {
-            report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata());
-        } catch (Exception e) {
-            Log.e(TAG, "getMetadata failed", e);
-        }
-        assertThat(report).isNotNull();
-        boolean foundConfig = false;
-        for (ConfigStats configStats : report.getConfigStatsList()) {
-            if (configStats.getId() == configId && configStats.getIsValid()
-                    && configStats.getDeletionTimeSec() == 0) {
-                foundConfig = true;
-            }
-        }
-        return foundConfig;
-    }
-
-    public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) {
-        return AtomMatcher.newBuilder()
-                .setId(id)
-                .setSimpleAtomMatcher(
-                        SimpleAtomMatcher.newBuilder()
-                                .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-                                .addFieldValueMatcher(FieldValueMatcher.newBuilder()
-                                        .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
-                                        .setEqInt(label)
-                                )
-                )
-                .build();
-    }
-
-    public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager,
-            long configId) {
-        ConfigMetricsReportList reportList = null;
-        try {
-            reportList = ConfigMetricsReportList.parser()
-                    .parseFrom(statsManager.getReports(configId));
-        } catch (Exception e) {
-            Log.e(TAG, "getData failed", e);
-        }
-        assertThat(reportList).isNotNull();
-        assertThat(reportList.getReportsCount()).isEqualTo(1);
-        ConfigMetricsReport report = reportList.getReports(0);
-        assertThat(report.getDumpReportReason())
-                .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED);
-        return report;
-
-    }
-    public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) {
-        List<Atom> data = new ArrayList<>();
-        for (StatsLogReport metric : report.getMetricsList()) {
-            for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) {
-                for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) {
-                    for (Atom atom : bucketInfo.getAtomList()) {
-                        data.add(atom);
-                    }
-                }
-            }
-        }
-        return data;
-    }
-
-    public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) {
-        ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId);
-        return getGaugeMetricDataList(report);
-    }
-}
-
diff --git a/api/Android.bp b/api/Android.bp
index 5ee41b7..9417030 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -38,6 +38,7 @@
         ":framework-statsd{.public.api.txt}",
         ":framework-tethering{.public.api.txt}",
         ":framework-wifi{.public.api.txt}",
+        ":i18n.module.public.api{.public.api.txt}",
         ":non-updatable-current.txt",
     ],
     out: ["current.txt"],
@@ -50,7 +51,10 @@
             dest: "current.txt",
         },
         {
-            targets: ["sdk", "win_sdk"],
+            targets: [
+                "sdk",
+                "win_sdk",
+            ],
             dir: "apistubs/android/public/api",
             dest: "android.txt",
         },
@@ -72,6 +76,7 @@
         ":framework-statsd{.public.stubs.source}",
         ":framework-tethering{.public.stubs.source}",
         ":framework-wifi{.public.stubs.source}",
+        ":i18n.module.public.api{.public.stubs.source}",
     ],
     out: ["current.srcjar"],
     tools: ["merge_zips"],
@@ -92,6 +97,7 @@
         ":framework-statsd{.public.removed-api.txt}",
         ":framework-tethering{.public.removed-api.txt}",
         ":framework-wifi{.public.removed-api.txt}",
+        ":i18n.module.public.api{.public.removed-api.txt}",
         ":non-updatable-removed.txt",
     ],
     out: ["removed.txt"],
@@ -130,7 +136,10 @@
             dest: "system-current.txt",
         },
         {
-            targets: ["sdk", "win_sdk"],
+            targets: [
+                "sdk",
+                "win_sdk",
+            ],
             dir: "apistubs/android/system/api",
             dest: "android.txt",
         },
@@ -189,7 +198,10 @@
             dest: "module-lib-current.txt",
         },
         {
-            targets: ["sdk", "win_sdk"],
+            targets: [
+                "sdk",
+                "win_sdk",
+            ],
             dir: "apistubs/android/module-lib/api",
             dest: "android.txt",
         },
diff --git a/api/OWNERS b/api/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/api/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/cmds/am/OWNERS b/cmds/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/cmds/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/cmds/appops/OWNERS b/cmds/appops/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/cmds/appops/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/cmds/backup/OWNERS b/cmds/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/bmgr/OWNERS b/cmds/bmgr/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/bmgr/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/bu/OWNERS b/cmds/bu/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/cmds/bu/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/cmds/dpm/OWNERS b/cmds/dpm/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/cmds/dpm/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 8323d0b..437180d 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -71,7 +71,7 @@
   }
 
   // next, try to parse as a package:type/name string
-  if (auto resid = am.GetResourceId(res, "", fallback_package)) {
+  if (auto resid = am.GetResourceId(res, "", fallback_package); resid.ok()) {
     return *resid;
   }
 
@@ -94,7 +94,7 @@
     case Res_value::TYPE_STRING: {
       const ResStringPool* pool = am->GetStringPoolForCookie(value.cookie);
       out->append("\"");
-      if (auto str = pool->string8ObjectAt(value.data)) {
+      if (auto str = pool->string8ObjectAt(value.data); str.ok()) {
         out->append(*str);
       }
     } break;
diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp
index 7c55b64..4030b83 100644
--- a/cmds/idmap2/libidmap2/XmlParser.cpp
+++ b/cmds/idmap2/libidmap2/XmlParser.cpp
@@ -98,7 +98,7 @@
 
   switch ((*value).dataType) {
     case Res_value::TYPE_STRING: {
-      if (auto str = parser_.getStrings().string8ObjectAt((*value).data)) {
+      if (auto str = parser_.getStrings().string8ObjectAt((*value).data); str.ok()) {
         return std::string(str->string());
       }
       break;
diff --git a/cmds/ime/OWNERS b/cmds/ime/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/cmds/ime/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/cmds/incident/OWNERS b/cmds/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/cmds/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/cmds/input/OWNERS b/cmds/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/locksettings/OWNERS b/cmds/locksettings/OWNERS
new file mode 100644
index 0000000..0a8dc8c
--- /dev/null
+++ b/cmds/locksettings/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/locksettings/OWNERS
diff --git a/cmds/pm/OWNERS b/cmds/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/cmds/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/cmds/sm/OWNERS b/cmds/sm/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/cmds/sm/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/cmds/telecom/OWNERS b/cmds/telecom/OWNERS
new file mode 100644
index 0000000..2f813e6
--- /dev/null
+++ b/cmds/telecom/OWNERS
@@ -0,0 +1 @@
+include /telecomm/OWNERS
diff --git a/cmds/uinput/OWNERS b/cmds/uinput/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/uinput/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/wm/OWNERS b/cmds/wm/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/cmds/wm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/config/OWNERS b/config/OWNERS
index 3d4924d..d59c6f2 100644
--- a/config/OWNERS
+++ b/config/OWNERS
@@ -1,4 +1,7 @@
+include /ZYGOTE_OWNERS
+
 # compat-team@ for changes to hiddenapi files
+
 per-file hiddenapi-* = andreionea@google.com, mathewi@google.com, satayev@google.com
 
 # Escalations:
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 8d2f143..6f818a9 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -14027,7 +14027,6 @@
 libcore.util.SneakyThrow
 libcore.util.XmlObjectFactory
 libcore.util.ZoneInfo
-org.apache.harmony.dalvik.NativeTestTarget
 org.apache.harmony.dalvik.ddmc.Chunk
 org.apache.harmony.dalvik.ddmc.ChunkHandler
 org.apache.harmony.dalvik.ddmc.DdmServer
diff --git a/core/api/OWNERS b/core/api/OWNERS
new file mode 100644
index 0000000..0b95c51
--- /dev/null
+++ b/core/api/OWNERS
@@ -0,0 +1,2 @@
+# API changes are managed via Prolog rules, not OWNERS
+*
diff --git a/core/api/current.txt b/core/api/current.txt
index 222be7f0..2cde77e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -87,6 +87,7 @@
     field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
     field @Deprecated public static final String GET_TASKS = "android.permission.GET_TASKS";
     field public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
+    field public static final String HIDE_OVERLAY_WINDOWS = "android.permission.HIDE_OVERLAY_WINDOWS";
     field public static final String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
     field public static final String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
     field public static final String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
@@ -140,6 +141,7 @@
     field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
     field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
+    field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
     field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
     field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
@@ -165,6 +167,7 @@
     field public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
     field @Deprecated public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
     field public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
+    field public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER";
     field public static final String USE_SIP = "android.permission.USE_SIP";
     field public static final String VIBRATE = "android.permission.VIBRATE";
     field public static final String WAKE_LOCK = "android.permission.WAKE_LOCK";
@@ -1146,6 +1149,7 @@
     field public static final int reqNavigation = 16843306; // 0x101022a
     field public static final int reqTouchScreen = 16843303; // 0x1010227
     field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
+    field public static final int requireDeviceScreenOn = 16844315; // 0x101061b
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -6020,7 +6024,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);
@@ -6037,6 +6041,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();
@@ -6071,6 +6076,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";
@@ -6215,6 +6223,7 @@
     method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>);
     method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational);
     method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterEnabled(boolean);
+    method @NonNull public android.app.PictureInPictureParams.Builder setSeamlessResizeEnabled(boolean);
     method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect);
   }
 
@@ -6920,6 +6929,7 @@
     method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName);
     method @NonNull public java.util.List<byte[]> getInstalledCaCerts(@Nullable android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getKeepUninstalledPackages(@Nullable android.content.ComponentName);
+    method @NonNull public java.util.Set<java.util.Set<java.lang.String>> getKeyPairGrants(@NonNull String);
     method public int getKeyguardDisabledFeatures(@Nullable android.content.ComponentName);
     method public int getLockTaskFeatures(@NonNull android.content.ComponentName);
     method @NonNull public String[] getLockTaskPackages(@NonNull android.content.ComponentName);
@@ -6937,14 +6947,14 @@
     method public long getPasswordExpirationTimeout(@Nullable android.content.ComponentName);
     method public int getPasswordHistoryLength(@Nullable android.content.ComponentName);
     method public int getPasswordMaximumLength(int);
-    method public int getPasswordMinimumLength(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumLetters(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumLowerCase(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumNonLetter(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumNumeric(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumSymbols(@Nullable android.content.ComponentName);
-    method public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName);
-    method public int getPasswordQuality(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumLength(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumLetters(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumLowerCase(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumNonLetter(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumNumeric(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumSymbols(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName);
+    method @Deprecated public int getPasswordQuality(@Nullable android.content.ComponentName);
     method @Nullable public android.app.admin.SystemUpdateInfo getPendingSystemUpdate(@NonNull android.content.ComponentName);
     method public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
     method public int getPermissionPolicy(android.content.ComponentName);
@@ -7068,14 +7078,14 @@
     method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean);
     method public void setPasswordExpirationTimeout(@NonNull android.content.ComponentName, long);
     method public void setPasswordHistoryLength(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumLetters(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumLowerCase(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumNonLetter(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumNumeric(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int);
-    method public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int);
-    method public void setPasswordQuality(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumLetters(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumLowerCase(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumNonLetter(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumNumeric(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int);
+    method @Deprecated public void setPasswordQuality(@NonNull android.content.ComponentName, int);
     method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, @NonNull String, @NonNull String, int);
     method public void setPermissionPolicy(@NonNull android.content.ComponentName, int);
     method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
@@ -7689,7 +7699,8 @@
     method public long getTriggerContentMaxDelay();
     method public long getTriggerContentUpdateDelay();
     method @Nullable public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
-    method public boolean isForegroundJob();
+    method public boolean isExpedited();
+    method @Deprecated public boolean isForegroundJob();
     method public boolean isImportantWhileForeground();
     method public boolean isPeriodic();
     method public boolean isPersisted();
@@ -7720,8 +7731,9 @@
     method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
     method public android.app.job.JobInfo.Builder setClipData(@Nullable android.content.ClipData, int);
     method public android.app.job.JobInfo.Builder setEstimatedNetworkBytes(long, long);
+    method @NonNull public android.app.job.JobInfo.Builder setExpedited(boolean);
     method public android.app.job.JobInfo.Builder setExtras(@NonNull android.os.PersistableBundle);
-    method @NonNull public android.app.job.JobInfo.Builder setForeground(boolean);
+    method @Deprecated @NonNull public android.app.job.JobInfo.Builder setForeground(boolean);
     method @Deprecated public android.app.job.JobInfo.Builder setImportantWhileForeground(boolean);
     method public android.app.job.JobInfo.Builder setMinimumLatency(long);
     method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
@@ -7762,7 +7774,8 @@
     method @NonNull public android.os.Bundle getTransientExtras();
     method @Nullable public String[] getTriggeredContentAuthorities();
     method @Nullable public android.net.Uri[] getTriggeredContentUris();
-    method public boolean isForegroundJob();
+    method public boolean isExpeditedJob();
+    method @Deprecated public boolean isForegroundJob();
     method public boolean isOverrideDeadlineExpired();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.job.JobParameters> CREATOR;
@@ -9516,6 +9529,8 @@
     method @NonNull public java.util.List<java.lang.String> getAssociations();
     method public boolean hasNotificationAccess(android.content.ComponentName);
     method public void requestNotificationAccess(android.content.ComponentName);
+    method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
+    method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
     field public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9536,6 +9551,9 @@
   public interface DeviceFilter<D extends android.os.Parcelable> extends android.os.Parcelable {
   }
 
+  public class DeviceNotAssociatedException extends java.lang.Exception {
+  }
+
   public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
     method public int describeContents();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -10233,6 +10251,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
@@ -12254,6 +12273,7 @@
     field public static final String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = "android.hardware.nfc.hcef";
     field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese";
     field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = "android.hardware.nfc.uicc";
+    field public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level";
     field public static final String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
     field public static final String FEATURE_PC = "android.hardware.type.pc";
     field public static final String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture";
@@ -12454,6 +12474,7 @@
     field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800
     field @Deprecated public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
+    field public static final int PROTECTION_INTERNAL = 4; // 0x4
     field @Deprecated public static final int PROTECTION_MASK_BASE = 15; // 0xf
     field @Deprecated public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
@@ -15276,16 +15297,11 @@
     ctor public PaintFlagsDrawFilter(int, int);
   }
 
-  public final class ParcelableColorSpace extends android.graphics.ColorSpace implements android.os.Parcelable {
+  public final class ParcelableColorSpace implements android.os.Parcelable {
     ctor public ParcelableColorSpace(@NonNull android.graphics.ColorSpace);
     method public int describeContents();
-    method @NonNull public float[] fromXyz(@NonNull float[]);
     method @NonNull public android.graphics.ColorSpace getColorSpace();
-    method public float getMaxValue(int);
-    method public float getMinValue(int);
     method public static boolean isParcelable(@NonNull android.graphics.ColorSpace);
-    method public boolean isWideGamut();
-    method @NonNull public float[] toXyz(@NonNull float[]);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.graphics.ParcelableColorSpace> CREATOR;
   }
@@ -15721,7 +15737,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);
@@ -18521,4812 +18537,6 @@
 
 }
 
-package android.icu.lang {
-
-  public final class UCharacter implements android.icu.lang.UCharacterEnums.ECharacterCategory android.icu.lang.UCharacterEnums.ECharacterDirection {
-    method public static int charCount(int);
-    method public static int codePointAt(CharSequence, int);
-    method public static int codePointAt(char[], int);
-    method public static int codePointAt(char[], int, int);
-    method public static int codePointBefore(CharSequence, int);
-    method public static int codePointBefore(char[], int);
-    method public static int codePointBefore(char[], int, int);
-    method public static int codePointCount(CharSequence, int, int);
-    method public static int codePointCount(char[], int, int);
-    method public static int digit(int, int);
-    method public static int digit(int);
-    method public static int foldCase(int, boolean);
-    method public static String foldCase(String, boolean);
-    method public static int foldCase(int, int);
-    method public static String foldCase(String, int);
-    method public static char forDigit(int, int);
-    method public static android.icu.util.VersionInfo getAge(int);
-    method public static int getBidiPairedBracket(int);
-    method public static int getCharFromExtendedName(String);
-    method public static int getCharFromName(String);
-    method public static int getCharFromNameAlias(String);
-    method public static int getCodePoint(char, char);
-    method public static int getCodePoint(char);
-    method public static int getCombiningClass(int);
-    method public static int getDirection(int);
-    method public static byte getDirectionality(int);
-    method public static String getExtendedName(int);
-    method public static android.icu.util.ValueIterator getExtendedNameIterator();
-    method public static int getHanNumericValue(int);
-    method public static int getIntPropertyMaxValue(int);
-    method public static int getIntPropertyMinValue(int);
-    method public static int getIntPropertyValue(int, int);
-    method public static int getMirror(int);
-    method public static String getName(int);
-    method public static String getName(String, String);
-    method public static String getNameAlias(int);
-    method public static android.icu.util.ValueIterator getNameIterator();
-    method public static int getNumericValue(int);
-    method public static int getPropertyEnum(CharSequence);
-    method public static String getPropertyName(int, int);
-    method public static int getPropertyValueEnum(int, CharSequence);
-    method public static String getPropertyValueName(int, int, int);
-    method public static int getType(int);
-    method public static android.icu.util.RangeValueIterator getTypeIterator();
-    method public static double getUnicodeNumericValue(int);
-    method public static android.icu.util.VersionInfo getUnicodeVersion();
-    method public static boolean hasBinaryProperty(int, int);
-    method public static boolean isBMP(int);
-    method public static boolean isBaseForm(int);
-    method public static boolean isDefined(int);
-    method public static boolean isDigit(int);
-    method public static boolean isHighSurrogate(char);
-    method public static boolean isISOControl(int);
-    method public static boolean isIdentifierIgnorable(int);
-    method public static boolean isJavaIdentifierPart(int);
-    method public static boolean isJavaIdentifierStart(int);
-    method public static boolean isLegal(int);
-    method public static boolean isLegal(String);
-    method public static boolean isLetter(int);
-    method public static boolean isLetterOrDigit(int);
-    method public static boolean isLowSurrogate(char);
-    method public static boolean isLowerCase(int);
-    method public static boolean isMirrored(int);
-    method public static boolean isPrintable(int);
-    method public static boolean isSpaceChar(int);
-    method public static boolean isSupplementary(int);
-    method public static boolean isSupplementaryCodePoint(int);
-    method public static boolean isSurrogatePair(char, char);
-    method public static boolean isTitleCase(int);
-    method public static boolean isUAlphabetic(int);
-    method public static boolean isULowercase(int);
-    method public static boolean isUUppercase(int);
-    method public static boolean isUWhiteSpace(int);
-    method public static boolean isUnicodeIdentifierPart(int);
-    method public static boolean isUnicodeIdentifierStart(int);
-    method public static boolean isUpperCase(int);
-    method public static boolean isValidCodePoint(int);
-    method public static boolean isWhitespace(int);
-    method public static int offsetByCodePoints(CharSequence, int, int);
-    method public static int offsetByCodePoints(char[], int, int, int, int);
-    method public static int toChars(int, char[], int);
-    method public static char[] toChars(int);
-    method public static int toCodePoint(char, char);
-    method public static int toLowerCase(int);
-    method public static String toLowerCase(String);
-    method public static String toLowerCase(java.util.Locale, String);
-    method public static String toLowerCase(android.icu.util.ULocale, String);
-    method public static String toString(int);
-    method public static int toTitleCase(int);
-    method public static String toTitleCase(String, android.icu.text.BreakIterator);
-    method public static String toTitleCase(java.util.Locale, String, android.icu.text.BreakIterator);
-    method public static String toTitleCase(android.icu.util.ULocale, String, android.icu.text.BreakIterator);
-    method public static String toTitleCase(android.icu.util.ULocale, String, android.icu.text.BreakIterator, int);
-    method public static String toTitleCase(java.util.Locale, String, android.icu.text.BreakIterator, int);
-    method public static int toUpperCase(int);
-    method public static String toUpperCase(String);
-    method public static String toUpperCase(java.util.Locale, String);
-    method public static String toUpperCase(android.icu.util.ULocale, String);
-    field public static final int FOLD_CASE_DEFAULT = 0; // 0x0
-    field public static final int FOLD_CASE_EXCLUDE_SPECIAL_I = 1; // 0x1
-    field public static final int MAX_CODE_POINT = 1114111; // 0x10ffff
-    field public static final char MAX_HIGH_SURROGATE = 56319; // 0xdbff '\udbff'
-    field public static final char MAX_LOW_SURROGATE = 57343; // 0xdfff '\udfff'
-    field public static final int MAX_RADIX = 36; // 0x24
-    field public static final char MAX_SURROGATE = 57343; // 0xdfff '\udfff'
-    field public static final int MAX_VALUE = 1114111; // 0x10ffff
-    field public static final int MIN_CODE_POINT = 0; // 0x0
-    field public static final char MIN_HIGH_SURROGATE = 55296; // 0xd800 '\ud800'
-    field public static final char MIN_LOW_SURROGATE = 56320; // 0xdc00 '\udc00'
-    field public static final int MIN_RADIX = 2; // 0x2
-    field public static final int MIN_SUPPLEMENTARY_CODE_POINT = 65536; // 0x10000
-    field public static final char MIN_SURROGATE = 55296; // 0xd800 '\ud800'
-    field public static final int MIN_VALUE = 0; // 0x0
-    field public static final double NO_NUMERIC_VALUE = -1.23456789E8;
-    field public static final int REPLACEMENT_CHAR = 65533; // 0xfffd
-    field public static final int SUPPLEMENTARY_MIN_VALUE = 65536; // 0x10000
-    field public static final int TITLECASE_NO_BREAK_ADJUSTMENT = 512; // 0x200
-    field public static final int TITLECASE_NO_LOWERCASE = 256; // 0x100
-  }
-
-  public static interface UCharacter.BidiPairedBracketType {
-    field public static final int CLOSE = 2; // 0x2
-    field public static final int NONE = 0; // 0x0
-    field public static final int OPEN = 1; // 0x1
-  }
-
-  public static interface UCharacter.DecompositionType {
-    field public static final int CANONICAL = 1; // 0x1
-    field public static final int CIRCLE = 3; // 0x3
-    field public static final int COMPAT = 2; // 0x2
-    field public static final int FINAL = 4; // 0x4
-    field public static final int FONT = 5; // 0x5
-    field public static final int FRACTION = 6; // 0x6
-    field public static final int INITIAL = 7; // 0x7
-    field public static final int ISOLATED = 8; // 0x8
-    field public static final int MEDIAL = 9; // 0x9
-    field public static final int NARROW = 10; // 0xa
-    field public static final int NOBREAK = 11; // 0xb
-    field public static final int NONE = 0; // 0x0
-    field public static final int SMALL = 12; // 0xc
-    field public static final int SQUARE = 13; // 0xd
-    field public static final int SUB = 14; // 0xe
-    field public static final int SUPER = 15; // 0xf
-    field public static final int VERTICAL = 16; // 0x10
-    field public static final int WIDE = 17; // 0x11
-  }
-
-  public static interface UCharacter.EastAsianWidth {
-    field public static final int AMBIGUOUS = 1; // 0x1
-    field public static final int FULLWIDTH = 3; // 0x3
-    field public static final int HALFWIDTH = 2; // 0x2
-    field public static final int NARROW = 4; // 0x4
-    field public static final int NEUTRAL = 0; // 0x0
-    field public static final int WIDE = 5; // 0x5
-  }
-
-  public static interface UCharacter.GraphemeClusterBreak {
-    field public static final int CONTROL = 1; // 0x1
-    field public static final int CR = 2; // 0x2
-    field public static final int EXTEND = 3; // 0x3
-    field public static final int E_BASE = 13; // 0xd
-    field public static final int E_BASE_GAZ = 14; // 0xe
-    field public static final int E_MODIFIER = 15; // 0xf
-    field public static final int GLUE_AFTER_ZWJ = 16; // 0x10
-    field public static final int L = 4; // 0x4
-    field public static final int LF = 5; // 0x5
-    field public static final int LV = 6; // 0x6
-    field public static final int LVT = 7; // 0x7
-    field public static final int OTHER = 0; // 0x0
-    field public static final int PREPEND = 11; // 0xb
-    field public static final int REGIONAL_INDICATOR = 12; // 0xc
-    field public static final int SPACING_MARK = 10; // 0xa
-    field public static final int T = 8; // 0x8
-    field public static final int V = 9; // 0x9
-    field public static final int ZWJ = 17; // 0x11
-  }
-
-  public static interface UCharacter.HangulSyllableType {
-    field public static final int LEADING_JAMO = 1; // 0x1
-    field public static final int LVT_SYLLABLE = 5; // 0x5
-    field public static final int LV_SYLLABLE = 4; // 0x4
-    field public static final int NOT_APPLICABLE = 0; // 0x0
-    field public static final int TRAILING_JAMO = 3; // 0x3
-    field public static final int VOWEL_JAMO = 2; // 0x2
-  }
-
-  public static interface UCharacter.IndicPositionalCategory {
-    field public static final int BOTTOM = 1; // 0x1
-    field public static final int BOTTOM_AND_LEFT = 2; // 0x2
-    field public static final int BOTTOM_AND_RIGHT = 3; // 0x3
-    field public static final int LEFT = 4; // 0x4
-    field public static final int LEFT_AND_RIGHT = 5; // 0x5
-    field public static final int NA = 0; // 0x0
-    field public static final int OVERSTRUCK = 6; // 0x6
-    field public static final int RIGHT = 7; // 0x7
-    field public static final int TOP = 8; // 0x8
-    field public static final int TOP_AND_BOTTOM = 9; // 0x9
-    field public static final int TOP_AND_BOTTOM_AND_LEFT = 15; // 0xf
-    field public static final int TOP_AND_BOTTOM_AND_RIGHT = 10; // 0xa
-    field public static final int TOP_AND_LEFT = 11; // 0xb
-    field public static final int TOP_AND_LEFT_AND_RIGHT = 12; // 0xc
-    field public static final int TOP_AND_RIGHT = 13; // 0xd
-    field public static final int VISUAL_ORDER_LEFT = 14; // 0xe
-  }
-
-  public static interface UCharacter.IndicSyllabicCategory {
-    field public static final int AVAGRAHA = 1; // 0x1
-    field public static final int BINDU = 2; // 0x2
-    field public static final int BRAHMI_JOINING_NUMBER = 3; // 0x3
-    field public static final int CANTILLATION_MARK = 4; // 0x4
-    field public static final int CONSONANT = 5; // 0x5
-    field public static final int CONSONANT_DEAD = 6; // 0x6
-    field public static final int CONSONANT_FINAL = 7; // 0x7
-    field public static final int CONSONANT_HEAD_LETTER = 8; // 0x8
-    field public static final int CONSONANT_INITIAL_POSTFIXED = 9; // 0x9
-    field public static final int CONSONANT_KILLER = 10; // 0xa
-    field public static final int CONSONANT_MEDIAL = 11; // 0xb
-    field public static final int CONSONANT_PLACEHOLDER = 12; // 0xc
-    field public static final int CONSONANT_PRECEDING_REPHA = 13; // 0xd
-    field public static final int CONSONANT_PREFIXED = 14; // 0xe
-    field public static final int CONSONANT_SUBJOINED = 15; // 0xf
-    field public static final int CONSONANT_SUCCEEDING_REPHA = 16; // 0x10
-    field public static final int CONSONANT_WITH_STACKER = 17; // 0x11
-    field public static final int GEMINATION_MARK = 18; // 0x12
-    field public static final int INVISIBLE_STACKER = 19; // 0x13
-    field public static final int JOINER = 20; // 0x14
-    field public static final int MODIFYING_LETTER = 21; // 0x15
-    field public static final int NON_JOINER = 22; // 0x16
-    field public static final int NUKTA = 23; // 0x17
-    field public static final int NUMBER = 24; // 0x18
-    field public static final int NUMBER_JOINER = 25; // 0x19
-    field public static final int OTHER = 0; // 0x0
-    field public static final int PURE_KILLER = 26; // 0x1a
-    field public static final int REGISTER_SHIFTER = 27; // 0x1b
-    field public static final int SYLLABLE_MODIFIER = 28; // 0x1c
-    field public static final int TONE_LETTER = 29; // 0x1d
-    field public static final int TONE_MARK = 30; // 0x1e
-    field public static final int VIRAMA = 31; // 0x1f
-    field public static final int VISARGA = 32; // 0x20
-    field public static final int VOWEL = 33; // 0x21
-    field public static final int VOWEL_DEPENDENT = 34; // 0x22
-    field public static final int VOWEL_INDEPENDENT = 35; // 0x23
-  }
-
-  public static interface UCharacter.JoiningGroup {
-    field public static final int AFRICAN_FEH = 86; // 0x56
-    field public static final int AFRICAN_NOON = 87; // 0x57
-    field public static final int AFRICAN_QAF = 88; // 0x58
-    field public static final int AIN = 1; // 0x1
-    field public static final int ALAPH = 2; // 0x2
-    field public static final int ALEF = 3; // 0x3
-    field public static final int BEH = 4; // 0x4
-    field public static final int BETH = 5; // 0x5
-    field public static final int BURUSHASKI_YEH_BARREE = 54; // 0x36
-    field public static final int DAL = 6; // 0x6
-    field public static final int DALATH_RISH = 7; // 0x7
-    field public static final int E = 8; // 0x8
-    field public static final int FARSI_YEH = 55; // 0x37
-    field public static final int FE = 51; // 0x33
-    field public static final int FEH = 9; // 0x9
-    field public static final int FINAL_SEMKATH = 10; // 0xa
-    field public static final int GAF = 11; // 0xb
-    field public static final int GAMAL = 12; // 0xc
-    field public static final int HAH = 13; // 0xd
-    field public static final int HAMZA_ON_HEH_GOAL = 14; // 0xe
-    field public static final int HANIFI_ROHINGYA_KINNA_YA = 100; // 0x64
-    field public static final int HANIFI_ROHINGYA_PA = 101; // 0x65
-    field public static final int HE = 15; // 0xf
-    field public static final int HEH = 16; // 0x10
-    field public static final int HEH_GOAL = 17; // 0x11
-    field public static final int HETH = 18; // 0x12
-    field public static final int KAF = 19; // 0x13
-    field public static final int KAPH = 20; // 0x14
-    field public static final int KHAPH = 52; // 0x34
-    field public static final int KNOTTED_HEH = 21; // 0x15
-    field public static final int LAM = 22; // 0x16
-    field public static final int LAMADH = 23; // 0x17
-    field public static final int MALAYALAM_BHA = 89; // 0x59
-    field public static final int MALAYALAM_JA = 90; // 0x5a
-    field public static final int MALAYALAM_LLA = 91; // 0x5b
-    field public static final int MALAYALAM_LLLA = 92; // 0x5c
-    field public static final int MALAYALAM_NGA = 93; // 0x5d
-    field public static final int MALAYALAM_NNA = 94; // 0x5e
-    field public static final int MALAYALAM_NNNA = 95; // 0x5f
-    field public static final int MALAYALAM_NYA = 96; // 0x60
-    field public static final int MALAYALAM_RA = 97; // 0x61
-    field public static final int MALAYALAM_SSA = 98; // 0x62
-    field public static final int MALAYALAM_TTA = 99; // 0x63
-    field public static final int MANICHAEAN_ALEPH = 58; // 0x3a
-    field public static final int MANICHAEAN_AYIN = 59; // 0x3b
-    field public static final int MANICHAEAN_BETH = 60; // 0x3c
-    field public static final int MANICHAEAN_DALETH = 61; // 0x3d
-    field public static final int MANICHAEAN_DHAMEDH = 62; // 0x3e
-    field public static final int MANICHAEAN_FIVE = 63; // 0x3f
-    field public static final int MANICHAEAN_GIMEL = 64; // 0x40
-    field public static final int MANICHAEAN_HETH = 65; // 0x41
-    field public static final int MANICHAEAN_HUNDRED = 66; // 0x42
-    field public static final int MANICHAEAN_KAPH = 67; // 0x43
-    field public static final int MANICHAEAN_LAMEDH = 68; // 0x44
-    field public static final int MANICHAEAN_MEM = 69; // 0x45
-    field public static final int MANICHAEAN_NUN = 70; // 0x46
-    field public static final int MANICHAEAN_ONE = 71; // 0x47
-    field public static final int MANICHAEAN_PE = 72; // 0x48
-    field public static final int MANICHAEAN_QOPH = 73; // 0x49
-    field public static final int MANICHAEAN_RESH = 74; // 0x4a
-    field public static final int MANICHAEAN_SADHE = 75; // 0x4b
-    field public static final int MANICHAEAN_SAMEKH = 76; // 0x4c
-    field public static final int MANICHAEAN_TAW = 77; // 0x4d
-    field public static final int MANICHAEAN_TEN = 78; // 0x4e
-    field public static final int MANICHAEAN_TETH = 79; // 0x4f
-    field public static final int MANICHAEAN_THAMEDH = 80; // 0x50
-    field public static final int MANICHAEAN_TWENTY = 81; // 0x51
-    field public static final int MANICHAEAN_WAW = 82; // 0x52
-    field public static final int MANICHAEAN_YODH = 83; // 0x53
-    field public static final int MANICHAEAN_ZAYIN = 84; // 0x54
-    field public static final int MEEM = 24; // 0x18
-    field public static final int MIM = 25; // 0x19
-    field public static final int NOON = 26; // 0x1a
-    field public static final int NO_JOINING_GROUP = 0; // 0x0
-    field public static final int NUN = 27; // 0x1b
-    field public static final int NYA = 56; // 0x38
-    field public static final int PE = 28; // 0x1c
-    field public static final int QAF = 29; // 0x1d
-    field public static final int QAPH = 30; // 0x1e
-    field public static final int REH = 31; // 0x1f
-    field public static final int REVERSED_PE = 32; // 0x20
-    field public static final int ROHINGYA_YEH = 57; // 0x39
-    field public static final int SAD = 33; // 0x21
-    field public static final int SADHE = 34; // 0x22
-    field public static final int SEEN = 35; // 0x23
-    field public static final int SEMKATH = 36; // 0x24
-    field public static final int SHIN = 37; // 0x25
-    field public static final int STRAIGHT_WAW = 85; // 0x55
-    field public static final int SWASH_KAF = 38; // 0x26
-    field public static final int SYRIAC_WAW = 39; // 0x27
-    field public static final int TAH = 40; // 0x28
-    field public static final int TAW = 41; // 0x29
-    field public static final int TEH_MARBUTA = 42; // 0x2a
-    field public static final int TEH_MARBUTA_GOAL = 14; // 0xe
-    field public static final int TETH = 43; // 0x2b
-    field public static final int WAW = 44; // 0x2c
-    field public static final int YEH = 45; // 0x2d
-    field public static final int YEH_BARREE = 46; // 0x2e
-    field public static final int YEH_WITH_TAIL = 47; // 0x2f
-    field public static final int YUDH = 48; // 0x30
-    field public static final int YUDH_HE = 49; // 0x31
-    field public static final int ZAIN = 50; // 0x32
-    field public static final int ZHAIN = 53; // 0x35
-  }
-
-  public static interface UCharacter.JoiningType {
-    field public static final int DUAL_JOINING = 2; // 0x2
-    field public static final int JOIN_CAUSING = 1; // 0x1
-    field public static final int LEFT_JOINING = 3; // 0x3
-    field public static final int NON_JOINING = 0; // 0x0
-    field public static final int RIGHT_JOINING = 4; // 0x4
-    field public static final int TRANSPARENT = 5; // 0x5
-  }
-
-  public static interface UCharacter.LineBreak {
-    field public static final int ALPHABETIC = 2; // 0x2
-    field public static final int AMBIGUOUS = 1; // 0x1
-    field public static final int BREAK_AFTER = 4; // 0x4
-    field public static final int BREAK_BEFORE = 5; // 0x5
-    field public static final int BREAK_BOTH = 3; // 0x3
-    field public static final int BREAK_SYMBOLS = 27; // 0x1b
-    field public static final int CARRIAGE_RETURN = 10; // 0xa
-    field public static final int CLOSE_PARENTHESIS = 36; // 0x24
-    field public static final int CLOSE_PUNCTUATION = 8; // 0x8
-    field public static final int COMBINING_MARK = 9; // 0x9
-    field public static final int COMPLEX_CONTEXT = 24; // 0x18
-    field public static final int CONDITIONAL_JAPANESE_STARTER = 37; // 0x25
-    field public static final int CONTINGENT_BREAK = 7; // 0x7
-    field public static final int EXCLAMATION = 11; // 0xb
-    field public static final int E_BASE = 40; // 0x28
-    field public static final int E_MODIFIER = 41; // 0x29
-    field public static final int GLUE = 12; // 0xc
-    field public static final int H2 = 31; // 0x1f
-    field public static final int H3 = 32; // 0x20
-    field public static final int HEBREW_LETTER = 38; // 0x26
-    field public static final int HYPHEN = 13; // 0xd
-    field public static final int IDEOGRAPHIC = 14; // 0xe
-    field public static final int INFIX_NUMERIC = 16; // 0x10
-    field public static final int INSEPARABLE = 15; // 0xf
-    field public static final int INSEPERABLE = 15; // 0xf
-    field public static final int JL = 33; // 0x21
-    field public static final int JT = 34; // 0x22
-    field public static final int JV = 35; // 0x23
-    field public static final int LINE_FEED = 17; // 0x11
-    field public static final int MANDATORY_BREAK = 6; // 0x6
-    field public static final int NEXT_LINE = 29; // 0x1d
-    field public static final int NONSTARTER = 18; // 0x12
-    field public static final int NUMERIC = 19; // 0x13
-    field public static final int OPEN_PUNCTUATION = 20; // 0x14
-    field public static final int POSTFIX_NUMERIC = 21; // 0x15
-    field public static final int PREFIX_NUMERIC = 22; // 0x16
-    field public static final int QUOTATION = 23; // 0x17
-    field public static final int REGIONAL_INDICATOR = 39; // 0x27
-    field public static final int SPACE = 26; // 0x1a
-    field public static final int SURROGATE = 25; // 0x19
-    field public static final int UNKNOWN = 0; // 0x0
-    field public static final int WORD_JOINER = 30; // 0x1e
-    field public static final int ZWJ = 42; // 0x2a
-    field public static final int ZWSPACE = 28; // 0x1c
-  }
-
-  public static interface UCharacter.NumericType {
-    field public static final int DECIMAL = 1; // 0x1
-    field public static final int DIGIT = 2; // 0x2
-    field public static final int NONE = 0; // 0x0
-    field public static final int NUMERIC = 3; // 0x3
-  }
-
-  public static interface UCharacter.SentenceBreak {
-    field public static final int ATERM = 1; // 0x1
-    field public static final int CLOSE = 2; // 0x2
-    field public static final int CR = 11; // 0xb
-    field public static final int EXTEND = 12; // 0xc
-    field public static final int FORMAT = 3; // 0x3
-    field public static final int LF = 13; // 0xd
-    field public static final int LOWER = 4; // 0x4
-    field public static final int NUMERIC = 5; // 0x5
-    field public static final int OLETTER = 6; // 0x6
-    field public static final int OTHER = 0; // 0x0
-    field public static final int SCONTINUE = 14; // 0xe
-    field public static final int SEP = 7; // 0x7
-    field public static final int SP = 8; // 0x8
-    field public static final int STERM = 9; // 0x9
-    field public static final int UPPER = 10; // 0xa
-  }
-
-  public static final class UCharacter.UnicodeBlock extends java.lang.Character.Subset {
-    method public static android.icu.lang.UCharacter.UnicodeBlock forName(String);
-    method public int getID();
-    method public static android.icu.lang.UCharacter.UnicodeBlock getInstance(int);
-    method public static android.icu.lang.UCharacter.UnicodeBlock of(int);
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ADLAM;
-    field public static final int ADLAM_ID = 263; // 0x107
-    field public static final android.icu.lang.UCharacter.UnicodeBlock AEGEAN_NUMBERS;
-    field public static final int AEGEAN_NUMBERS_ID = 119; // 0x77
-    field public static final android.icu.lang.UCharacter.UnicodeBlock AHOM;
-    field public static final int AHOM_ID = 253; // 0xfd
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ALCHEMICAL_SYMBOLS;
-    field public static final int ALCHEMICAL_SYMBOLS_ID = 208; // 0xd0
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ALPHABETIC_PRESENTATION_FORMS;
-    field public static final int ALPHABETIC_PRESENTATION_FORMS_ID = 80; // 0x50
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ANATOLIAN_HIEROGLYPHS;
-    field public static final int ANATOLIAN_HIEROGLYPHS_ID = 254; // 0xfe
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION;
-    field public static final int ANCIENT_GREEK_MUSICAL_NOTATION_ID = 126; // 0x7e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_GREEK_NUMBERS;
-    field public static final int ANCIENT_GREEK_NUMBERS_ID = 127; // 0x7f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_SYMBOLS;
-    field public static final int ANCIENT_SYMBOLS_ID = 165; // 0xa5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_EXTENDED_A;
-    field public static final int ARABIC_EXTENDED_A_ID = 210; // 0xd2
-    field public static final int ARABIC_ID = 12; // 0xc
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS;
-    field public static final int ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_ID = 211; // 0xd3
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_PRESENTATION_FORMS_A;
-    field public static final int ARABIC_PRESENTATION_FORMS_A_ID = 81; // 0x51
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_PRESENTATION_FORMS_B;
-    field public static final int ARABIC_PRESENTATION_FORMS_B_ID = 85; // 0x55
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_SUPPLEMENT;
-    field public static final int ARABIC_SUPPLEMENT_ID = 128; // 0x80
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARMENIAN;
-    field public static final int ARMENIAN_ID = 10; // 0xa
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ARROWS;
-    field public static final int ARROWS_ID = 46; // 0x2e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock AVESTAN;
-    field public static final int AVESTAN_ID = 188; // 0xbc
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BALINESE;
-    field public static final int BALINESE_ID = 147; // 0x93
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BAMUM;
-    field public static final int BAMUM_ID = 177; // 0xb1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BAMUM_SUPPLEMENT;
-    field public static final int BAMUM_SUPPLEMENT_ID = 202; // 0xca
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BASIC_LATIN;
-    field public static final int BASIC_LATIN_ID = 1; // 0x1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BASSA_VAH;
-    field public static final int BASSA_VAH_ID = 221; // 0xdd
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BATAK;
-    field public static final int BATAK_ID = 199; // 0xc7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BENGALI;
-    field public static final int BENGALI_ID = 16; // 0x10
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BHAIKSUKI;
-    field public static final int BHAIKSUKI_ID = 264; // 0x108
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BLOCK_ELEMENTS;
-    field public static final int BLOCK_ELEMENTS_ID = 53; // 0x35
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BOPOMOFO;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BOPOMOFO_EXTENDED;
-    field public static final int BOPOMOFO_EXTENDED_ID = 67; // 0x43
-    field public static final int BOPOMOFO_ID = 64; // 0x40
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BOX_DRAWING;
-    field public static final int BOX_DRAWING_ID = 52; // 0x34
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BRAHMI;
-    field public static final int BRAHMI_ID = 201; // 0xc9
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BRAILLE_PATTERNS;
-    field public static final int BRAILLE_PATTERNS_ID = 57; // 0x39
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BUGINESE;
-    field public static final int BUGINESE_ID = 129; // 0x81
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BUHID;
-    field public static final int BUHID_ID = 100; // 0x64
-    field public static final android.icu.lang.UCharacter.UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS;
-    field public static final int BYZANTINE_MUSICAL_SYMBOLS_ID = 91; // 0x5b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CARIAN;
-    field public static final int CARIAN_ID = 168; // 0xa8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CAUCASIAN_ALBANIAN;
-    field public static final int CAUCASIAN_ALBANIAN_ID = 222; // 0xde
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHAKMA;
-    field public static final int CHAKMA_ID = 212; // 0xd4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHAM;
-    field public static final int CHAM_ID = 164; // 0xa4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHEROKEE;
-    field public static final int CHEROKEE_ID = 32; // 0x20
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHEROKEE_SUPPLEMENT;
-    field public static final int CHEROKEE_SUPPLEMENT_ID = 255; // 0xff
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHESS_SYMBOLS;
-    field public static final int CHESS_SYMBOLS_ID = 281; // 0x119
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CHORASMIAN;
-    field public static final int CHORASMIAN_ID = 301; // 0x12d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_FORMS;
-    field public static final int CJK_COMPATIBILITY_FORMS_ID = 83; // 0x53
-    field public static final int CJK_COMPATIBILITY_ID = 69; // 0x45
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS;
-    field public static final int CJK_COMPATIBILITY_IDEOGRAPHS_ID = 79; // 0x4f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT;
-    field public static final int CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_ID = 95; // 0x5f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_RADICALS_SUPPLEMENT;
-    field public static final int CJK_RADICALS_SUPPLEMENT_ID = 58; // 0x3a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_STROKES;
-    field public static final int CJK_STROKES_ID = 130; // 0x82
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION;
-    field public static final int CJK_SYMBOLS_AND_PUNCTUATION_ID = 61; // 0x3d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_ID = 70; // 0x46
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_ID = 94; // 0x5e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_ID = 197; // 0xc5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_ID = 209; // 0xd1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E_ID = 256; // 0x100
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F_ID = 274; // 0x112
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G;
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G_ID = 302; // 0x12e
-    field public static final int CJK_UNIFIED_IDEOGRAPHS_ID = 71; // 0x47
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_EXTENDED;
-    field public static final int COMBINING_DIACRITICAL_MARKS_EXTENDED_ID = 224; // 0xe0
-    field public static final int COMBINING_DIACRITICAL_MARKS_ID = 7; // 0x7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT;
-    field public static final int COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_ID = 131; // 0x83
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_HALF_MARKS;
-    field public static final int COMBINING_HALF_MARKS_ID = 82; // 0x52
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS;
-    field public static final int COMBINING_MARKS_FOR_SYMBOLS_ID = 43; // 0x2b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COMMON_INDIC_NUMBER_FORMS;
-    field public static final int COMMON_INDIC_NUMBER_FORMS_ID = 178; // 0xb2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CONTROL_PICTURES;
-    field public static final int CONTROL_PICTURES_ID = 49; // 0x31
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COPTIC;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COPTIC_EPACT_NUMBERS;
-    field public static final int COPTIC_EPACT_NUMBERS_ID = 223; // 0xdf
-    field public static final int COPTIC_ID = 132; // 0x84
-    field public static final android.icu.lang.UCharacter.UnicodeBlock COUNTING_ROD_NUMERALS;
-    field public static final int COUNTING_ROD_NUMERALS_ID = 154; // 0x9a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CUNEIFORM;
-    field public static final int CUNEIFORM_ID = 152; // 0x98
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION;
-    field public static final int CUNEIFORM_NUMBERS_AND_PUNCTUATION_ID = 153; // 0x99
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CURRENCY_SYMBOLS;
-    field public static final int CURRENCY_SYMBOLS_ID = 42; // 0x2a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYPRIOT_SYLLABARY;
-    field public static final int CYPRIOT_SYLLABARY_ID = 123; // 0x7b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_A;
-    field public static final int CYRILLIC_EXTENDED_A_ID = 158; // 0x9e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_B;
-    field public static final int CYRILLIC_EXTENDED_B_ID = 160; // 0xa0
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_C;
-    field public static final int CYRILLIC_EXTENDED_C_ID = 265; // 0x109
-    field public static final int CYRILLIC_ID = 9; // 0x9
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_SUPPLEMENT;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_SUPPLEMENTARY;
-    field public static final int CYRILLIC_SUPPLEMENTARY_ID = 97; // 0x61
-    field public static final int CYRILLIC_SUPPLEMENT_ID = 97; // 0x61
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DESERET;
-    field public static final int DESERET_ID = 90; // 0x5a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DEVANAGARI;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DEVANAGARI_EXTENDED;
-    field public static final int DEVANAGARI_EXTENDED_ID = 179; // 0xb3
-    field public static final int DEVANAGARI_ID = 15; // 0xf
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DINGBATS;
-    field public static final int DINGBATS_ID = 56; // 0x38
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DIVES_AKURU;
-    field public static final int DIVES_AKURU_ID = 303; // 0x12f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DOGRA;
-    field public static final int DOGRA_ID = 282; // 0x11a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DOMINO_TILES;
-    field public static final int DOMINO_TILES_ID = 171; // 0xab
-    field public static final android.icu.lang.UCharacter.UnicodeBlock DUPLOYAN;
-    field public static final int DUPLOYAN_ID = 225; // 0xe1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock EARLY_DYNASTIC_CUNEIFORM;
-    field public static final int EARLY_DYNASTIC_CUNEIFORM_ID = 257; // 0x101
-    field public static final android.icu.lang.UCharacter.UnicodeBlock EGYPTIAN_HIEROGLYPHS;
-    field public static final int EGYPTIAN_HIEROGLYPHS_ID = 194; // 0xc2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS;
-    field public static final int EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS_ID = 292; // 0x124
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ELBASAN;
-    field public static final int ELBASAN_ID = 226; // 0xe2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ELYMAIC;
-    field public static final int ELYMAIC_ID = 293; // 0x125
-    field public static final android.icu.lang.UCharacter.UnicodeBlock EMOTICONS;
-    field public static final int EMOTICONS_ID = 206; // 0xce
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_ALPHANUMERICS;
-    field public static final int ENCLOSED_ALPHANUMERICS_ID = 51; // 0x33
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_ALPHANUMERIC_SUPPLEMENT;
-    field public static final int ENCLOSED_ALPHANUMERIC_SUPPLEMENT_ID = 195; // 0xc3
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS;
-    field public static final int ENCLOSED_CJK_LETTERS_AND_MONTHS_ID = 68; // 0x44
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_IDEOGRAPHIC_SUPPLEMENT;
-    field public static final int ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_ID = 196; // 0xc4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_EXTENDED;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_EXTENDED_A;
-    field public static final int ETHIOPIC_EXTENDED_A_ID = 200; // 0xc8
-    field public static final int ETHIOPIC_EXTENDED_ID = 133; // 0x85
-    field public static final int ETHIOPIC_ID = 31; // 0x1f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_SUPPLEMENT;
-    field public static final int ETHIOPIC_SUPPLEMENT_ID = 134; // 0x86
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GENERAL_PUNCTUATION;
-    field public static final int GENERAL_PUNCTUATION_ID = 40; // 0x28
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GEOMETRIC_SHAPES;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GEOMETRIC_SHAPES_EXTENDED;
-    field public static final int GEOMETRIC_SHAPES_EXTENDED_ID = 227; // 0xe3
-    field public static final int GEOMETRIC_SHAPES_ID = 54; // 0x36
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_EXTENDED;
-    field public static final int GEORGIAN_EXTENDED_ID = 283; // 0x11b
-    field public static final int GEORGIAN_ID = 29; // 0x1d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_SUPPLEMENT;
-    field public static final int GEORGIAN_SUPPLEMENT_ID = 135; // 0x87
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GLAGOLITIC;
-    field public static final int GLAGOLITIC_ID = 136; // 0x88
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GLAGOLITIC_SUPPLEMENT;
-    field public static final int GLAGOLITIC_SUPPLEMENT_ID = 266; // 0x10a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GOTHIC;
-    field public static final int GOTHIC_ID = 89; // 0x59
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GRANTHA;
-    field public static final int GRANTHA_ID = 228; // 0xe4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GREEK;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GREEK_EXTENDED;
-    field public static final int GREEK_EXTENDED_ID = 39; // 0x27
-    field public static final int GREEK_ID = 8; // 0x8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GUJARATI;
-    field public static final int GUJARATI_ID = 18; // 0x12
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GUNJALA_GONDI;
-    field public static final int GUNJALA_GONDI_ID = 284; // 0x11c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock GURMUKHI;
-    field public static final int GURMUKHI_ID = 17; // 0x11
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS;
-    field public static final int HALFWIDTH_AND_FULLWIDTH_FORMS_ID = 87; // 0x57
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_COMPATIBILITY_JAMO;
-    field public static final int HANGUL_COMPATIBILITY_JAMO_ID = 65; // 0x41
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO_EXTENDED_A;
-    field public static final int HANGUL_JAMO_EXTENDED_A_ID = 180; // 0xb4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO_EXTENDED_B;
-    field public static final int HANGUL_JAMO_EXTENDED_B_ID = 185; // 0xb9
-    field public static final int HANGUL_JAMO_ID = 30; // 0x1e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_SYLLABLES;
-    field public static final int HANGUL_SYLLABLES_ID = 74; // 0x4a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANIFI_ROHINGYA;
-    field public static final int HANIFI_ROHINGYA_ID = 285; // 0x11d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HANUNOO;
-    field public static final int HANUNOO_ID = 99; // 0x63
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HATRAN;
-    field public static final int HATRAN_ID = 258; // 0x102
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HEBREW;
-    field public static final int HEBREW_ID = 11; // 0xb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HIGH_PRIVATE_USE_SURROGATES;
-    field public static final int HIGH_PRIVATE_USE_SURROGATES_ID = 76; // 0x4c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HIGH_SURROGATES;
-    field public static final int HIGH_SURROGATES_ID = 75; // 0x4b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock HIRAGANA;
-    field public static final int HIRAGANA_ID = 62; // 0x3e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS;
-    field public static final int IDEOGRAPHIC_DESCRIPTION_CHARACTERS_ID = 60; // 0x3c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION;
-    field public static final int IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION_ID = 267; // 0x10b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock IMPERIAL_ARAMAIC;
-    field public static final int IMPERIAL_ARAMAIC_ID = 186; // 0xba
-    field public static final android.icu.lang.UCharacter.UnicodeBlock INDIC_SIYAQ_NUMBERS;
-    field public static final int INDIC_SIYAQ_NUMBERS_ID = 286; // 0x11e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PAHLAVI;
-    field public static final int INSCRIPTIONAL_PAHLAVI_ID = 190; // 0xbe
-    field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PARTHIAN;
-    field public static final int INSCRIPTIONAL_PARTHIAN_ID = 189; // 0xbd
-    field public static final android.icu.lang.UCharacter.UnicodeBlock INVALID_CODE;
-    field public static final int INVALID_CODE_ID = -1; // 0xffffffff
-    field public static final android.icu.lang.UCharacter.UnicodeBlock IPA_EXTENSIONS;
-    field public static final int IPA_EXTENSIONS_ID = 5; // 0x5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock JAVANESE;
-    field public static final int JAVANESE_ID = 181; // 0xb5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KAITHI;
-    field public static final int KAITHI_ID = 193; // 0xc1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KANA_EXTENDED_A;
-    field public static final int KANA_EXTENDED_A_ID = 275; // 0x113
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KANA_SUPPLEMENT;
-    field public static final int KANA_SUPPLEMENT_ID = 203; // 0xcb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KANBUN;
-    field public static final int KANBUN_ID = 66; // 0x42
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KANGXI_RADICALS;
-    field public static final int KANGXI_RADICALS_ID = 59; // 0x3b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KANNADA;
-    field public static final int KANNADA_ID = 22; // 0x16
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KATAKANA;
-    field public static final int KATAKANA_ID = 63; // 0x3f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS;
-    field public static final int KATAKANA_PHONETIC_EXTENSIONS_ID = 107; // 0x6b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KAYAH_LI;
-    field public static final int KAYAH_LI_ID = 162; // 0xa2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHAROSHTHI;
-    field public static final int KHAROSHTHI_ID = 137; // 0x89
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHITAN_SMALL_SCRIPT;
-    field public static final int KHITAN_SMALL_SCRIPT_ID = 304; // 0x130
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER;
-    field public static final int KHMER_ID = 36; // 0x24
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER_SYMBOLS;
-    field public static final int KHMER_SYMBOLS_ID = 113; // 0x71
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHOJKI;
-    field public static final int KHOJKI_ID = 229; // 0xe5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock KHUDAWADI;
-    field public static final int KHUDAWADI_ID = 230; // 0xe6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LAO;
-    field public static final int LAO_ID = 26; // 0x1a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_1_SUPPLEMENT;
-    field public static final int LATIN_1_SUPPLEMENT_ID = 2; // 0x2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_A;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_ADDITIONAL;
-    field public static final int LATIN_EXTENDED_ADDITIONAL_ID = 38; // 0x26
-    field public static final int LATIN_EXTENDED_A_ID = 3; // 0x3
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_B;
-    field public static final int LATIN_EXTENDED_B_ID = 4; // 0x4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_C;
-    field public static final int LATIN_EXTENDED_C_ID = 148; // 0x94
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_D;
-    field public static final int LATIN_EXTENDED_D_ID = 149; // 0x95
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_E;
-    field public static final int LATIN_EXTENDED_E_ID = 231; // 0xe7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LEPCHA;
-    field public static final int LEPCHA_ID = 156; // 0x9c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LETTERLIKE_SYMBOLS;
-    field public static final int LETTERLIKE_SYMBOLS_ID = 44; // 0x2c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LIMBU;
-    field public static final int LIMBU_ID = 111; // 0x6f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_A;
-    field public static final int LINEAR_A_ID = 232; // 0xe8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_B_IDEOGRAMS;
-    field public static final int LINEAR_B_IDEOGRAMS_ID = 118; // 0x76
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_B_SYLLABARY;
-    field public static final int LINEAR_B_SYLLABARY_ID = 117; // 0x75
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LISU;
-    field public static final int LISU_ID = 176; // 0xb0
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LISU_SUPPLEMENT;
-    field public static final int LISU_SUPPLEMENT_ID = 305; // 0x131
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LOW_SURROGATES;
-    field public static final int LOW_SURROGATES_ID = 77; // 0x4d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LYCIAN;
-    field public static final int LYCIAN_ID = 167; // 0xa7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock LYDIAN;
-    field public static final int LYDIAN_ID = 169; // 0xa9
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MAHAJANI;
-    field public static final int MAHAJANI_ID = 233; // 0xe9
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MAHJONG_TILES;
-    field public static final int MAHJONG_TILES_ID = 170; // 0xaa
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MAKASAR;
-    field public static final int MAKASAR_ID = 287; // 0x11f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MALAYALAM;
-    field public static final int MALAYALAM_ID = 23; // 0x17
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MANDAIC;
-    field public static final int MANDAIC_ID = 198; // 0xc6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MANICHAEAN;
-    field public static final int MANICHAEAN_ID = 234; // 0xea
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MARCHEN;
-    field public static final int MARCHEN_ID = 268; // 0x10c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MASARAM_GONDI;
-    field public static final int MASARAM_GONDI_ID = 276; // 0x114
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS;
-    field public static final int MATHEMATICAL_ALPHANUMERIC_SYMBOLS_ID = 93; // 0x5d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MATHEMATICAL_OPERATORS;
-    field public static final int MATHEMATICAL_OPERATORS_ID = 47; // 0x2f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MAYAN_NUMERALS;
-    field public static final int MAYAN_NUMERALS_ID = 288; // 0x120
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MEDEFAIDRIN;
-    field public static final int MEDEFAIDRIN_ID = 289; // 0x121
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK_EXTENSIONS;
-    field public static final int MEETEI_MAYEK_EXTENSIONS_ID = 213; // 0xd5
-    field public static final int MEETEI_MAYEK_ID = 184; // 0xb8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MENDE_KIKAKUI;
-    field public static final int MENDE_KIKAKUI_ID = 235; // 0xeb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MEROITIC_CURSIVE;
-    field public static final int MEROITIC_CURSIVE_ID = 214; // 0xd6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MEROITIC_HIEROGLYPHS;
-    field public static final int MEROITIC_HIEROGLYPHS_ID = 215; // 0xd7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MIAO;
-    field public static final int MIAO_ID = 216; // 0xd8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A;
-    field public static final int MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_ID = 102; // 0x66
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B;
-    field public static final int MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_ID = 105; // 0x69
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS;
-    field public static final int MISCELLANEOUS_SYMBOLS_AND_ARROWS_ID = 115; // 0x73
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS;
-    field public static final int MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_ID = 205; // 0xcd
-    field public static final int MISCELLANEOUS_SYMBOLS_ID = 55; // 0x37
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_TECHNICAL;
-    field public static final int MISCELLANEOUS_TECHNICAL_ID = 48; // 0x30
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MODI;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MODIFIER_TONE_LETTERS;
-    field public static final int MODIFIER_TONE_LETTERS_ID = 138; // 0x8a
-    field public static final int MODI_ID = 236; // 0xec
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MONGOLIAN;
-    field public static final int MONGOLIAN_ID = 37; // 0x25
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MONGOLIAN_SUPPLEMENT;
-    field public static final int MONGOLIAN_SUPPLEMENT_ID = 269; // 0x10d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MRO;
-    field public static final int MRO_ID = 237; // 0xed
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MULTANI;
-    field public static final int MULTANI_ID = 259; // 0x103
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MUSICAL_SYMBOLS;
-    field public static final int MUSICAL_SYMBOLS_ID = 92; // 0x5c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR_EXTENDED_A;
-    field public static final int MYANMAR_EXTENDED_A_ID = 182; // 0xb6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR_EXTENDED_B;
-    field public static final int MYANMAR_EXTENDED_B_ID = 238; // 0xee
-    field public static final int MYANMAR_ID = 28; // 0x1c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NABATAEAN;
-    field public static final int NABATAEAN_ID = 239; // 0xef
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NANDINAGARI;
-    field public static final int NANDINAGARI_ID = 294; // 0x126
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NEWA;
-    field public static final int NEWA_ID = 270; // 0x10e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NEW_TAI_LUE;
-    field public static final int NEW_TAI_LUE_ID = 139; // 0x8b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NKO;
-    field public static final int NKO_ID = 146; // 0x92
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NO_BLOCK;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NUMBER_FORMS;
-    field public static final int NUMBER_FORMS_ID = 45; // 0x2d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NUSHU;
-    field public static final int NUSHU_ID = 277; // 0x115
-    field public static final android.icu.lang.UCharacter.UnicodeBlock NYIAKENG_PUACHUE_HMONG;
-    field public static final int NYIAKENG_PUACHUE_HMONG_ID = 295; // 0x127
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OGHAM;
-    field public static final int OGHAM_ID = 34; // 0x22
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_HUNGARIAN;
-    field public static final int OLD_HUNGARIAN_ID = 260; // 0x104
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_ITALIC;
-    field public static final int OLD_ITALIC_ID = 88; // 0x58
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_NORTH_ARABIAN;
-    field public static final int OLD_NORTH_ARABIAN_ID = 240; // 0xf0
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_PERMIC;
-    field public static final int OLD_PERMIC_ID = 241; // 0xf1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_PERSIAN;
-    field public static final int OLD_PERSIAN_ID = 140; // 0x8c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOGDIAN;
-    field public static final int OLD_SOGDIAN_ID = 290; // 0x122
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOUTH_ARABIAN;
-    field public static final int OLD_SOUTH_ARABIAN_ID = 187; // 0xbb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_TURKIC;
-    field public static final int OLD_TURKIC_ID = 191; // 0xbf
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OL_CHIKI;
-    field public static final int OL_CHIKI_ID = 157; // 0x9d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OPTICAL_CHARACTER_RECOGNITION;
-    field public static final int OPTICAL_CHARACTER_RECOGNITION_ID = 50; // 0x32
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ORIYA;
-    field public static final int ORIYA_ID = 19; // 0x13
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ORNAMENTAL_DINGBATS;
-    field public static final int ORNAMENTAL_DINGBATS_ID = 242; // 0xf2
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OSAGE;
-    field public static final int OSAGE_ID = 271; // 0x10f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OSMANYA;
-    field public static final int OSMANYA_ID = 122; // 0x7a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock OTTOMAN_SIYAQ_NUMBERS;
-    field public static final int OTTOMAN_SIYAQ_NUMBERS_ID = 296; // 0x128
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PAHAWH_HMONG;
-    field public static final int PAHAWH_HMONG_ID = 243; // 0xf3
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PALMYRENE;
-    field public static final int PALMYRENE_ID = 244; // 0xf4
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PAU_CIN_HAU;
-    field public static final int PAU_CIN_HAU_ID = 245; // 0xf5
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PHAGS_PA;
-    field public static final int PHAGS_PA_ID = 150; // 0x96
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PHAISTOS_DISC;
-    field public static final int PHAISTOS_DISC_ID = 166; // 0xa6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PHOENICIAN;
-    field public static final int PHOENICIAN_ID = 151; // 0x97
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PHONETIC_EXTENSIONS;
-    field public static final int PHONETIC_EXTENSIONS_ID = 114; // 0x72
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT;
-    field public static final int PHONETIC_EXTENSIONS_SUPPLEMENT_ID = 141; // 0x8d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PLAYING_CARDS;
-    field public static final int PLAYING_CARDS_ID = 204; // 0xcc
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PRIVATE_USE;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PRIVATE_USE_AREA;
-    field public static final int PRIVATE_USE_AREA_ID = 78; // 0x4e
-    field public static final int PRIVATE_USE_ID = 78; // 0x4e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock PSALTER_PAHLAVI;
-    field public static final int PSALTER_PAHLAVI_ID = 246; // 0xf6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock REJANG;
-    field public static final int REJANG_ID = 163; // 0xa3
-    field public static final android.icu.lang.UCharacter.UnicodeBlock RUMI_NUMERAL_SYMBOLS;
-    field public static final int RUMI_NUMERAL_SYMBOLS_ID = 192; // 0xc0
-    field public static final android.icu.lang.UCharacter.UnicodeBlock RUNIC;
-    field public static final int RUNIC_ID = 35; // 0x23
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SAMARITAN;
-    field public static final int SAMARITAN_ID = 172; // 0xac
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SAURASHTRA;
-    field public static final int SAURASHTRA_ID = 161; // 0xa1
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SHARADA;
-    field public static final int SHARADA_ID = 217; // 0xd9
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SHAVIAN;
-    field public static final int SHAVIAN_ID = 121; // 0x79
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SHORTHAND_FORMAT_CONTROLS;
-    field public static final int SHORTHAND_FORMAT_CONTROLS_ID = 247; // 0xf7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SIDDHAM;
-    field public static final int SIDDHAM_ID = 248; // 0xf8
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SINHALA;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SINHALA_ARCHAIC_NUMBERS;
-    field public static final int SINHALA_ARCHAIC_NUMBERS_ID = 249; // 0xf9
-    field public static final int SINHALA_ID = 24; // 0x18
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SMALL_FORM_VARIANTS;
-    field public static final int SMALL_FORM_VARIANTS_ID = 84; // 0x54
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SMALL_KANA_EXTENSION;
-    field public static final int SMALL_KANA_EXTENSION_ID = 297; // 0x129
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SOGDIAN;
-    field public static final int SOGDIAN_ID = 291; // 0x123
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SORA_SOMPENG;
-    field public static final int SORA_SOMPENG_ID = 218; // 0xda
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SOYOMBO;
-    field public static final int SOYOMBO_ID = 278; // 0x116
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SPACING_MODIFIER_LETTERS;
-    field public static final int SPACING_MODIFIER_LETTERS_ID = 6; // 0x6
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SPECIALS;
-    field public static final int SPECIALS_ID = 86; // 0x56
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUNDANESE;
-    field public static final int SUNDANESE_ID = 155; // 0x9b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUNDANESE_SUPPLEMENT;
-    field public static final int SUNDANESE_SUPPLEMENT_ID = 219; // 0xdb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS;
-    field public static final int SUPERSCRIPTS_AND_SUBSCRIPTS_ID = 41; // 0x29
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_A;
-    field public static final int SUPPLEMENTAL_ARROWS_A_ID = 103; // 0x67
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_B;
-    field public static final int SUPPLEMENTAL_ARROWS_B_ID = 104; // 0x68
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_C;
-    field public static final int SUPPLEMENTAL_ARROWS_C_ID = 250; // 0xfa
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS;
-    field public static final int SUPPLEMENTAL_MATHEMATICAL_OPERATORS_ID = 106; // 0x6a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_PUNCTUATION;
-    field public static final int SUPPLEMENTAL_PUNCTUATION_ID = 142; // 0x8e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS;
-    field public static final int SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS_ID = 261; // 0x105
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A;
-    field public static final int SUPPLEMENTARY_PRIVATE_USE_AREA_A_ID = 109; // 0x6d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B;
-    field public static final int SUPPLEMENTARY_PRIVATE_USE_AREA_B_ID = 110; // 0x6e
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SUTTON_SIGNWRITING;
-    field public static final int SUTTON_SIGNWRITING_ID = 262; // 0x106
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SYLOTI_NAGRI;
-    field public static final int SYLOTI_NAGRI_ID = 143; // 0x8f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A;
-    field public static final int SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A_ID = 298; // 0x12a
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_FOR_LEGACY_COMPUTING;
-    field public static final int SYMBOLS_FOR_LEGACY_COMPUTING_ID = 306; // 0x132
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC;
-    field public static final int SYRIAC_ID = 13; // 0xd
-    field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC_SUPPLEMENT;
-    field public static final int SYRIAC_SUPPLEMENT_ID = 279; // 0x117
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAGALOG;
-    field public static final int TAGALOG_ID = 98; // 0x62
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAGBANWA;
-    field public static final int TAGBANWA_ID = 101; // 0x65
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAGS;
-    field public static final int TAGS_ID = 96; // 0x60
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_LE;
-    field public static final int TAI_LE_ID = 112; // 0x70
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_THAM;
-    field public static final int TAI_THAM_ID = 174; // 0xae
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_VIET;
-    field public static final int TAI_VIET_ID = 183; // 0xb7
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_XUAN_JING_SYMBOLS;
-    field public static final int TAI_XUAN_JING_SYMBOLS_ID = 124; // 0x7c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAKRI;
-    field public static final int TAKRI_ID = 220; // 0xdc
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAMIL;
-    field public static final int TAMIL_ID = 20; // 0x14
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TAMIL_SUPPLEMENT;
-    field public static final int TAMIL_SUPPLEMENT_ID = 299; // 0x12b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_COMPONENTS;
-    field public static final int TANGUT_COMPONENTS_ID = 273; // 0x111
-    field public static final int TANGUT_ID = 272; // 0x110
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_SUPPLEMENT;
-    field public static final int TANGUT_SUPPLEMENT_ID = 307; // 0x133
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TELUGU;
-    field public static final int TELUGU_ID = 21; // 0x15
-    field public static final android.icu.lang.UCharacter.UnicodeBlock THAANA;
-    field public static final int THAANA_ID = 14; // 0xe
-    field public static final android.icu.lang.UCharacter.UnicodeBlock THAI;
-    field public static final int THAI_ID = 25; // 0x19
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TIBETAN;
-    field public static final int TIBETAN_ID = 27; // 0x1b
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TIFINAGH;
-    field public static final int TIFINAGH_ID = 144; // 0x90
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TIRHUTA;
-    field public static final int TIRHUTA_ID = 251; // 0xfb
-    field public static final android.icu.lang.UCharacter.UnicodeBlock TRANSPORT_AND_MAP_SYMBOLS;
-    field public static final int TRANSPORT_AND_MAP_SYMBOLS_ID = 207; // 0xcf
-    field public static final android.icu.lang.UCharacter.UnicodeBlock UGARITIC;
-    field public static final int UGARITIC_ID = 120; // 0x78
-    field public static final android.icu.lang.UCharacter.UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS;
-    field public static final android.icu.lang.UCharacter.UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED;
-    field public static final int UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_ID = 173; // 0xad
-    field public static final int UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_ID = 33; // 0x21
-    field public static final android.icu.lang.UCharacter.UnicodeBlock VAI;
-    field public static final int VAI_ID = 159; // 0x9f
-    field public static final android.icu.lang.UCharacter.UnicodeBlock VARIATION_SELECTORS;
-    field public static final int VARIATION_SELECTORS_ID = 108; // 0x6c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT;
-    field public static final int VARIATION_SELECTORS_SUPPLEMENT_ID = 125; // 0x7d
-    field public static final android.icu.lang.UCharacter.UnicodeBlock VEDIC_EXTENSIONS;
-    field public static final int VEDIC_EXTENSIONS_ID = 175; // 0xaf
-    field public static final android.icu.lang.UCharacter.UnicodeBlock VERTICAL_FORMS;
-    field public static final int VERTICAL_FORMS_ID = 145; // 0x91
-    field public static final android.icu.lang.UCharacter.UnicodeBlock WANCHO;
-    field public static final int WANCHO_ID = 300; // 0x12c
-    field public static final android.icu.lang.UCharacter.UnicodeBlock WARANG_CITI;
-    field public static final int WARANG_CITI_ID = 252; // 0xfc
-    field public static final android.icu.lang.UCharacter.UnicodeBlock YEZIDI;
-    field public static final int YEZIDI_ID = 308; // 0x134
-    field public static final android.icu.lang.UCharacter.UnicodeBlock YIJING_HEXAGRAM_SYMBOLS;
-    field public static final int YIJING_HEXAGRAM_SYMBOLS_ID = 116; // 0x74
-    field public static final android.icu.lang.UCharacter.UnicodeBlock YI_RADICALS;
-    field public static final int YI_RADICALS_ID = 73; // 0x49
-    field public static final android.icu.lang.UCharacter.UnicodeBlock YI_SYLLABLES;
-    field public static final int YI_SYLLABLES_ID = 72; // 0x48
-    field public static final android.icu.lang.UCharacter.UnicodeBlock ZANABAZAR_SQUARE;
-    field public static final int ZANABAZAR_SQUARE_ID = 280; // 0x118
-  }
-
-  public static interface UCharacter.VerticalOrientation {
-    field public static final int ROTATED = 0; // 0x0
-    field public static final int TRANSFORMED_ROTATED = 1; // 0x1
-    field public static final int TRANSFORMED_UPRIGHT = 2; // 0x2
-    field public static final int UPRIGHT = 3; // 0x3
-  }
-
-  public static interface UCharacter.WordBreak {
-    field public static final int ALETTER = 1; // 0x1
-    field public static final int CR = 8; // 0x8
-    field public static final int DOUBLE_QUOTE = 16; // 0x10
-    field public static final int EXTEND = 9; // 0x9
-    field public static final int EXTENDNUMLET = 7; // 0x7
-    field public static final int E_BASE = 17; // 0x11
-    field public static final int E_BASE_GAZ = 18; // 0x12
-    field public static final int E_MODIFIER = 19; // 0x13
-    field public static final int FORMAT = 2; // 0x2
-    field public static final int GLUE_AFTER_ZWJ = 20; // 0x14
-    field public static final int HEBREW_LETTER = 14; // 0xe
-    field public static final int KATAKANA = 3; // 0x3
-    field public static final int LF = 10; // 0xa
-    field public static final int MIDLETTER = 4; // 0x4
-    field public static final int MIDNUM = 5; // 0x5
-    field public static final int MIDNUMLET = 11; // 0xb
-    field public static final int NEWLINE = 12; // 0xc
-    field public static final int NUMERIC = 6; // 0x6
-    field public static final int OTHER = 0; // 0x0
-    field public static final int REGIONAL_INDICATOR = 13; // 0xd
-    field public static final int SINGLE_QUOTE = 15; // 0xf
-    field public static final int WSEGSPACE = 22; // 0x16
-    field public static final int ZWJ = 21; // 0x15
-  }
-
-  public final class UCharacterCategory implements android.icu.lang.UCharacterEnums.ECharacterCategory {
-    method public static String toString(int);
-  }
-
-  public final class UCharacterDirection implements android.icu.lang.UCharacterEnums.ECharacterDirection {
-    method public static String toString(int);
-  }
-
-  public class UCharacterEnums {
-  }
-
-  public static interface UCharacterEnums.ECharacterCategory {
-    field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
-    field public static final byte CONNECTOR_PUNCTUATION = 22; // 0x16
-    field public static final byte CONTROL = 15; // 0xf
-    field public static final byte CURRENCY_SYMBOL = 25; // 0x19
-    field public static final byte DASH_PUNCTUATION = 19; // 0x13
-    field public static final byte DECIMAL_DIGIT_NUMBER = 9; // 0x9
-    field public static final byte ENCLOSING_MARK = 7; // 0x7
-    field public static final byte END_PUNCTUATION = 21; // 0x15
-    field public static final byte FINAL_PUNCTUATION = 29; // 0x1d
-    field public static final byte FINAL_QUOTE_PUNCTUATION = 29; // 0x1d
-    field public static final byte FORMAT = 16; // 0x10
-    field public static final byte GENERAL_OTHER_TYPES = 0; // 0x0
-    field public static final byte INITIAL_PUNCTUATION = 28; // 0x1c
-    field public static final byte INITIAL_QUOTE_PUNCTUATION = 28; // 0x1c
-    field public static final byte LETTER_NUMBER = 10; // 0xa
-    field public static final byte LINE_SEPARATOR = 13; // 0xd
-    field public static final byte LOWERCASE_LETTER = 2; // 0x2
-    field public static final byte MATH_SYMBOL = 24; // 0x18
-    field public static final byte MODIFIER_LETTER = 4; // 0x4
-    field public static final byte MODIFIER_SYMBOL = 26; // 0x1a
-    field public static final byte NON_SPACING_MARK = 6; // 0x6
-    field public static final byte OTHER_LETTER = 5; // 0x5
-    field public static final byte OTHER_NUMBER = 11; // 0xb
-    field public static final byte OTHER_PUNCTUATION = 23; // 0x17
-    field public static final byte OTHER_SYMBOL = 27; // 0x1b
-    field public static final byte PARAGRAPH_SEPARATOR = 14; // 0xe
-    field public static final byte PRIVATE_USE = 17; // 0x11
-    field public static final byte SPACE_SEPARATOR = 12; // 0xc
-    field public static final byte START_PUNCTUATION = 20; // 0x14
-    field public static final byte SURROGATE = 18; // 0x12
-    field public static final byte TITLECASE_LETTER = 3; // 0x3
-    field public static final byte UNASSIGNED = 0; // 0x0
-    field public static final byte UPPERCASE_LETTER = 1; // 0x1
-  }
-
-  public static interface UCharacterEnums.ECharacterDirection {
-    field public static final int ARABIC_NUMBER = 5; // 0x5
-    field public static final int BLOCK_SEPARATOR = 7; // 0x7
-    field public static final int BOUNDARY_NEUTRAL = 18; // 0x12
-    field public static final int COMMON_NUMBER_SEPARATOR = 6; // 0x6
-    field public static final byte DIRECTIONALITY_ARABIC_NUMBER = 5; // 0x5
-    field public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 18; // 0x12
-    field public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 6; // 0x6
-    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 2; // 0x2
-    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 3; // 0x3
-    field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 4; // 0x4
-    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0; // 0x0
-    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 11; // 0xb
-    field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 12; // 0xc
-    field public static final byte DIRECTIONALITY_NONSPACING_MARK = 17; // 0x11
-    field public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 10; // 0xa
-    field public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 7; // 0x7
-    field public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 16; // 0x10
-    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1; // 0x1
-    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 13; // 0xd
-    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 14; // 0xe
-    field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 15; // 0xf
-    field public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 8; // 0x8
-    field public static final byte DIRECTIONALITY_UNDEFINED = -1; // 0xffffffff
-    field public static final byte DIRECTIONALITY_WHITESPACE = 9; // 0x9
-    field public static final int DIR_NON_SPACING_MARK = 17; // 0x11
-    field public static final int EUROPEAN_NUMBER = 2; // 0x2
-    field public static final int EUROPEAN_NUMBER_SEPARATOR = 3; // 0x3
-    field public static final int EUROPEAN_NUMBER_TERMINATOR = 4; // 0x4
-    field public static final byte FIRST_STRONG_ISOLATE = 19; // 0x13
-    field public static final int LEFT_TO_RIGHT = 0; // 0x0
-    field public static final int LEFT_TO_RIGHT_EMBEDDING = 11; // 0xb
-    field public static final byte LEFT_TO_RIGHT_ISOLATE = 20; // 0x14
-    field public static final int LEFT_TO_RIGHT_OVERRIDE = 12; // 0xc
-    field public static final int OTHER_NEUTRAL = 10; // 0xa
-    field public static final int POP_DIRECTIONAL_FORMAT = 16; // 0x10
-    field public static final byte POP_DIRECTIONAL_ISOLATE = 22; // 0x16
-    field public static final int RIGHT_TO_LEFT = 1; // 0x1
-    field public static final int RIGHT_TO_LEFT_ARABIC = 13; // 0xd
-    field public static final int RIGHT_TO_LEFT_EMBEDDING = 14; // 0xe
-    field public static final byte RIGHT_TO_LEFT_ISOLATE = 21; // 0x15
-    field public static final int RIGHT_TO_LEFT_OVERRIDE = 15; // 0xf
-    field public static final int SEGMENT_SEPARATOR = 8; // 0x8
-    field public static final int WHITE_SPACE_NEUTRAL = 9; // 0x9
-  }
-
-  public interface UProperty {
-    field public static final int AGE = 16384; // 0x4000
-    field public static final int ALPHABETIC = 0; // 0x0
-    field public static final int ASCII_HEX_DIGIT = 1; // 0x1
-    field public static final int BIDI_CLASS = 4096; // 0x1000
-    field public static final int BIDI_CONTROL = 2; // 0x2
-    field public static final int BIDI_MIRRORED = 3; // 0x3
-    field public static final int BIDI_MIRRORING_GLYPH = 16385; // 0x4001
-    field public static final int BIDI_PAIRED_BRACKET = 16397; // 0x400d
-    field public static final int BIDI_PAIRED_BRACKET_TYPE = 4117; // 0x1015
-    field public static final int BINARY_START = 0; // 0x0
-    field public static final int BLOCK = 4097; // 0x1001
-    field public static final int CANONICAL_COMBINING_CLASS = 4098; // 0x1002
-    field public static final int CASED = 49; // 0x31
-    field public static final int CASE_FOLDING = 16386; // 0x4002
-    field public static final int CASE_IGNORABLE = 50; // 0x32
-    field public static final int CASE_SENSITIVE = 34; // 0x22
-    field public static final int CHANGES_WHEN_CASEFOLDED = 54; // 0x36
-    field public static final int CHANGES_WHEN_CASEMAPPED = 55; // 0x37
-    field public static final int CHANGES_WHEN_LOWERCASED = 51; // 0x33
-    field public static final int CHANGES_WHEN_NFKC_CASEFOLDED = 56; // 0x38
-    field public static final int CHANGES_WHEN_TITLECASED = 53; // 0x35
-    field public static final int CHANGES_WHEN_UPPERCASED = 52; // 0x34
-    field public static final int DASH = 4; // 0x4
-    field public static final int DECOMPOSITION_TYPE = 4099; // 0x1003
-    field public static final int DEFAULT_IGNORABLE_CODE_POINT = 5; // 0x5
-    field public static final int DEPRECATED = 6; // 0x6
-    field public static final int DIACRITIC = 7; // 0x7
-    field public static final int DOUBLE_START = 12288; // 0x3000
-    field public static final int EAST_ASIAN_WIDTH = 4100; // 0x1004
-    field public static final int EMOJI = 57; // 0x39
-    field public static final int EMOJI_COMPONENT = 61; // 0x3d
-    field public static final int EMOJI_MODIFIER = 59; // 0x3b
-    field public static final int EMOJI_MODIFIER_BASE = 60; // 0x3c
-    field public static final int EMOJI_PRESENTATION = 58; // 0x3a
-    field public static final int EXTENDED_PICTOGRAPHIC = 64; // 0x40
-    field public static final int EXTENDER = 8; // 0x8
-    field public static final int FULL_COMPOSITION_EXCLUSION = 9; // 0x9
-    field public static final int GENERAL_CATEGORY = 4101; // 0x1005
-    field public static final int GENERAL_CATEGORY_MASK = 8192; // 0x2000
-    field public static final int GRAPHEME_BASE = 10; // 0xa
-    field public static final int GRAPHEME_CLUSTER_BREAK = 4114; // 0x1012
-    field public static final int GRAPHEME_EXTEND = 11; // 0xb
-    field public static final int GRAPHEME_LINK = 12; // 0xc
-    field public static final int HANGUL_SYLLABLE_TYPE = 4107; // 0x100b
-    field public static final int HEX_DIGIT = 13; // 0xd
-    field public static final int HYPHEN = 14; // 0xe
-    field public static final int IDEOGRAPHIC = 17; // 0x11
-    field public static final int IDS_BINARY_OPERATOR = 18; // 0x12
-    field public static final int IDS_TRINARY_OPERATOR = 19; // 0x13
-    field public static final int ID_CONTINUE = 15; // 0xf
-    field public static final int ID_START = 16; // 0x10
-    field public static final int INDIC_POSITIONAL_CATEGORY = 4118; // 0x1016
-    field public static final int INDIC_SYLLABIC_CATEGORY = 4119; // 0x1017
-    field public static final int INT_START = 4096; // 0x1000
-    field public static final int JOINING_GROUP = 4102; // 0x1006
-    field public static final int JOINING_TYPE = 4103; // 0x1007
-    field public static final int JOIN_CONTROL = 20; // 0x14
-    field public static final int LEAD_CANONICAL_COMBINING_CLASS = 4112; // 0x1010
-    field public static final int LINE_BREAK = 4104; // 0x1008
-    field public static final int LOGICAL_ORDER_EXCEPTION = 21; // 0x15
-    field public static final int LOWERCASE = 22; // 0x16
-    field public static final int LOWERCASE_MAPPING = 16388; // 0x4004
-    field public static final int MASK_START = 8192; // 0x2000
-    field public static final int MATH = 23; // 0x17
-    field public static final int NAME = 16389; // 0x4005
-    field public static final int NFC_INERT = 39; // 0x27
-    field public static final int NFC_QUICK_CHECK = 4110; // 0x100e
-    field public static final int NFD_INERT = 37; // 0x25
-    field public static final int NFD_QUICK_CHECK = 4108; // 0x100c
-    field public static final int NFKC_INERT = 40; // 0x28
-    field public static final int NFKC_QUICK_CHECK = 4111; // 0x100f
-    field public static final int NFKD_INERT = 38; // 0x26
-    field public static final int NFKD_QUICK_CHECK = 4109; // 0x100d
-    field public static final int NONCHARACTER_CODE_POINT = 24; // 0x18
-    field public static final int NUMERIC_TYPE = 4105; // 0x1009
-    field public static final int NUMERIC_VALUE = 12288; // 0x3000
-    field public static final int OTHER_PROPERTY_START = 28672; // 0x7000
-    field public static final int PATTERN_SYNTAX = 42; // 0x2a
-    field public static final int PATTERN_WHITE_SPACE = 43; // 0x2b
-    field public static final int POSIX_ALNUM = 44; // 0x2c
-    field public static final int POSIX_BLANK = 45; // 0x2d
-    field public static final int POSIX_GRAPH = 46; // 0x2e
-    field public static final int POSIX_PRINT = 47; // 0x2f
-    field public static final int POSIX_XDIGIT = 48; // 0x30
-    field public static final int PREPENDED_CONCATENATION_MARK = 63; // 0x3f
-    field public static final int QUOTATION_MARK = 25; // 0x19
-    field public static final int RADICAL = 26; // 0x1a
-    field public static final int REGIONAL_INDICATOR = 62; // 0x3e
-    field public static final int SCRIPT = 4106; // 0x100a
-    field public static final int SCRIPT_EXTENSIONS = 28672; // 0x7000
-    field public static final int SEGMENT_STARTER = 41; // 0x29
-    field public static final int SENTENCE_BREAK = 4115; // 0x1013
-    field public static final int SIMPLE_CASE_FOLDING = 16390; // 0x4006
-    field public static final int SIMPLE_LOWERCASE_MAPPING = 16391; // 0x4007
-    field public static final int SIMPLE_TITLECASE_MAPPING = 16392; // 0x4008
-    field public static final int SIMPLE_UPPERCASE_MAPPING = 16393; // 0x4009
-    field public static final int SOFT_DOTTED = 27; // 0x1b
-    field public static final int STRING_START = 16384; // 0x4000
-    field public static final int S_TERM = 35; // 0x23
-    field public static final int TERMINAL_PUNCTUATION = 28; // 0x1c
-    field public static final int TITLECASE_MAPPING = 16394; // 0x400a
-    field public static final int TRAIL_CANONICAL_COMBINING_CLASS = 4113; // 0x1011
-    field public static final int UNIFIED_IDEOGRAPH = 29; // 0x1d
-    field public static final int UPPERCASE = 30; // 0x1e
-    field public static final int UPPERCASE_MAPPING = 16396; // 0x400c
-    field public static final int VARIATION_SELECTOR = 36; // 0x24
-    field public static final int VERTICAL_ORIENTATION = 4120; // 0x1018
-    field public static final int WHITE_SPACE = 31; // 0x1f
-    field public static final int WORD_BREAK = 4116; // 0x1014
-    field public static final int XID_CONTINUE = 32; // 0x20
-    field public static final int XID_START = 33; // 0x21
-  }
-
-  public static interface UProperty.NameChoice {
-    field public static final int LONG = 1; // 0x1
-    field public static final int SHORT = 0; // 0x0
-  }
-
-  public final class UScript {
-    method public static boolean breaksBetweenLetters(int);
-    method public static int[] getCode(java.util.Locale);
-    method public static int[] getCode(android.icu.util.ULocale);
-    method public static int[] getCode(String);
-    method public static int getCodeFromName(String);
-    method public static String getName(int);
-    method public static String getSampleString(int);
-    method public static int getScript(int);
-    method public static int getScriptExtensions(int, java.util.BitSet);
-    method public static String getShortName(int);
-    method public static android.icu.lang.UScript.ScriptUsage getUsage(int);
-    method public static boolean hasScript(int, int);
-    method public static boolean isCased(int);
-    method public static boolean isRightToLeft(int);
-    field public static final int ADLAM = 167; // 0xa7
-    field public static final int AFAKA = 147; // 0x93
-    field public static final int AHOM = 161; // 0xa1
-    field public static final int ANATOLIAN_HIEROGLYPHS = 156; // 0x9c
-    field public static final int ARABIC = 2; // 0x2
-    field public static final int ARMENIAN = 3; // 0x3
-    field public static final int AVESTAN = 117; // 0x75
-    field public static final int BALINESE = 62; // 0x3e
-    field public static final int BAMUM = 130; // 0x82
-    field public static final int BASSA_VAH = 134; // 0x86
-    field public static final int BATAK = 63; // 0x3f
-    field public static final int BENGALI = 4; // 0x4
-    field public static final int BHAIKSUKI = 168; // 0xa8
-    field public static final int BLISSYMBOLS = 64; // 0x40
-    field public static final int BOOK_PAHLAVI = 124; // 0x7c
-    field public static final int BOPOMOFO = 5; // 0x5
-    field public static final int BRAHMI = 65; // 0x41
-    field public static final int BRAILLE = 46; // 0x2e
-    field public static final int BUGINESE = 55; // 0x37
-    field public static final int BUHID = 44; // 0x2c
-    field public static final int CANADIAN_ABORIGINAL = 40; // 0x28
-    field public static final int CARIAN = 104; // 0x68
-    field public static final int CAUCASIAN_ALBANIAN = 159; // 0x9f
-    field public static final int CHAKMA = 118; // 0x76
-    field public static final int CHAM = 66; // 0x42
-    field public static final int CHEROKEE = 6; // 0x6
-    field public static final int CHORASMIAN = 189; // 0xbd
-    field public static final int CIRTH = 67; // 0x43
-    field public static final int COMMON = 0; // 0x0
-    field public static final int COPTIC = 7; // 0x7
-    field public static final int CUNEIFORM = 101; // 0x65
-    field public static final int CYPRIOT = 47; // 0x2f
-    field public static final int CYRILLIC = 8; // 0x8
-    field public static final int DEMOTIC_EGYPTIAN = 69; // 0x45
-    field public static final int DESERET = 9; // 0x9
-    field public static final int DEVANAGARI = 10; // 0xa
-    field public static final int DIVES_AKURU = 190; // 0xbe
-    field public static final int DOGRA = 178; // 0xb2
-    field public static final int DUPLOYAN = 135; // 0x87
-    field public static final int EASTERN_SYRIAC = 97; // 0x61
-    field public static final int EGYPTIAN_HIEROGLYPHS = 71; // 0x47
-    field public static final int ELBASAN = 136; // 0x88
-    field public static final int ELYMAIC = 185; // 0xb9
-    field public static final int ESTRANGELO_SYRIAC = 95; // 0x5f
-    field public static final int ETHIOPIC = 11; // 0xb
-    field public static final int GEORGIAN = 12; // 0xc
-    field public static final int GLAGOLITIC = 56; // 0x38
-    field public static final int GOTHIC = 13; // 0xd
-    field public static final int GRANTHA = 137; // 0x89
-    field public static final int GREEK = 14; // 0xe
-    field public static final int GUJARATI = 15; // 0xf
-    field public static final int GUNJALA_GONDI = 179; // 0xb3
-    field public static final int GURMUKHI = 16; // 0x10
-    field public static final int HAN = 17; // 0x11
-    field public static final int HANGUL = 18; // 0x12
-    field public static final int HANIFI_ROHINGYA = 182; // 0xb6
-    field public static final int HANUNOO = 43; // 0x2b
-    field public static final int HAN_WITH_BOPOMOFO = 172; // 0xac
-    field public static final int HARAPPAN_INDUS = 77; // 0x4d
-    field public static final int HATRAN = 162; // 0xa2
-    field public static final int HEBREW = 19; // 0x13
-    field public static final int HIERATIC_EGYPTIAN = 70; // 0x46
-    field public static final int HIRAGANA = 20; // 0x14
-    field public static final int IMPERIAL_ARAMAIC = 116; // 0x74
-    field public static final int INHERITED = 1; // 0x1
-    field public static final int INSCRIPTIONAL_PAHLAVI = 122; // 0x7a
-    field public static final int INSCRIPTIONAL_PARTHIAN = 125; // 0x7d
-    field public static final int INVALID_CODE = -1; // 0xffffffff
-    field public static final int JAMO = 173; // 0xad
-    field public static final int JAPANESE = 105; // 0x69
-    field public static final int JAVANESE = 78; // 0x4e
-    field public static final int JURCHEN = 148; // 0x94
-    field public static final int KAITHI = 120; // 0x78
-    field public static final int KANNADA = 21; // 0x15
-    field public static final int KATAKANA = 22; // 0x16
-    field public static final int KATAKANA_OR_HIRAGANA = 54; // 0x36
-    field public static final int KAYAH_LI = 79; // 0x4f
-    field public static final int KHAROSHTHI = 57; // 0x39
-    field public static final int KHITAN_SMALL_SCRIPT = 191; // 0xbf
-    field public static final int KHMER = 23; // 0x17
-    field public static final int KHOJKI = 157; // 0x9d
-    field public static final int KHUDAWADI = 145; // 0x91
-    field public static final int KHUTSURI = 72; // 0x48
-    field public static final int KOREAN = 119; // 0x77
-    field public static final int KPELLE = 138; // 0x8a
-    field public static final int LANNA = 106; // 0x6a
-    field public static final int LAO = 24; // 0x18
-    field public static final int LATIN = 25; // 0x19
-    field public static final int LATIN_FRAKTUR = 80; // 0x50
-    field public static final int LATIN_GAELIC = 81; // 0x51
-    field public static final int LEPCHA = 82; // 0x52
-    field public static final int LIMBU = 48; // 0x30
-    field public static final int LINEAR_A = 83; // 0x53
-    field public static final int LINEAR_B = 49; // 0x31
-    field public static final int LISU = 131; // 0x83
-    field public static final int LOMA = 139; // 0x8b
-    field public static final int LYCIAN = 107; // 0x6b
-    field public static final int LYDIAN = 108; // 0x6c
-    field public static final int MAHAJANI = 160; // 0xa0
-    field public static final int MAKASAR = 180; // 0xb4
-    field public static final int MALAYALAM = 26; // 0x1a
-    field public static final int MANDAEAN = 84; // 0x54
-    field public static final int MANDAIC = 84; // 0x54
-    field public static final int MANICHAEAN = 121; // 0x79
-    field public static final int MARCHEN = 169; // 0xa9
-    field public static final int MASARAM_GONDI = 175; // 0xaf
-    field public static final int MATHEMATICAL_NOTATION = 128; // 0x80
-    field public static final int MAYAN_HIEROGLYPHS = 85; // 0x55
-    field public static final int MEDEFAIDRIN = 181; // 0xb5
-    field public static final int MEITEI_MAYEK = 115; // 0x73
-    field public static final int MENDE = 140; // 0x8c
-    field public static final int MEROITIC = 86; // 0x56
-    field public static final int MEROITIC_CURSIVE = 141; // 0x8d
-    field public static final int MEROITIC_HIEROGLYPHS = 86; // 0x56
-    field public static final int MIAO = 92; // 0x5c
-    field public static final int MODI = 163; // 0xa3
-    field public static final int MONGOLIAN = 27; // 0x1b
-    field public static final int MOON = 114; // 0x72
-    field public static final int MRO = 149; // 0x95
-    field public static final int MULTANI = 164; // 0xa4
-    field public static final int MYANMAR = 28; // 0x1c
-    field public static final int NABATAEAN = 143; // 0x8f
-    field public static final int NAKHI_GEBA = 132; // 0x84
-    field public static final int NANDINAGARI = 187; // 0xbb
-    field public static final int NEWA = 170; // 0xaa
-    field public static final int NEW_TAI_LUE = 59; // 0x3b
-    field public static final int NKO = 87; // 0x57
-    field public static final int NUSHU = 150; // 0x96
-    field public static final int NYIAKENG_PUACHUE_HMONG = 186; // 0xba
-    field public static final int OGHAM = 29; // 0x1d
-    field public static final int OLD_CHURCH_SLAVONIC_CYRILLIC = 68; // 0x44
-    field public static final int OLD_HUNGARIAN = 76; // 0x4c
-    field public static final int OLD_ITALIC = 30; // 0x1e
-    field public static final int OLD_NORTH_ARABIAN = 142; // 0x8e
-    field public static final int OLD_PERMIC = 89; // 0x59
-    field public static final int OLD_PERSIAN = 61; // 0x3d
-    field public static final int OLD_SOGDIAN = 184; // 0xb8
-    field public static final int OLD_SOUTH_ARABIAN = 133; // 0x85
-    field public static final int OL_CHIKI = 109; // 0x6d
-    field public static final int ORIYA = 31; // 0x1f
-    field public static final int ORKHON = 88; // 0x58
-    field public static final int OSAGE = 171; // 0xab
-    field public static final int OSMANYA = 50; // 0x32
-    field public static final int PAHAWH_HMONG = 75; // 0x4b
-    field public static final int PALMYRENE = 144; // 0x90
-    field public static final int PAU_CIN_HAU = 165; // 0xa5
-    field public static final int PHAGS_PA = 90; // 0x5a
-    field public static final int PHOENICIAN = 91; // 0x5b
-    field public static final int PHONETIC_POLLARD = 92; // 0x5c
-    field public static final int PSALTER_PAHLAVI = 123; // 0x7b
-    field public static final int REJANG = 110; // 0x6e
-    field public static final int RONGORONGO = 93; // 0x5d
-    field public static final int RUNIC = 32; // 0x20
-    field public static final int SAMARITAN = 126; // 0x7e
-    field public static final int SARATI = 94; // 0x5e
-    field public static final int SAURASHTRA = 111; // 0x6f
-    field public static final int SHARADA = 151; // 0x97
-    field public static final int SHAVIAN = 51; // 0x33
-    field public static final int SIDDHAM = 166; // 0xa6
-    field public static final int SIGN_WRITING = 112; // 0x70
-    field public static final int SIMPLIFIED_HAN = 73; // 0x49
-    field public static final int SINDHI = 145; // 0x91
-    field public static final int SINHALA = 33; // 0x21
-    field public static final int SOGDIAN = 183; // 0xb7
-    field public static final int SORA_SOMPENG = 152; // 0x98
-    field public static final int SOYOMBO = 176; // 0xb0
-    field public static final int SUNDANESE = 113; // 0x71
-    field public static final int SYLOTI_NAGRI = 58; // 0x3a
-    field public static final int SYMBOLS = 129; // 0x81
-    field public static final int SYMBOLS_EMOJI = 174; // 0xae
-    field public static final int SYRIAC = 34; // 0x22
-    field public static final int TAGALOG = 42; // 0x2a
-    field public static final int TAGBANWA = 45; // 0x2d
-    field public static final int TAI_LE = 52; // 0x34
-    field public static final int TAI_VIET = 127; // 0x7f
-    field public static final int TAKRI = 153; // 0x99
-    field public static final int TAMIL = 35; // 0x23
-    field public static final int TANGUT = 154; // 0x9a
-    field public static final int TELUGU = 36; // 0x24
-    field public static final int TENGWAR = 98; // 0x62
-    field public static final int THAANA = 37; // 0x25
-    field public static final int THAI = 38; // 0x26
-    field public static final int TIBETAN = 39; // 0x27
-    field public static final int TIFINAGH = 60; // 0x3c
-    field public static final int TIRHUTA = 158; // 0x9e
-    field public static final int TRADITIONAL_HAN = 74; // 0x4a
-    field public static final int UCAS = 40; // 0x28
-    field public static final int UGARITIC = 53; // 0x35
-    field public static final int UNKNOWN = 103; // 0x67
-    field public static final int UNWRITTEN_LANGUAGES = 102; // 0x66
-    field public static final int VAI = 99; // 0x63
-    field public static final int VISIBLE_SPEECH = 100; // 0x64
-    field public static final int WANCHO = 188; // 0xbc
-    field public static final int WARANG_CITI = 146; // 0x92
-    field public static final int WESTERN_SYRIAC = 96; // 0x60
-    field public static final int WOLEAI = 155; // 0x9b
-    field public static final int YEZIDI = 192; // 0xc0
-    field public static final int YI = 41; // 0x29
-    field public static final int ZANABAZAR_SQUARE = 177; // 0xb1
-  }
-
-  public enum UScript.ScriptUsage {
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage ASPIRATIONAL;
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage EXCLUDED;
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage LIMITED_USE;
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage NOT_ENCODED;
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage RECOMMENDED;
-    enum_constant public static final android.icu.lang.UScript.ScriptUsage UNKNOWN;
-  }
-
-}
-
-package android.icu.math {
-
-  public class BigDecimal extends java.lang.Number implements java.lang.Comparable<android.icu.math.BigDecimal> java.io.Serializable {
-    ctor public BigDecimal(java.math.BigDecimal);
-    ctor public BigDecimal(java.math.BigInteger);
-    ctor public BigDecimal(java.math.BigInteger, int);
-    ctor public BigDecimal(char[]);
-    ctor public BigDecimal(char[], int, int);
-    ctor public BigDecimal(double);
-    ctor public BigDecimal(int);
-    ctor public BigDecimal(long);
-    ctor public BigDecimal(String);
-    method public android.icu.math.BigDecimal abs();
-    method public android.icu.math.BigDecimal abs(android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal add(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal add(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public byte byteValueExact();
-    method public int compareTo(android.icu.math.BigDecimal);
-    method public int compareTo(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, int);
-    method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, int, int);
-    method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal divideInteger(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal divideInteger(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public double doubleValue();
-    method public float floatValue();
-    method public String format(int, int);
-    method public String format(int, int, int, int, int, int);
-    method public int intValue();
-    method public int intValueExact();
-    method public long longValue();
-    method public long longValueExact();
-    method public android.icu.math.BigDecimal max(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal max(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal min(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal min(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal movePointLeft(int);
-    method public android.icu.math.BigDecimal movePointRight(int);
-    method public android.icu.math.BigDecimal multiply(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal multiply(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal negate();
-    method public android.icu.math.BigDecimal negate(android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal plus();
-    method public android.icu.math.BigDecimal plus(android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal pow(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal pow(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public android.icu.math.BigDecimal remainder(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal remainder(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public int scale();
-    method public android.icu.math.BigDecimal setScale(int);
-    method public android.icu.math.BigDecimal setScale(int, int);
-    method public short shortValueExact();
-    method public int signum();
-    method public android.icu.math.BigDecimal subtract(android.icu.math.BigDecimal);
-    method public android.icu.math.BigDecimal subtract(android.icu.math.BigDecimal, android.icu.math.MathContext);
-    method public java.math.BigDecimal toBigDecimal();
-    method public java.math.BigInteger toBigInteger();
-    method public java.math.BigInteger toBigIntegerExact();
-    method public char[] toCharArray();
-    method public java.math.BigInteger unscaledValue();
-    method public static android.icu.math.BigDecimal valueOf(double);
-    method public static android.icu.math.BigDecimal valueOf(long);
-    method public static android.icu.math.BigDecimal valueOf(long, int);
-    field public static final android.icu.math.BigDecimal ONE;
-    field public static final int ROUND_CEILING = 2; // 0x2
-    field public static final int ROUND_DOWN = 1; // 0x1
-    field public static final int ROUND_FLOOR = 3; // 0x3
-    field public static final int ROUND_HALF_DOWN = 5; // 0x5
-    field public static final int ROUND_HALF_EVEN = 6; // 0x6
-    field public static final int ROUND_HALF_UP = 4; // 0x4
-    field public static final int ROUND_UNNECESSARY = 7; // 0x7
-    field public static final int ROUND_UP = 0; // 0x0
-    field public static final android.icu.math.BigDecimal TEN;
-    field public static final android.icu.math.BigDecimal ZERO;
-  }
-
-  public final class MathContext implements java.io.Serializable {
-    ctor public MathContext(int);
-    ctor public MathContext(int, int);
-    ctor public MathContext(int, int, boolean);
-    ctor public MathContext(int, int, boolean, int);
-    method public int getDigits();
-    method public int getForm();
-    method public boolean getLostDigits();
-    method public int getRoundingMode();
-    field public static final android.icu.math.MathContext DEFAULT;
-    field public static final int ENGINEERING = 2; // 0x2
-    field public static final int PLAIN = 0; // 0x0
-    field public static final int ROUND_CEILING = 2; // 0x2
-    field public static final int ROUND_DOWN = 1; // 0x1
-    field public static final int ROUND_FLOOR = 3; // 0x3
-    field public static final int ROUND_HALF_DOWN = 5; // 0x5
-    field public static final int ROUND_HALF_EVEN = 6; // 0x6
-    field public static final int ROUND_HALF_UP = 4; // 0x4
-    field public static final int ROUND_UNNECESSARY = 7; // 0x7
-    field public static final int ROUND_UP = 0; // 0x0
-    field public static final int SCIENTIFIC = 1; // 0x1
-  }
-
-}
-
-package android.icu.number {
-
-  public class CompactNotation extends android.icu.number.Notation {
-  }
-
-  public abstract class CurrencyPrecision extends android.icu.number.Precision {
-    method public android.icu.number.Precision withCurrency(android.icu.util.Currency);
-  }
-
-  public class FormattedNumber implements java.lang.CharSequence {
-    method public char charAt(int);
-    method public int length();
-    method public CharSequence subSequence(int, int);
-    method public java.math.BigDecimal toBigDecimal();
-    method public java.text.AttributedCharacterIterator toCharacterIterator();
-  }
-
-  public class FormattedNumberRange implements java.lang.CharSequence {
-    method public char charAt(int);
-    method public java.math.BigDecimal getFirstBigDecimal();
-    method public android.icu.number.NumberRangeFormatter.RangeIdentityResult getIdentityResult();
-    method public java.math.BigDecimal getSecondBigDecimal();
-    method public int length();
-    method public CharSequence subSequence(int, int);
-    method public java.text.AttributedCharacterIterator toCharacterIterator();
-  }
-
-  public abstract class FractionPrecision extends android.icu.number.Precision {
-    method public android.icu.number.Precision withMaxDigits(int);
-    method public android.icu.number.Precision withMinDigits(int);
-  }
-
-  public class IntegerWidth {
-    method public android.icu.number.IntegerWidth truncateAt(int);
-    method public static android.icu.number.IntegerWidth zeroFillTo(int);
-  }
-
-  public class LocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.LocalizedNumberFormatter> {
-    method public android.icu.number.FormattedNumber format(long);
-    method public android.icu.number.FormattedNumber format(double);
-    method public android.icu.number.FormattedNumber format(Number);
-    method public android.icu.number.FormattedNumber format(android.icu.util.Measure);
-    method public java.text.Format toFormat();
-  }
-
-  public class LocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.LocalizedNumberRangeFormatter> {
-    method public android.icu.number.FormattedNumberRange formatRange(int, int);
-    method public android.icu.number.FormattedNumberRange formatRange(double, double);
-    method public android.icu.number.FormattedNumberRange formatRange(Number, Number);
-  }
-
-  public class Notation {
-    method public static android.icu.number.CompactNotation compactLong();
-    method public static android.icu.number.CompactNotation compactShort();
-    method public static android.icu.number.ScientificNotation engineering();
-    method public static android.icu.number.ScientificNotation scientific();
-    method public static android.icu.number.SimpleNotation simple();
-  }
-
-  public final class NumberFormatter {
-    method public static android.icu.number.UnlocalizedNumberFormatter with();
-    method public static android.icu.number.LocalizedNumberFormatter withLocale(java.util.Locale);
-    method public static android.icu.number.LocalizedNumberFormatter withLocale(android.icu.util.ULocale);
-  }
-
-  public enum NumberFormatter.DecimalSeparatorDisplay {
-    enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay ALWAYS;
-    enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay AUTO;
-  }
-
-  public enum NumberFormatter.GroupingStrategy {
-    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy AUTO;
-    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy MIN2;
-    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy OFF;
-    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy ON_ALIGNED;
-    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy THOUSANDS;
-  }
-
-  public enum NumberFormatter.SignDisplay {
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_ALWAYS;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_EXCEPT_ZERO;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ALWAYS;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay AUTO;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay EXCEPT_ZERO;
-    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay NEVER;
-  }
-
-  public enum NumberFormatter.UnitWidth {
-    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth FULL_NAME;
-    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth HIDDEN;
-    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth ISO_CODE;
-    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth NARROW;
-    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth SHORT;
-  }
-
-  public abstract class NumberFormatterSettings<T extends android.icu.number.NumberFormatterSettings<?>> {
-    method public T decimal(android.icu.number.NumberFormatter.DecimalSeparatorDisplay);
-    method public T grouping(android.icu.number.NumberFormatter.GroupingStrategy);
-    method public T integerWidth(android.icu.number.IntegerWidth);
-    method public T notation(android.icu.number.Notation);
-    method public T perUnit(android.icu.util.MeasureUnit);
-    method public T precision(android.icu.number.Precision);
-    method public T roundingMode(java.math.RoundingMode);
-    method public T scale(android.icu.number.Scale);
-    method public T sign(android.icu.number.NumberFormatter.SignDisplay);
-    method public T symbols(android.icu.text.DecimalFormatSymbols);
-    method public T symbols(android.icu.text.NumberingSystem);
-    method public T unit(android.icu.util.MeasureUnit);
-    method public T unitWidth(android.icu.number.NumberFormatter.UnitWidth);
-  }
-
-  public abstract class NumberRangeFormatter {
-    method public static android.icu.number.UnlocalizedNumberRangeFormatter with();
-    method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(java.util.Locale);
-    method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(android.icu.util.ULocale);
-  }
-
-  public enum NumberRangeFormatter.RangeCollapse {
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse ALL;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse AUTO;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse NONE;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse UNIT;
-  }
-
-  public enum NumberRangeFormatter.RangeIdentityFallback {
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY_OR_SINGLE_VALUE;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback RANGE;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback SINGLE_VALUE;
-  }
-
-  public enum NumberRangeFormatter.RangeIdentityResult {
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_AFTER_ROUNDING;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_BEFORE_ROUNDING;
-    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult NOT_EQUAL;
-  }
-
-  public abstract class NumberRangeFormatterSettings<T extends android.icu.number.NumberRangeFormatterSettings<?>> {
-    method public T collapse(android.icu.number.NumberRangeFormatter.RangeCollapse);
-    method public T identityFallback(android.icu.number.NumberRangeFormatter.RangeIdentityFallback);
-    method public T numberFormatterBoth(android.icu.number.UnlocalizedNumberFormatter);
-    method public T numberFormatterFirst(android.icu.number.UnlocalizedNumberFormatter);
-    method public T numberFormatterSecond(android.icu.number.UnlocalizedNumberFormatter);
-  }
-
-  public abstract class Precision {
-    method public static android.icu.number.CurrencyPrecision currency(android.icu.util.Currency.CurrencyUsage);
-    method public static android.icu.number.FractionPrecision fixedFraction(int);
-    method public static android.icu.number.Precision fixedSignificantDigits(int);
-    method public static android.icu.number.Precision increment(java.math.BigDecimal);
-    method public static android.icu.number.FractionPrecision integer();
-    method public static android.icu.number.FractionPrecision maxFraction(int);
-    method public static android.icu.number.Precision maxSignificantDigits(int);
-    method public static android.icu.number.FractionPrecision minFraction(int);
-    method public static android.icu.number.FractionPrecision minMaxFraction(int, int);
-    method public static android.icu.number.Precision minMaxSignificantDigits(int, int);
-    method public static android.icu.number.Precision minSignificantDigits(int);
-    method public static android.icu.number.Precision unlimited();
-  }
-
-  public class Scale {
-    method public static android.icu.number.Scale byBigDecimal(java.math.BigDecimal);
-    method public static android.icu.number.Scale byDouble(double);
-    method public static android.icu.number.Scale byDoubleAndPowerOfTen(double, int);
-    method public static android.icu.number.Scale none();
-    method public static android.icu.number.Scale powerOfTen(int);
-  }
-
-  public class ScientificNotation extends android.icu.number.Notation {
-    method public android.icu.number.ScientificNotation withExponentSignDisplay(android.icu.number.NumberFormatter.SignDisplay);
-    method public android.icu.number.ScientificNotation withMinExponentDigits(int);
-  }
-
-  public class SimpleNotation extends android.icu.number.Notation {
-  }
-
-  public class UnlocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.UnlocalizedNumberFormatter> {
-    method public android.icu.number.LocalizedNumberFormatter locale(java.util.Locale);
-    method public android.icu.number.LocalizedNumberFormatter locale(android.icu.util.ULocale);
-  }
-
-  public class UnlocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.UnlocalizedNumberRangeFormatter> {
-    method public android.icu.number.LocalizedNumberRangeFormatter locale(java.util.Locale);
-    method public android.icu.number.LocalizedNumberRangeFormatter locale(android.icu.util.ULocale);
-  }
-
-}
-
-package android.icu.text {
-
-  public final class AlphabeticIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> {
-    ctor public AlphabeticIndex(android.icu.util.ULocale);
-    ctor public AlphabeticIndex(java.util.Locale);
-    ctor public AlphabeticIndex(android.icu.text.RuleBasedCollator);
-    method public android.icu.text.AlphabeticIndex<V> addLabels(android.icu.text.UnicodeSet);
-    method public android.icu.text.AlphabeticIndex<V> addLabels(android.icu.util.ULocale...);
-    method public android.icu.text.AlphabeticIndex<V> addLabels(java.util.Locale...);
-    method public android.icu.text.AlphabeticIndex<V> addRecord(CharSequence, V);
-    method public android.icu.text.AlphabeticIndex.ImmutableIndex<V> buildImmutableIndex();
-    method public android.icu.text.AlphabeticIndex<V> clearRecords();
-    method public int getBucketCount();
-    method public int getBucketIndex(CharSequence);
-    method public java.util.List<java.lang.String> getBucketLabels();
-    method public android.icu.text.RuleBasedCollator getCollator();
-    method public String getInflowLabel();
-    method public int getMaxLabelCount();
-    method public String getOverflowLabel();
-    method public int getRecordCount();
-    method public String getUnderflowLabel();
-    method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator();
-    method public android.icu.text.AlphabeticIndex<V> setInflowLabel(String);
-    method public android.icu.text.AlphabeticIndex<V> setMaxLabelCount(int);
-    method public android.icu.text.AlphabeticIndex<V> setOverflowLabel(String);
-    method public android.icu.text.AlphabeticIndex<V> setUnderflowLabel(String);
-  }
-
-  public static class AlphabeticIndex.Bucket<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Record<V>> {
-    method public String getLabel();
-    method public android.icu.text.AlphabeticIndex.Bucket.LabelType getLabelType();
-    method public java.util.Iterator<android.icu.text.AlphabeticIndex.Record<V>> iterator();
-    method public int size();
-  }
-
-  public enum AlphabeticIndex.Bucket.LabelType {
-    enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType INFLOW;
-    enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType NORMAL;
-    enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType OVERFLOW;
-    enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType UNDERFLOW;
-  }
-
-  public static final class AlphabeticIndex.ImmutableIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> {
-    method public android.icu.text.AlphabeticIndex.Bucket<V> getBucket(int);
-    method public int getBucketCount();
-    method public int getBucketIndex(CharSequence);
-    method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator();
-  }
-
-  public static class AlphabeticIndex.Record<V> {
-    method public V getData();
-    method public CharSequence getName();
-  }
-
-  public class Bidi {
-    ctor public Bidi();
-    ctor public Bidi(int, int);
-    ctor public Bidi(String, int);
-    ctor public Bidi(java.text.AttributedCharacterIterator);
-    ctor public Bidi(char[], int, byte[], int, int, int);
-    method public boolean baseIsLeftToRight();
-    method public int countParagraphs();
-    method public int countRuns();
-    method public android.icu.text.Bidi createLineBidi(int, int);
-    method public static byte getBaseDirection(CharSequence);
-    method public int getBaseLevel();
-    method public android.icu.text.BidiClassifier getCustomClassifier();
-    method public int getCustomizedClass(int);
-    method public byte getDirection();
-    method public int getLength();
-    method public byte getLevelAt(int);
-    method public byte[] getLevels();
-    method public int getLogicalIndex(int);
-    method public int[] getLogicalMap();
-    method public android.icu.text.BidiRun getLogicalRun(int);
-    method public byte getParaLevel();
-    method public android.icu.text.BidiRun getParagraph(int);
-    method public android.icu.text.BidiRun getParagraphByIndex(int);
-    method public int getParagraphIndex(int);
-    method public int getProcessedLength();
-    method public int getReorderingMode();
-    method public int getReorderingOptions();
-    method public int getResultLength();
-    method public int getRunCount();
-    method public int getRunLevel(int);
-    method public int getRunLimit(int);
-    method public int getRunStart(int);
-    method public char[] getText();
-    method public String getTextAsString();
-    method public int getVisualIndex(int);
-    method public int[] getVisualMap();
-    method public android.icu.text.BidiRun getVisualRun(int);
-    method public static int[] invertMap(int[]);
-    method public boolean isInverse();
-    method public boolean isLeftToRight();
-    method public boolean isMixed();
-    method public boolean isOrderParagraphsLTR();
-    method public boolean isRightToLeft();
-    method public void orderParagraphsLTR(boolean);
-    method public static int[] reorderLogical(byte[]);
-    method public static int[] reorderVisual(byte[]);
-    method public static void reorderVisually(byte[], int, Object[], int, int);
-    method public static boolean requiresBidi(char[], int, int);
-    method public void setContext(String, String);
-    method public void setCustomClassifier(android.icu.text.BidiClassifier);
-    method public void setInverse(boolean);
-    method public android.icu.text.Bidi setLine(int, int);
-    method public void setPara(String, byte, byte[]);
-    method public void setPara(char[], byte, byte[]);
-    method public void setPara(java.text.AttributedCharacterIterator);
-    method public void setReorderingMode(int);
-    method public void setReorderingOptions(int);
-    method public String writeReordered(int);
-    method public static String writeReverse(String, int);
-    field public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = 126; // 0x7e
-    field public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = 127; // 0x7f
-    field public static final int DIRECTION_LEFT_TO_RIGHT = 0; // 0x0
-    field public static final int DIRECTION_RIGHT_TO_LEFT = 1; // 0x1
-    field public static final short DO_MIRRORING = 2; // 0x2
-    field public static final short INSERT_LRM_FOR_NUMERIC = 4; // 0x4
-    field public static final short KEEP_BASE_COMBINING = 1; // 0x1
-    field public static final byte LEVEL_DEFAULT_LTR = 126; // 0x7e
-    field public static final byte LEVEL_DEFAULT_RTL = 127; // 0x7f
-    field public static final byte LEVEL_OVERRIDE = -128; // 0xffffff80
-    field public static final byte LTR = 0; // 0x0
-    field public static final int MAP_NOWHERE = -1; // 0xffffffff
-    field public static final byte MAX_EXPLICIT_LEVEL = 125; // 0x7d
-    field public static final byte MIXED = 2; // 0x2
-    field public static final byte NEUTRAL = 3; // 0x3
-    field public static final int OPTION_DEFAULT = 0; // 0x0
-    field public static final int OPTION_INSERT_MARKS = 1; // 0x1
-    field public static final int OPTION_REMOVE_CONTROLS = 2; // 0x2
-    field public static final int OPTION_STREAMING = 4; // 0x4
-    field public static final short OUTPUT_REVERSE = 16; // 0x10
-    field public static final short REMOVE_BIDI_CONTROLS = 8; // 0x8
-    field public static final short REORDER_DEFAULT = 0; // 0x0
-    field public static final short REORDER_GROUP_NUMBERS_WITH_R = 2; // 0x2
-    field public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6; // 0x6
-    field public static final short REORDER_INVERSE_LIKE_DIRECT = 5; // 0x5
-    field public static final short REORDER_INVERSE_NUMBERS_AS_L = 4; // 0x4
-    field public static final short REORDER_NUMBERS_SPECIAL = 1; // 0x1
-    field public static final short REORDER_RUNS_ONLY = 3; // 0x3
-    field public static final byte RTL = 1; // 0x1
-  }
-
-  public class BidiClassifier {
-    ctor public BidiClassifier(Object);
-    method public int classify(int);
-    method public Object getContext();
-    method public void setContext(Object);
-  }
-
-  public class BidiRun {
-    method public byte getDirection();
-    method public byte getEmbeddingLevel();
-    method public int getLength();
-    method public int getLimit();
-    method public int getStart();
-    method public boolean isEvenRun();
-    method public boolean isOddRun();
-  }
-
-  public abstract class BreakIterator implements java.lang.Cloneable {
-    ctor protected BreakIterator();
-    method public Object clone();
-    method public abstract int current();
-    method public abstract int first();
-    method public abstract int following(int);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public static android.icu.text.BreakIterator getCharacterInstance();
-    method public static android.icu.text.BreakIterator getCharacterInstance(java.util.Locale);
-    method public static android.icu.text.BreakIterator getCharacterInstance(android.icu.util.ULocale);
-    method public static android.icu.text.BreakIterator getLineInstance();
-    method public static android.icu.text.BreakIterator getLineInstance(java.util.Locale);
-    method public static android.icu.text.BreakIterator getLineInstance(android.icu.util.ULocale);
-    method public int getRuleStatus();
-    method public int getRuleStatusVec(int[]);
-    method public static android.icu.text.BreakIterator getSentenceInstance();
-    method public static android.icu.text.BreakIterator getSentenceInstance(java.util.Locale);
-    method public static android.icu.text.BreakIterator getSentenceInstance(android.icu.util.ULocale);
-    method public abstract java.text.CharacterIterator getText();
-    method @Deprecated public static android.icu.text.BreakIterator getTitleInstance();
-    method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(java.util.Locale);
-    method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(android.icu.util.ULocale);
-    method public static android.icu.text.BreakIterator getWordInstance();
-    method public static android.icu.text.BreakIterator getWordInstance(java.util.Locale);
-    method public static android.icu.text.BreakIterator getWordInstance(android.icu.util.ULocale);
-    method public boolean isBoundary(int);
-    method public abstract int last();
-    method public abstract int next(int);
-    method public abstract int next();
-    method public int preceding(int);
-    method public abstract int previous();
-    method public void setText(String);
-    method public void setText(CharSequence);
-    method public abstract void setText(java.text.CharacterIterator);
-    field public static final int DONE = -1; // 0xffffffff
-    field public static final int KIND_CHARACTER = 0; // 0x0
-    field public static final int KIND_LINE = 2; // 0x2
-    field public static final int KIND_SENTENCE = 3; // 0x3
-    field @Deprecated public static final int KIND_TITLE = 4; // 0x4
-    field public static final int KIND_WORD = 1; // 0x1
-    field public static final int WORD_IDEO = 400; // 0x190
-    field public static final int WORD_IDEO_LIMIT = 500; // 0x1f4
-    field public static final int WORD_KANA = 300; // 0x12c
-    field public static final int WORD_KANA_LIMIT = 400; // 0x190
-    field public static final int WORD_LETTER = 200; // 0xc8
-    field public static final int WORD_LETTER_LIMIT = 300; // 0x12c
-    field public static final int WORD_NONE = 0; // 0x0
-    field public static final int WORD_NONE_LIMIT = 100; // 0x64
-    field public static final int WORD_NUMBER = 100; // 0x64
-    field public static final int WORD_NUMBER_LIMIT = 200; // 0xc8
-  }
-
-  public abstract class CaseMap {
-    method public static android.icu.text.CaseMap.Fold fold();
-    method public abstract android.icu.text.CaseMap omitUnchangedText();
-    method public static android.icu.text.CaseMap.Lower toLower();
-    method public static android.icu.text.CaseMap.Title toTitle();
-    method public static android.icu.text.CaseMap.Upper toUpper();
-  }
-
-  public static final class CaseMap.Fold extends android.icu.text.CaseMap {
-    method public String apply(CharSequence);
-    method public <A extends java.lang.Appendable> A apply(CharSequence, A, android.icu.text.Edits);
-    method public android.icu.text.CaseMap.Fold omitUnchangedText();
-    method public android.icu.text.CaseMap.Fold turkic();
-  }
-
-  public static final class CaseMap.Lower extends android.icu.text.CaseMap {
-    method public String apply(java.util.Locale, CharSequence);
-    method public <A extends java.lang.Appendable> A apply(java.util.Locale, CharSequence, A, android.icu.text.Edits);
-    method public android.icu.text.CaseMap.Lower omitUnchangedText();
-  }
-
-  public static final class CaseMap.Title extends android.icu.text.CaseMap {
-    method public android.icu.text.CaseMap.Title adjustToCased();
-    method public String apply(java.util.Locale, android.icu.text.BreakIterator, CharSequence);
-    method public <A extends java.lang.Appendable> A apply(java.util.Locale, android.icu.text.BreakIterator, CharSequence, A, android.icu.text.Edits);
-    method public android.icu.text.CaseMap.Title noBreakAdjustment();
-    method public android.icu.text.CaseMap.Title noLowercase();
-    method public android.icu.text.CaseMap.Title omitUnchangedText();
-    method public android.icu.text.CaseMap.Title sentences();
-    method public android.icu.text.CaseMap.Title wholeString();
-  }
-
-  public static final class CaseMap.Upper extends android.icu.text.CaseMap {
-    method public String apply(java.util.Locale, CharSequence);
-    method public <A extends java.lang.Appendable> A apply(java.util.Locale, CharSequence, A, android.icu.text.Edits);
-    method public android.icu.text.CaseMap.Upper omitUnchangedText();
-  }
-
-  public final class CollationElementIterator {
-    method public int getMaxExpansion(int);
-    method public int getOffset();
-    method public int next();
-    method public int previous();
-    method public static int primaryOrder(int);
-    method public void reset();
-    method public static int secondaryOrder(int);
-    method public void setOffset(int);
-    method public void setText(String);
-    method public void setText(android.icu.text.UCharacterIterator);
-    method public void setText(java.text.CharacterIterator);
-    method public static int tertiaryOrder(int);
-    field public static final int IGNORABLE = 0; // 0x0
-    field public static final int NULLORDER = -1; // 0xffffffff
-  }
-
-  public final class CollationKey implements java.lang.Comparable<android.icu.text.CollationKey> {
-    ctor public CollationKey(String, byte[]);
-    method public int compareTo(android.icu.text.CollationKey);
-    method public boolean equals(android.icu.text.CollationKey);
-    method public android.icu.text.CollationKey getBound(int, int);
-    method public String getSourceString();
-    method public android.icu.text.CollationKey merge(android.icu.text.CollationKey);
-    method public byte[] toByteArray();
-  }
-
-  public static final class CollationKey.BoundMode {
-    field public static final int LOWER = 0; // 0x0
-    field public static final int UPPER = 1; // 0x1
-    field public static final int UPPER_LONG = 2; // 0x2
-  }
-
-  public abstract class Collator implements java.lang.Cloneable java.util.Comparator<java.lang.Object> android.icu.util.Freezable<android.icu.text.Collator> {
-    ctor protected Collator();
-    method public Object clone() throws java.lang.CloneNotSupportedException;
-    method public android.icu.text.Collator cloneAsThawed();
-    method public abstract int compare(String, String);
-    method public int compare(Object, Object);
-    method public boolean equals(String, String);
-    method public android.icu.text.Collator freeze();
-    method public static java.util.Locale[] getAvailableLocales();
-    method public static final android.icu.util.ULocale[] getAvailableULocales();
-    method public abstract android.icu.text.CollationKey getCollationKey(String);
-    method public int getDecomposition();
-    method public static String getDisplayName(java.util.Locale, java.util.Locale);
-    method public static String getDisplayName(android.icu.util.ULocale, android.icu.util.ULocale);
-    method public static String getDisplayName(java.util.Locale);
-    method public static String getDisplayName(android.icu.util.ULocale);
-    method public static int[] getEquivalentReorderCodes(int);
-    method public static final android.icu.util.ULocale getFunctionalEquivalent(String, android.icu.util.ULocale, boolean[]);
-    method public static final android.icu.util.ULocale getFunctionalEquivalent(String, android.icu.util.ULocale);
-    method public static final android.icu.text.Collator getInstance();
-    method public static final android.icu.text.Collator getInstance(android.icu.util.ULocale);
-    method public static final android.icu.text.Collator getInstance(java.util.Locale);
-    method public static final String[] getKeywordValues(String);
-    method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean);
-    method public static final String[] getKeywords();
-    method public int getMaxVariable();
-    method public int[] getReorderCodes();
-    method public int getStrength();
-    method public android.icu.text.UnicodeSet getTailoredSet();
-    method public abstract android.icu.util.VersionInfo getUCAVersion();
-    method public abstract int getVariableTop();
-    method public abstract android.icu.util.VersionInfo getVersion();
-    method public boolean isFrozen();
-    method public void setDecomposition(int);
-    method public android.icu.text.Collator setMaxVariable(int);
-    method public void setReorderCodes(int...);
-    method public void setStrength(int);
-    field public static final int CANONICAL_DECOMPOSITION = 17; // 0x11
-    field public static final int FULL_DECOMPOSITION = 15; // 0xf
-    field public static final int IDENTICAL = 15; // 0xf
-    field public static final int NO_DECOMPOSITION = 16; // 0x10
-    field public static final int PRIMARY = 0; // 0x0
-    field public static final int QUATERNARY = 3; // 0x3
-    field public static final int SECONDARY = 1; // 0x1
-    field public static final int TERTIARY = 2; // 0x2
-  }
-
-  public static interface Collator.ReorderCodes {
-    field public static final int CURRENCY = 4099; // 0x1003
-    field public static final int DEFAULT = -1; // 0xffffffff
-    field public static final int DIGIT = 4100; // 0x1004
-    field public static final int FIRST = 4096; // 0x1000
-    field public static final int NONE = 103; // 0x67
-    field public static final int OTHERS = 103; // 0x67
-    field public static final int PUNCTUATION = 4097; // 0x1001
-    field public static final int SPACE = 4096; // 0x1000
-    field public static final int SYMBOL = 4098; // 0x1002
-  }
-
-  public class CompactDecimalFormat extends android.icu.text.DecimalFormat {
-    method public static android.icu.text.CompactDecimalFormat getInstance(android.icu.util.ULocale, android.icu.text.CompactDecimalFormat.CompactStyle);
-    method public static android.icu.text.CompactDecimalFormat getInstance(java.util.Locale, android.icu.text.CompactDecimalFormat.CompactStyle);
-  }
-
-  public enum CompactDecimalFormat.CompactStyle {
-    enum_constant public static final android.icu.text.CompactDecimalFormat.CompactStyle LONG;
-    enum_constant public static final android.icu.text.CompactDecimalFormat.CompactStyle SHORT;
-  }
-
-  public class CurrencyPluralInfo implements java.lang.Cloneable java.io.Serializable {
-    ctor public CurrencyPluralInfo();
-    ctor public CurrencyPluralInfo(java.util.Locale);
-    ctor public CurrencyPluralInfo(android.icu.util.ULocale);
-    method public Object clone();
-    method public String getCurrencyPluralPattern(String);
-    method public static android.icu.text.CurrencyPluralInfo getInstance();
-    method public static android.icu.text.CurrencyPluralInfo getInstance(java.util.Locale);
-    method public static android.icu.text.CurrencyPluralInfo getInstance(android.icu.util.ULocale);
-    method public android.icu.util.ULocale getLocale();
-    method public android.icu.text.PluralRules getPluralRules();
-    method public void setCurrencyPluralPattern(String, String);
-    method public void setLocale(android.icu.util.ULocale);
-    method public void setPluralRules(String);
-  }
-
-  public abstract class DateFormat extends android.icu.text.UFormat {
-    ctor protected DateFormat();
-    method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public abstract StringBuffer format(android.icu.util.Calendar, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(java.util.Date, StringBuffer, java.text.FieldPosition);
-    method public final String format(java.util.Date);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public boolean getBooleanAttribute(android.icu.text.DateFormat.BooleanAttribute);
-    method public android.icu.util.Calendar getCalendar();
-    method public android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
-    method public static final android.icu.text.DateFormat getDateInstance();
-    method public static final android.icu.text.DateFormat getDateInstance(int);
-    method public static final android.icu.text.DateFormat getDateInstance(int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getDateInstance(int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int);
-    method public static final android.icu.text.DateFormat getDateTimeInstance();
-    method public static final android.icu.text.DateFormat getDateTimeInstance(int, int);
-    method public static final android.icu.text.DateFormat getDateTimeInstance(int, int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getDateTimeInstance(int, int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int);
-    method public static final android.icu.text.DateFormat getInstance();
-    method public static final android.icu.text.DateFormat getInstance(android.icu.util.Calendar, java.util.Locale);
-    method public static final android.icu.text.DateFormat getInstance(android.icu.util.Calendar);
-    method public static final android.icu.text.DateFormat getInstanceForSkeleton(String);
-    method public static final android.icu.text.DateFormat getInstanceForSkeleton(String, java.util.Locale);
-    method public static final android.icu.text.DateFormat getInstanceForSkeleton(String, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getInstanceForSkeleton(android.icu.util.Calendar, String, java.util.Locale);
-    method public static final android.icu.text.DateFormat getInstanceForSkeleton(android.icu.util.Calendar, String, android.icu.util.ULocale);
-    method public android.icu.text.NumberFormat getNumberFormat();
-    method public static final android.icu.text.DateFormat getPatternInstance(String);
-    method public static final android.icu.text.DateFormat getPatternInstance(String, java.util.Locale);
-    method public static final android.icu.text.DateFormat getPatternInstance(String, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getPatternInstance(android.icu.util.Calendar, String, java.util.Locale);
-    method public static final android.icu.text.DateFormat getPatternInstance(android.icu.util.Calendar, String, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getTimeInstance();
-    method public static final android.icu.text.DateFormat getTimeInstance(int);
-    method public static final android.icu.text.DateFormat getTimeInstance(int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getTimeInstance(int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int, java.util.Locale);
-    method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int, android.icu.util.ULocale);
-    method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int);
-    method public android.icu.util.TimeZone getTimeZone();
-    method public boolean isCalendarLenient();
-    method public boolean isLenient();
-    method public java.util.Date parse(String) throws java.text.ParseException;
-    method public abstract void parse(String, android.icu.util.Calendar, java.text.ParsePosition);
-    method public java.util.Date parse(String, java.text.ParsePosition);
-    method public Object parseObject(String, java.text.ParsePosition);
-    method public android.icu.text.DateFormat setBooleanAttribute(android.icu.text.DateFormat.BooleanAttribute, boolean);
-    method public void setCalendar(android.icu.util.Calendar);
-    method public void setCalendarLenient(boolean);
-    method public void setContext(android.icu.text.DisplayContext);
-    method public void setLenient(boolean);
-    method public void setNumberFormat(android.icu.text.NumberFormat);
-    method public void setTimeZone(android.icu.util.TimeZone);
-    field public static final String ABBR_GENERIC_TZ = "v";
-    field public static final String ABBR_MONTH = "MMM";
-    field public static final String ABBR_MONTH_DAY = "MMMd";
-    field public static final String ABBR_MONTH_WEEKDAY_DAY = "MMMEd";
-    field public static final String ABBR_QUARTER = "QQQ";
-    field public static final String ABBR_SPECIFIC_TZ = "z";
-    field public static final String ABBR_UTC_TZ = "ZZZZ";
-    field public static final String ABBR_WEEKDAY = "E";
-    field public static final int AM_PM_FIELD = 14; // 0xe
-    field public static final int AM_PM_MIDNIGHT_NOON_FIELD = 35; // 0x23
-    field public static final int DATE_FIELD = 3; // 0x3
-    field public static final String DAY = "d";
-    field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9
-    field public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11; // 0xb
-    field public static final int DAY_OF_YEAR_FIELD = 10; // 0xa
-    field public static final int DEFAULT = 2; // 0x2
-    field public static final int DOW_LOCAL_FIELD = 19; // 0x13
-    field public static final int ERA_FIELD = 0; // 0x0
-    field public static final int EXTENDED_YEAR_FIELD = 20; // 0x14
-    field public static final int FLEXIBLE_DAY_PERIOD_FIELD = 36; // 0x24
-    field public static final int FRACTIONAL_SECOND_FIELD = 8; // 0x8
-    field public static final int FULL = 0; // 0x0
-    field public static final String GENERIC_TZ = "vvvv";
-    field public static final String HOUR = "j";
-    field public static final int HOUR0_FIELD = 16; // 0x10
-    field public static final int HOUR1_FIELD = 15; // 0xf
-    field public static final String HOUR24 = "H";
-    field public static final String HOUR24_MINUTE = "Hm";
-    field public static final String HOUR24_MINUTE_SECOND = "Hms";
-    field public static final String HOUR_MINUTE = "jm";
-    field public static final String HOUR_MINUTE_SECOND = "jms";
-    field public static final int HOUR_OF_DAY0_FIELD = 5; // 0x5
-    field public static final int HOUR_OF_DAY1_FIELD = 4; // 0x4
-    field public static final int JULIAN_DAY_FIELD = 21; // 0x15
-    field public static final String LOCATION_TZ = "VVVV";
-    field public static final int LONG = 1; // 0x1
-    field public static final int MEDIUM = 2; // 0x2
-    field public static final int MILLISECONDS_IN_DAY_FIELD = 22; // 0x16
-    field public static final int MILLISECOND_FIELD = 8; // 0x8
-    field public static final String MINUTE = "m";
-    field public static final int MINUTE_FIELD = 6; // 0x6
-    field public static final String MINUTE_SECOND = "ms";
-    field public static final String MONTH = "MMMM";
-    field public static final String MONTH_DAY = "MMMMd";
-    field public static final int MONTH_FIELD = 2; // 0x2
-    field public static final String MONTH_WEEKDAY_DAY = "MMMMEEEEd";
-    field public static final int NONE = -1; // 0xffffffff
-    field public static final String NUM_MONTH = "M";
-    field public static final String NUM_MONTH_DAY = "Md";
-    field public static final String NUM_MONTH_WEEKDAY_DAY = "MEd";
-    field public static final String QUARTER = "QQQQ";
-    field public static final int QUARTER_FIELD = 27; // 0x1b
-    field public static final int RELATIVE = 128; // 0x80
-    field public static final int RELATIVE_DEFAULT = 130; // 0x82
-    field public static final int RELATIVE_FULL = 128; // 0x80
-    field public static final int RELATIVE_LONG = 129; // 0x81
-    field public static final int RELATIVE_MEDIUM = 130; // 0x82
-    field public static final int RELATIVE_SHORT = 131; // 0x83
-    field public static final String SECOND = "s";
-    field public static final int SECOND_FIELD = 7; // 0x7
-    field public static final int SHORT = 3; // 0x3
-    field public static final String SPECIFIC_TZ = "zzzz";
-    field public static final int STANDALONE_DAY_FIELD = 25; // 0x19
-    field public static final int STANDALONE_MONTH_FIELD = 26; // 0x1a
-    field public static final int STANDALONE_QUARTER_FIELD = 28; // 0x1c
-    field public static final int TIMEZONE_FIELD = 17; // 0x11
-    field public static final int TIMEZONE_GENERIC_FIELD = 24; // 0x18
-    field public static final int TIMEZONE_ISO_FIELD = 32; // 0x20
-    field public static final int TIMEZONE_ISO_LOCAL_FIELD = 33; // 0x21
-    field public static final int TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31; // 0x1f
-    field public static final int TIMEZONE_RFC_FIELD = 23; // 0x17
-    field public static final int TIMEZONE_SPECIAL_FIELD = 29; // 0x1d
-    field public static final String WEEKDAY = "EEEE";
-    field public static final int WEEK_OF_MONTH_FIELD = 13; // 0xd
-    field public static final int WEEK_OF_YEAR_FIELD = 12; // 0xc
-    field public static final String YEAR = "y";
-    field public static final String YEAR_ABBR_MONTH = "yMMM";
-    field public static final String YEAR_ABBR_MONTH_DAY = "yMMMd";
-    field public static final String YEAR_ABBR_MONTH_WEEKDAY_DAY = "yMMMEd";
-    field public static final String YEAR_ABBR_QUARTER = "yQQQ";
-    field public static final int YEAR_FIELD = 1; // 0x1
-    field public static final String YEAR_MONTH = "yMMMM";
-    field public static final String YEAR_MONTH_DAY = "yMMMMd";
-    field public static final String YEAR_MONTH_WEEKDAY_DAY = "yMMMMEEEEd";
-    field public static final int YEAR_NAME_FIELD = 30; // 0x1e
-    field public static final String YEAR_NUM_MONTH = "yM";
-    field public static final String YEAR_NUM_MONTH_DAY = "yMd";
-    field public static final String YEAR_NUM_MONTH_WEEKDAY_DAY = "yMEd";
-    field public static final String YEAR_QUARTER = "yQQQQ";
-    field public static final int YEAR_WOY_FIELD = 18; // 0x12
-    field protected android.icu.util.Calendar calendar;
-    field protected android.icu.text.NumberFormat numberFormat;
-  }
-
-  public enum DateFormat.BooleanAttribute {
-    enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_ALLOW_NUMERIC;
-    enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_ALLOW_WHITESPACE;
-    enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_MULTIPLE_PATTERNS_FOR_MATCH;
-    enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_PARTIAL_LITERAL_MATCH;
-  }
-
-  public static class DateFormat.Field extends java.text.Format.Field {
-    ctor protected DateFormat.Field(String, int);
-    method public int getCalendarField();
-    method public static android.icu.text.DateFormat.Field ofCalendarField(int);
-    field public static final android.icu.text.DateFormat.Field AM_PM;
-    field public static final android.icu.text.DateFormat.Field AM_PM_MIDNIGHT_NOON;
-    field public static final android.icu.text.DateFormat.Field DAY_OF_MONTH;
-    field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK;
-    field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH;
-    field public static final android.icu.text.DateFormat.Field DAY_OF_YEAR;
-    field public static final android.icu.text.DateFormat.Field DOW_LOCAL;
-    field public static final android.icu.text.DateFormat.Field ERA;
-    field public static final android.icu.text.DateFormat.Field EXTENDED_YEAR;
-    field public static final android.icu.text.DateFormat.Field FLEXIBLE_DAY_PERIOD;
-    field public static final android.icu.text.DateFormat.Field HOUR0;
-    field public static final android.icu.text.DateFormat.Field HOUR1;
-    field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY0;
-    field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY1;
-    field public static final android.icu.text.DateFormat.Field JULIAN_DAY;
-    field public static final android.icu.text.DateFormat.Field MILLISECOND;
-    field public static final android.icu.text.DateFormat.Field MILLISECONDS_IN_DAY;
-    field public static final android.icu.text.DateFormat.Field MINUTE;
-    field public static final android.icu.text.DateFormat.Field MONTH;
-    field public static final android.icu.text.DateFormat.Field QUARTER;
-    field public static final android.icu.text.DateFormat.Field SECOND;
-    field public static final android.icu.text.DateFormat.Field TIME_ZONE;
-    field public static final android.icu.text.DateFormat.Field WEEK_OF_MONTH;
-    field public static final android.icu.text.DateFormat.Field WEEK_OF_YEAR;
-    field public static final android.icu.text.DateFormat.Field YEAR;
-    field public static final android.icu.text.DateFormat.Field YEAR_WOY;
-  }
-
-  public class DateFormatSymbols implements java.lang.Cloneable java.io.Serializable {
-    ctor public DateFormatSymbols();
-    ctor public DateFormatSymbols(java.util.Locale);
-    ctor public DateFormatSymbols(android.icu.util.ULocale);
-    ctor public DateFormatSymbols(android.icu.util.Calendar, java.util.Locale);
-    ctor public DateFormatSymbols(android.icu.util.Calendar, android.icu.util.ULocale);
-    ctor public DateFormatSymbols(Class<? extends android.icu.util.Calendar>, java.util.Locale);
-    ctor public DateFormatSymbols(Class<? extends android.icu.util.Calendar>, android.icu.util.ULocale);
-    ctor public DateFormatSymbols(java.util.ResourceBundle, java.util.Locale);
-    ctor public DateFormatSymbols(java.util.ResourceBundle, android.icu.util.ULocale);
-    method public Object clone();
-    method public String[] getAmPmStrings();
-    method public static java.util.Locale[] getAvailableLocales();
-    method public String[] getEraNames();
-    method public String[] getEras();
-    method public static android.icu.text.DateFormatSymbols getInstance();
-    method public static android.icu.text.DateFormatSymbols getInstance(java.util.Locale);
-    method public static android.icu.text.DateFormatSymbols getInstance(android.icu.util.ULocale);
-    method public String getLocalPatternChars();
-    method public String[] getMonths();
-    method public String[] getMonths(int, int);
-    method public String[] getQuarters(int, int);
-    method public String[] getShortMonths();
-    method public String[] getShortWeekdays();
-    method public String[] getWeekdays();
-    method public String[] getWeekdays(int, int);
-    method public String[] getYearNames(int, int);
-    method public String[] getZodiacNames(int, int);
-    method public String[][] getZoneStrings();
-    method protected void initializeData(android.icu.util.ULocale, String);
-    method public void setAmPmStrings(String[]);
-    method public void setEraNames(String[]);
-    method public void setEras(String[]);
-    method public void setLocalPatternChars(String);
-    method public void setMonths(String[]);
-    method public void setMonths(String[], int, int);
-    method public void setQuarters(String[], int, int);
-    method public void setShortMonths(String[]);
-    method public void setShortWeekdays(String[]);
-    method public void setWeekdays(String[], int, int);
-    method public void setWeekdays(String[]);
-    method public void setYearNames(String[], int, int);
-    method public void setZodiacNames(String[], int, int);
-    method public void setZoneStrings(String[][]);
-    field public static final int ABBREVIATED = 0; // 0x0
-    field public static final int FORMAT = 0; // 0x0
-    field public static final int NARROW = 2; // 0x2
-    field public static final int SHORT = 3; // 0x3
-    field public static final int STANDALONE = 1; // 0x1
-    field public static final int WIDE = 1; // 0x1
-  }
-
-  public class DateIntervalFormat extends android.icu.text.UFormat {
-    method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public final StringBuffer format(android.icu.util.DateInterval, StringBuffer, java.text.FieldPosition);
-    method public final StringBuffer format(android.icu.util.Calendar, android.icu.util.Calendar, StringBuffer, java.text.FieldPosition);
-    method public android.icu.text.DateFormat getDateFormat();
-    method public android.icu.text.DateIntervalInfo getDateIntervalInfo();
-    method public static final android.icu.text.DateIntervalFormat getInstance(String);
-    method public static final android.icu.text.DateIntervalFormat getInstance(String, java.util.Locale);
-    method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.util.ULocale);
-    method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.text.DateIntervalInfo);
-    method public static final android.icu.text.DateIntervalFormat getInstance(String, java.util.Locale, android.icu.text.DateIntervalInfo);
-    method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.util.ULocale, android.icu.text.DateIntervalInfo);
-    method public android.icu.util.TimeZone getTimeZone();
-    method @Deprecated public Object parseObject(String, java.text.ParsePosition);
-    method public void setDateIntervalInfo(android.icu.text.DateIntervalInfo);
-    method public void setTimeZone(android.icu.util.TimeZone);
-  }
-
-  public class DateIntervalInfo implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.DateIntervalInfo> java.io.Serializable {
-    ctor public DateIntervalInfo(android.icu.util.ULocale);
-    ctor public DateIntervalInfo(java.util.Locale);
-    method public Object clone();
-    method public android.icu.text.DateIntervalInfo cloneAsThawed();
-    method public android.icu.text.DateIntervalInfo freeze();
-    method public boolean getDefaultOrder();
-    method public String getFallbackIntervalPattern();
-    method public android.icu.text.DateIntervalInfo.PatternInfo getIntervalPattern(String, int);
-    method public boolean isFrozen();
-    method public void setFallbackIntervalPattern(String);
-    method public void setIntervalPattern(String, int, String);
-  }
-
-  public static final class DateIntervalInfo.PatternInfo implements java.lang.Cloneable java.io.Serializable {
-    ctor public DateIntervalInfo.PatternInfo(String, String, boolean);
-    method public boolean firstDateInPtnIsLaterDate();
-    method public String getFirstPart();
-    method public String getSecondPart();
-  }
-
-  public class DateTimePatternGenerator implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.DateTimePatternGenerator> {
-    ctor protected DateTimePatternGenerator();
-    method public android.icu.text.DateTimePatternGenerator addPattern(String, boolean, android.icu.text.DateTimePatternGenerator.PatternInfo);
-    method public Object clone();
-    method public android.icu.text.DateTimePatternGenerator cloneAsThawed();
-    method public android.icu.text.DateTimePatternGenerator freeze();
-    method public String getAppendItemFormat(int);
-    method public String getAppendItemName(int);
-    method public String getBaseSkeleton(String);
-    method public java.util.Set<java.lang.String> getBaseSkeletons(java.util.Set<java.lang.String>);
-    method public String getBestPattern(String);
-    method public String getBestPattern(String, int);
-    method public String getDateTimeFormat();
-    method public String getDecimal();
-    method public static android.icu.text.DateTimePatternGenerator getEmptyInstance();
-    method public String getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth);
-    method public static android.icu.text.DateTimePatternGenerator getInstance();
-    method public static android.icu.text.DateTimePatternGenerator getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.DateTimePatternGenerator getInstance(java.util.Locale);
-    method public String getSkeleton(String);
-    method public java.util.Map<java.lang.String,java.lang.String> getSkeletons(java.util.Map<java.lang.String,java.lang.String>);
-    method public boolean isFrozen();
-    method public String replaceFieldTypes(String, String);
-    method public String replaceFieldTypes(String, String, int);
-    method public void setAppendItemFormat(int, String);
-    method public void setAppendItemName(int, String);
-    method public void setDateTimeFormat(String);
-    method public void setDecimal(String);
-    field public static final int DAY = 7; // 0x7
-    field public static final int DAYPERIOD = 10; // 0xa
-    field public static final int DAY_OF_WEEK_IN_MONTH = 9; // 0x9
-    field public static final int DAY_OF_YEAR = 8; // 0x8
-    field public static final int ERA = 0; // 0x0
-    field public static final int FRACTIONAL_SECOND = 14; // 0xe
-    field public static final int HOUR = 11; // 0xb
-    field public static final int MATCH_ALL_FIELDS_LENGTH = 65535; // 0xffff
-    field public static final int MATCH_HOUR_FIELD_LENGTH = 2048; // 0x800
-    field public static final int MATCH_NO_OPTIONS = 0; // 0x0
-    field public static final int MINUTE = 12; // 0xc
-    field public static final int MONTH = 3; // 0x3
-    field public static final int QUARTER = 2; // 0x2
-    field public static final int SECOND = 13; // 0xd
-    field public static final int WEEKDAY = 6; // 0x6
-    field public static final int WEEK_OF_MONTH = 5; // 0x5
-    field public static final int WEEK_OF_YEAR = 4; // 0x4
-    field public static final int YEAR = 1; // 0x1
-    field public static final int ZONE = 15; // 0xf
-  }
-
-  public enum DateTimePatternGenerator.DisplayWidth {
-    enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth ABBREVIATED;
-    enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth NARROW;
-    enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth WIDE;
-  }
-
-  public static final class DateTimePatternGenerator.PatternInfo {
-    ctor public DateTimePatternGenerator.PatternInfo();
-    field public static final int BASE_CONFLICT = 1; // 0x1
-    field public static final int CONFLICT = 2; // 0x2
-    field public static final int OK = 0; // 0x0
-    field public String conflictingPattern;
-    field public int status;
-  }
-
-  public class DecimalFormat extends android.icu.text.NumberFormat {
-    ctor public DecimalFormat();
-    ctor public DecimalFormat(String);
-    ctor public DecimalFormat(String, android.icu.text.DecimalFormatSymbols);
-    ctor public DecimalFormat(String, android.icu.text.DecimalFormatSymbols, android.icu.text.CurrencyPluralInfo, int);
-    method public void applyLocalizedPattern(String);
-    method public void applyPattern(String);
-    method public boolean areSignificantDigitsUsed();
-    method public StringBuffer format(double, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(long, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(java.math.BigInteger, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(java.math.BigDecimal, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(android.icu.math.BigDecimal, StringBuffer, java.text.FieldPosition);
-    method public android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
-    method public android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
-    method public android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
-    method public int getFormatWidth();
-    method public int getGroupingSize();
-    method public java.math.MathContext getMathContext();
-    method public android.icu.math.MathContext getMathContextICU();
-    method public int getMaximumSignificantDigits();
-    method public byte getMinimumExponentDigits();
-    method public int getMinimumSignificantDigits();
-    method public int getMultiplier();
-    method public String getNegativePrefix();
-    method public String getNegativeSuffix();
-    method public char getPadCharacter();
-    method public int getPadPosition();
-    method @Deprecated public int getParseMaxDigits();
-    method public String getPositivePrefix();
-    method public String getPositiveSuffix();
-    method public java.math.BigDecimal getRoundingIncrement();
-    method public int getSecondaryGroupingSize();
-    method public boolean isDecimalPatternMatchRequired();
-    method public boolean isDecimalSeparatorAlwaysShown();
-    method public boolean isExponentSignAlwaysShown();
-    method public boolean isParseBigDecimal();
-    method public boolean isScientificNotation();
-    method public Number parse(String, java.text.ParsePosition);
-    method public void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
-    method public void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
-    method public void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
-    method public void setDecimalPatternMatchRequired(boolean);
-    method public void setDecimalSeparatorAlwaysShown(boolean);
-    method public void setExponentSignAlwaysShown(boolean);
-    method public void setFormatWidth(int);
-    method public void setGroupingSize(int);
-    method public void setMathContext(java.math.MathContext);
-    method public void setMathContextICU(android.icu.math.MathContext);
-    method public void setMaximumSignificantDigits(int);
-    method public void setMinimumExponentDigits(byte);
-    method public void setMinimumSignificantDigits(int);
-    method public void setMultiplier(int);
-    method public void setNegativePrefix(String);
-    method public void setNegativeSuffix(String);
-    method public void setPadCharacter(char);
-    method public void setPadPosition(int);
-    method public void setParseBigDecimal(boolean);
-    method @Deprecated public void setParseMaxDigits(int);
-    method public void setPositivePrefix(String);
-    method public void setPositiveSuffix(String);
-    method public void setRoundingIncrement(java.math.BigDecimal);
-    method public void setRoundingIncrement(android.icu.math.BigDecimal);
-    method public void setRoundingIncrement(double);
-    method public void setScientificNotation(boolean);
-    method public void setSecondaryGroupingSize(int);
-    method public void setSignificantDigitsUsed(boolean);
-    method public String toLocalizedPattern();
-    method public String toPattern();
-    field public static final int PAD_AFTER_PREFIX = 1; // 0x1
-    field public static final int PAD_AFTER_SUFFIX = 3; // 0x3
-    field public static final int PAD_BEFORE_PREFIX = 0; // 0x0
-    field public static final int PAD_BEFORE_SUFFIX = 2; // 0x2
-  }
-
-  public class DecimalFormatSymbols implements java.lang.Cloneable java.io.Serializable {
-    ctor public DecimalFormatSymbols();
-    ctor public DecimalFormatSymbols(java.util.Locale);
-    ctor public DecimalFormatSymbols(android.icu.util.ULocale);
-    method public Object clone();
-    method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(java.util.Locale, android.icu.text.NumberingSystem);
-    method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(android.icu.util.ULocale, android.icu.text.NumberingSystem);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public android.icu.util.Currency getCurrency();
-    method public String getCurrencySymbol();
-    method public char getDecimalSeparator();
-    method public String getDecimalSeparatorString();
-    method public char getDigit();
-    method public String[] getDigitStrings();
-    method public char[] getDigits();
-    method public String getExponentMultiplicationSign();
-    method public String getExponentSeparator();
-    method public char getGroupingSeparator();
-    method public String getGroupingSeparatorString();
-    method public String getInfinity();
-    method public static android.icu.text.DecimalFormatSymbols getInstance();
-    method public static android.icu.text.DecimalFormatSymbols getInstance(java.util.Locale);
-    method public static android.icu.text.DecimalFormatSymbols getInstance(android.icu.util.ULocale);
-    method public String getInternationalCurrencySymbol();
-    method public java.util.Locale getLocale();
-    method public char getMinusSign();
-    method public String getMinusSignString();
-    method public char getMonetaryDecimalSeparator();
-    method public String getMonetaryDecimalSeparatorString();
-    method public char getMonetaryGroupingSeparator();
-    method public String getMonetaryGroupingSeparatorString();
-    method public String getNaN();
-    method public char getPadEscape();
-    method public String getPatternForCurrencySpacing(int, boolean);
-    method public char getPatternSeparator();
-    method public char getPerMill();
-    method public String getPerMillString();
-    method public char getPercent();
-    method public String getPercentString();
-    method public char getPlusSign();
-    method public String getPlusSignString();
-    method public char getSignificantDigit();
-    method public android.icu.util.ULocale getULocale();
-    method public char getZeroDigit();
-    method public void setCurrency(android.icu.util.Currency);
-    method public void setCurrencySymbol(String);
-    method public void setDecimalSeparator(char);
-    method public void setDecimalSeparatorString(String);
-    method public void setDigit(char);
-    method public void setDigitStrings(String[]);
-    method public void setExponentMultiplicationSign(String);
-    method public void setExponentSeparator(String);
-    method public void setGroupingSeparator(char);
-    method public void setGroupingSeparatorString(String);
-    method public void setInfinity(String);
-    method public void setInternationalCurrencySymbol(String);
-    method public void setMinusSign(char);
-    method public void setMinusSignString(String);
-    method public void setMonetaryDecimalSeparator(char);
-    method public void setMonetaryDecimalSeparatorString(String);
-    method public void setMonetaryGroupingSeparator(char);
-    method public void setMonetaryGroupingSeparatorString(String);
-    method public void setNaN(String);
-    method public void setPadEscape(char);
-    method public void setPatternForCurrencySpacing(int, boolean, String);
-    method public void setPatternSeparator(char);
-    method public void setPerMill(char);
-    method public void setPerMillString(String);
-    method public void setPercent(char);
-    method public void setPercentString(String);
-    method public void setPlusSign(char);
-    method public void setPlusSignString(String);
-    method public void setSignificantDigit(char);
-    method public void setZeroDigit(char);
-    field public static final int CURRENCY_SPC_CURRENCY_MATCH = 0; // 0x0
-    field public static final int CURRENCY_SPC_INSERT = 2; // 0x2
-    field public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1; // 0x1
-  }
-
-  public enum DisplayContext {
-    method public android.icu.text.DisplayContext.Type type();
-    method public int value();
-    enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE;
-    enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE;
-    enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_STANDALONE;
-    enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_UI_LIST_OR_MENU;
-    enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_NONE;
-    enum_constant public static final android.icu.text.DisplayContext DIALECT_NAMES;
-    enum_constant public static final android.icu.text.DisplayContext LENGTH_FULL;
-    enum_constant public static final android.icu.text.DisplayContext LENGTH_SHORT;
-    enum_constant public static final android.icu.text.DisplayContext NO_SUBSTITUTE;
-    enum_constant public static final android.icu.text.DisplayContext STANDARD_NAMES;
-    enum_constant public static final android.icu.text.DisplayContext SUBSTITUTE;
-  }
-
-  public enum DisplayContext.Type {
-    enum_constant public static final android.icu.text.DisplayContext.Type CAPITALIZATION;
-    enum_constant public static final android.icu.text.DisplayContext.Type DIALECT_HANDLING;
-    enum_constant public static final android.icu.text.DisplayContext.Type DISPLAY_LENGTH;
-    enum_constant public static final android.icu.text.DisplayContext.Type SUBSTITUTE_HANDLING;
-  }
-
-  public final class Edits {
-    ctor public Edits();
-    method public void addReplace(int, int);
-    method public void addUnchanged(int);
-    method public android.icu.text.Edits.Iterator getCoarseChangesIterator();
-    method public android.icu.text.Edits.Iterator getCoarseIterator();
-    method public android.icu.text.Edits.Iterator getFineChangesIterator();
-    method public android.icu.text.Edits.Iterator getFineIterator();
-    method public boolean hasChanges();
-    method public int lengthDelta();
-    method public android.icu.text.Edits mergeAndAppend(android.icu.text.Edits, android.icu.text.Edits);
-    method public int numberOfChanges();
-    method public void reset();
-  }
-
-  public static final class Edits.Iterator {
-    method public int destinationIndex();
-    method public int destinationIndexFromSourceIndex(int);
-    method public boolean findDestinationIndex(int);
-    method public boolean findSourceIndex(int);
-    method public boolean hasChange();
-    method public int newLength();
-    method public boolean next();
-    method public int oldLength();
-    method public int replacementIndex();
-    method public int sourceIndex();
-    method public int sourceIndexFromDestinationIndex(int);
-  }
-
-  public abstract class IDNA {
-    method public static android.icu.text.IDNA getUTS46Instance(int);
-    method public abstract StringBuilder labelToASCII(CharSequence, StringBuilder, android.icu.text.IDNA.Info);
-    method public abstract StringBuilder labelToUnicode(CharSequence, StringBuilder, android.icu.text.IDNA.Info);
-    method public abstract StringBuilder nameToASCII(CharSequence, StringBuilder, android.icu.text.IDNA.Info);
-    method public abstract StringBuilder nameToUnicode(CharSequence, StringBuilder, android.icu.text.IDNA.Info);
-    field public static final int CHECK_BIDI = 4; // 0x4
-    field public static final int CHECK_CONTEXTJ = 8; // 0x8
-    field public static final int CHECK_CONTEXTO = 64; // 0x40
-    field public static final int DEFAULT = 0; // 0x0
-    field public static final int NONTRANSITIONAL_TO_ASCII = 16; // 0x10
-    field public static final int NONTRANSITIONAL_TO_UNICODE = 32; // 0x20
-    field public static final int USE_STD3_RULES = 2; // 0x2
-  }
-
-  public enum IDNA.Error {
-    enum_constant public static final android.icu.text.IDNA.Error BIDI;
-    enum_constant public static final android.icu.text.IDNA.Error CONTEXTJ;
-    enum_constant public static final android.icu.text.IDNA.Error CONTEXTO_DIGITS;
-    enum_constant public static final android.icu.text.IDNA.Error CONTEXTO_PUNCTUATION;
-    enum_constant public static final android.icu.text.IDNA.Error DISALLOWED;
-    enum_constant public static final android.icu.text.IDNA.Error DOMAIN_NAME_TOO_LONG;
-    enum_constant public static final android.icu.text.IDNA.Error EMPTY_LABEL;
-    enum_constant public static final android.icu.text.IDNA.Error HYPHEN_3_4;
-    enum_constant public static final android.icu.text.IDNA.Error INVALID_ACE_LABEL;
-    enum_constant public static final android.icu.text.IDNA.Error LABEL_HAS_DOT;
-    enum_constant public static final android.icu.text.IDNA.Error LABEL_TOO_LONG;
-    enum_constant public static final android.icu.text.IDNA.Error LEADING_COMBINING_MARK;
-    enum_constant public static final android.icu.text.IDNA.Error LEADING_HYPHEN;
-    enum_constant public static final android.icu.text.IDNA.Error PUNYCODE;
-    enum_constant public static final android.icu.text.IDNA.Error TRAILING_HYPHEN;
-  }
-
-  public static final class IDNA.Info {
-    ctor public IDNA.Info();
-    method public java.util.Set<android.icu.text.IDNA.Error> getErrors();
-    method public boolean hasErrors();
-    method public boolean isTransitionalDifferent();
-  }
-
-  public final class ListFormatter {
-    method public String format(java.lang.Object...);
-    method public String format(java.util.Collection<?>);
-    method public static android.icu.text.ListFormatter getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.ListFormatter getInstance(java.util.Locale);
-    method public static android.icu.text.ListFormatter getInstance();
-    method public String getPatternForNumItems(int);
-  }
-
-  public abstract class LocaleDisplayNames {
-    method public abstract android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
-    method public abstract android.icu.text.LocaleDisplayNames.DialectHandling getDialectHandling();
-    method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale);
-    method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.LocaleDisplayNames.DialectHandling);
-    method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.DisplayContext...);
-    method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale, android.icu.text.DisplayContext...);
-    method public abstract android.icu.util.ULocale getLocale();
-    method public java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiList(java.util.Set<android.icu.util.ULocale>, boolean, java.util.Comparator<java.lang.Object>);
-    method public abstract java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiListCompareWholeItems(java.util.Set<android.icu.util.ULocale>, java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem>);
-    method public abstract String keyDisplayName(String);
-    method public abstract String keyValueDisplayName(String, String);
-    method public abstract String languageDisplayName(String);
-    method public abstract String localeDisplayName(android.icu.util.ULocale);
-    method public abstract String localeDisplayName(java.util.Locale);
-    method public abstract String localeDisplayName(String);
-    method public abstract String regionDisplayName(String);
-    method public abstract String scriptDisplayName(String);
-    method public abstract String scriptDisplayName(int);
-    method public abstract String variantDisplayName(String);
-  }
-
-  public enum LocaleDisplayNames.DialectHandling {
-    enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling DIALECT_NAMES;
-    enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling STANDARD_NAMES;
-  }
-
-  public static class LocaleDisplayNames.UiListItem {
-    ctor public LocaleDisplayNames.UiListItem(android.icu.util.ULocale, android.icu.util.ULocale, String, String);
-    method public static java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem> getComparator(java.util.Comparator<java.lang.Object>, boolean);
-    field public final android.icu.util.ULocale minimized;
-    field public final android.icu.util.ULocale modified;
-    field public final String nameInDisplayLocale;
-    field public final String nameInSelf;
-  }
-
-  public class MeasureFormat extends android.icu.text.UFormat {
-    method public final boolean equals(Object);
-    method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public StringBuilder formatMeasurePerUnit(android.icu.util.Measure, android.icu.util.MeasureUnit, StringBuilder, java.text.FieldPosition);
-    method public final String formatMeasures(android.icu.util.Measure...);
-    method public StringBuilder formatMeasures(StringBuilder, java.text.FieldPosition, android.icu.util.Measure...);
-    method public static android.icu.text.MeasureFormat getCurrencyFormat(android.icu.util.ULocale);
-    method public static android.icu.text.MeasureFormat getCurrencyFormat(java.util.Locale);
-    method public static android.icu.text.MeasureFormat getCurrencyFormat();
-    method public static android.icu.text.MeasureFormat getInstance(android.icu.util.ULocale, android.icu.text.MeasureFormat.FormatWidth);
-    method public static android.icu.text.MeasureFormat getInstance(java.util.Locale, android.icu.text.MeasureFormat.FormatWidth);
-    method public static android.icu.text.MeasureFormat getInstance(android.icu.util.ULocale, android.icu.text.MeasureFormat.FormatWidth, android.icu.text.NumberFormat);
-    method public static android.icu.text.MeasureFormat getInstance(java.util.Locale, android.icu.text.MeasureFormat.FormatWidth, android.icu.text.NumberFormat);
-    method public final android.icu.util.ULocale getLocale();
-    method public android.icu.text.NumberFormat getNumberFormat();
-    method public String getUnitDisplayName(android.icu.util.MeasureUnit);
-    method public android.icu.text.MeasureFormat.FormatWidth getWidth();
-    method public final int hashCode();
-    method public android.icu.util.Measure parseObject(String, java.text.ParsePosition);
-  }
-
-  public enum MeasureFormat.FormatWidth {
-    enum_constant public static final android.icu.text.MeasureFormat.FormatWidth NARROW;
-    enum_constant public static final android.icu.text.MeasureFormat.FormatWidth NUMERIC;
-    enum_constant public static final android.icu.text.MeasureFormat.FormatWidth SHORT;
-    enum_constant public static final android.icu.text.MeasureFormat.FormatWidth WIDE;
-  }
-
-  public class MessageFormat extends android.icu.text.UFormat {
-    ctor public MessageFormat(String);
-    ctor public MessageFormat(String, java.util.Locale);
-    ctor public MessageFormat(String, android.icu.util.ULocale);
-    method public void applyPattern(String);
-    method public void applyPattern(String, android.icu.text.MessagePattern.ApostropheMode);
-    method public static String autoQuoteApostrophe(String);
-    method public final StringBuffer format(Object[], StringBuffer, java.text.FieldPosition);
-    method public final StringBuffer format(java.util.Map<java.lang.String,java.lang.Object>, StringBuffer, java.text.FieldPosition);
-    method public static String format(String, java.lang.Object...);
-    method public static String format(String, java.util.Map<java.lang.String,java.lang.Object>);
-    method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public android.icu.text.MessagePattern.ApostropheMode getApostropheMode();
-    method public java.util.Set<java.lang.String> getArgumentNames();
-    method public java.text.Format getFormatByArgumentName(String);
-    method public java.text.Format[] getFormats();
-    method public java.text.Format[] getFormatsByArgumentIndex();
-    method public java.util.Locale getLocale();
-    method public android.icu.util.ULocale getULocale();
-    method public Object[] parse(String, java.text.ParsePosition);
-    method public Object[] parse(String) throws java.text.ParseException;
-    method public Object parseObject(String, java.text.ParsePosition);
-    method public java.util.Map<java.lang.String,java.lang.Object> parseToMap(String, java.text.ParsePosition);
-    method public java.util.Map<java.lang.String,java.lang.Object> parseToMap(String) throws java.text.ParseException;
-    method public void setFormat(int, java.text.Format);
-    method public void setFormatByArgumentIndex(int, java.text.Format);
-    method public void setFormatByArgumentName(String, java.text.Format);
-    method public void setFormats(java.text.Format[]);
-    method public void setFormatsByArgumentIndex(java.text.Format[]);
-    method public void setFormatsByArgumentName(java.util.Map<java.lang.String,java.text.Format>);
-    method public void setLocale(java.util.Locale);
-    method public void setLocale(android.icu.util.ULocale);
-    method public String toPattern();
-    method public boolean usesNamedArguments();
-  }
-
-  public static class MessageFormat.Field extends java.text.Format.Field {
-    ctor protected MessageFormat.Field(String);
-    field public static final android.icu.text.MessageFormat.Field ARGUMENT;
-  }
-
-  public final class MessagePattern implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.MessagePattern> {
-    ctor public MessagePattern();
-    ctor public MessagePattern(android.icu.text.MessagePattern.ApostropheMode);
-    ctor public MessagePattern(String);
-    method public String autoQuoteApostropheDeep();
-    method public void clear();
-    method public void clearPatternAndSetApostropheMode(android.icu.text.MessagePattern.ApostropheMode);
-    method public Object clone();
-    method public android.icu.text.MessagePattern cloneAsThawed();
-    method public int countParts();
-    method public android.icu.text.MessagePattern freeze();
-    method public android.icu.text.MessagePattern.ApostropheMode getApostropheMode();
-    method public int getLimitPartIndex(int);
-    method public double getNumericValue(android.icu.text.MessagePattern.Part);
-    method public android.icu.text.MessagePattern.Part getPart(int);
-    method public android.icu.text.MessagePattern.Part.Type getPartType(int);
-    method public int getPatternIndex(int);
-    method public String getPatternString();
-    method public double getPluralOffset(int);
-    method public String getSubstring(android.icu.text.MessagePattern.Part);
-    method public boolean hasNamedArguments();
-    method public boolean hasNumberedArguments();
-    method public boolean isFrozen();
-    method public android.icu.text.MessagePattern parse(String);
-    method public android.icu.text.MessagePattern parseChoiceStyle(String);
-    method public android.icu.text.MessagePattern parsePluralStyle(String);
-    method public android.icu.text.MessagePattern parseSelectStyle(String);
-    method public boolean partSubstringMatches(android.icu.text.MessagePattern.Part, String);
-    method public static int validateArgumentName(String);
-    field public static final int ARG_NAME_NOT_NUMBER = -1; // 0xffffffff
-    field public static final int ARG_NAME_NOT_VALID = -2; // 0xfffffffe
-    field public static final double NO_NUMERIC_VALUE = -1.23456789E8;
-  }
-
-  public enum MessagePattern.ApostropheMode {
-    enum_constant public static final android.icu.text.MessagePattern.ApostropheMode DOUBLE_OPTIONAL;
-    enum_constant public static final android.icu.text.MessagePattern.ApostropheMode DOUBLE_REQUIRED;
-  }
-
-  public enum MessagePattern.ArgType {
-    method public boolean hasPluralStyle();
-    enum_constant public static final android.icu.text.MessagePattern.ArgType CHOICE;
-    enum_constant public static final android.icu.text.MessagePattern.ArgType NONE;
-    enum_constant public static final android.icu.text.MessagePattern.ArgType PLURAL;
-    enum_constant public static final android.icu.text.MessagePattern.ArgType SELECT;
-    enum_constant public static final android.icu.text.MessagePattern.ArgType SELECTORDINAL;
-    enum_constant public static final android.icu.text.MessagePattern.ArgType SIMPLE;
-  }
-
-  public static final class MessagePattern.Part {
-    method public android.icu.text.MessagePattern.ArgType getArgType();
-    method public int getIndex();
-    method public int getLength();
-    method public int getLimit();
-    method public android.icu.text.MessagePattern.Part.Type getType();
-    method public int getValue();
-  }
-
-  public enum MessagePattern.Part.Type {
-    method public boolean hasNumericValue();
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_DOUBLE;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_INT;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_LIMIT;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_NAME;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_NUMBER;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_SELECTOR;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_START;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_STYLE;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_TYPE;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type INSERT_CHAR;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type MSG_LIMIT;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type MSG_START;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type REPLACE_NUMBER;
-    enum_constant public static final android.icu.text.MessagePattern.Part.Type SKIP_SYNTAX;
-  }
-
-  public final class Normalizer implements java.lang.Cloneable {
-    method @Deprecated public Object clone();
-    method public static int compare(char[], int, int, char[], int, int, int);
-    method public static int compare(String, String, int);
-    method public static int compare(char[], char[], int);
-    method public static int compare(int, int, int);
-    method public static int compare(int, String, int);
-    field public static final int COMPARE_CODE_POINT_ORDER = 32768; // 0x8000
-    field public static final int COMPARE_IGNORE_CASE = 65536; // 0x10000
-    field public static final int FOLD_CASE_DEFAULT = 0; // 0x0
-    field public static final int FOLD_CASE_EXCLUDE_SPECIAL_I = 1; // 0x1
-    field public static final int INPUT_IS_FCD = 131072; // 0x20000
-    field public static final android.icu.text.Normalizer.QuickCheckResult MAYBE;
-    field public static final android.icu.text.Normalizer.QuickCheckResult NO;
-    field public static final android.icu.text.Normalizer.QuickCheckResult YES;
-  }
-
-  public static final class Normalizer.QuickCheckResult {
-  }
-
-  public abstract class Normalizer2 {
-    method public abstract StringBuilder append(StringBuilder, CharSequence);
-    method public int composePair(int, int);
-    method public int getCombiningClass(int);
-    method public abstract String getDecomposition(int);
-    method public static android.icu.text.Normalizer2 getInstance(java.io.InputStream, String, android.icu.text.Normalizer2.Mode);
-    method public static android.icu.text.Normalizer2 getNFCInstance();
-    method public static android.icu.text.Normalizer2 getNFDInstance();
-    method public static android.icu.text.Normalizer2 getNFKCCasefoldInstance();
-    method public static android.icu.text.Normalizer2 getNFKCInstance();
-    method public static android.icu.text.Normalizer2 getNFKDInstance();
-    method public String getRawDecomposition(int);
-    method public abstract boolean hasBoundaryAfter(int);
-    method public abstract boolean hasBoundaryBefore(int);
-    method public abstract boolean isInert(int);
-    method public abstract boolean isNormalized(CharSequence);
-    method public String normalize(CharSequence);
-    method public abstract StringBuilder normalize(CharSequence, StringBuilder);
-    method public abstract Appendable normalize(CharSequence, Appendable);
-    method public abstract StringBuilder normalizeSecondAndAppend(StringBuilder, CharSequence);
-    method public abstract android.icu.text.Normalizer.QuickCheckResult quickCheck(CharSequence);
-    method public abstract int spanQuickCheckYes(CharSequence);
-  }
-
-  public enum Normalizer2.Mode {
-    enum_constant public static final android.icu.text.Normalizer2.Mode COMPOSE;
-    enum_constant public static final android.icu.text.Normalizer2.Mode COMPOSE_CONTIGUOUS;
-    enum_constant public static final android.icu.text.Normalizer2.Mode DECOMPOSE;
-    enum_constant public static final android.icu.text.Normalizer2.Mode FCD;
-  }
-
-  public abstract class NumberFormat extends android.icu.text.UFormat {
-    ctor public NumberFormat();
-    method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public final String format(double);
-    method public final String format(long);
-    method public final String format(java.math.BigInteger);
-    method public final String format(java.math.BigDecimal);
-    method public final String format(android.icu.math.BigDecimal);
-    method public final String format(android.icu.util.CurrencyAmount);
-    method public abstract StringBuffer format(double, StringBuffer, java.text.FieldPosition);
-    method public abstract StringBuffer format(long, StringBuffer, java.text.FieldPosition);
-    method public abstract StringBuffer format(java.math.BigInteger, StringBuffer, java.text.FieldPosition);
-    method public abstract StringBuffer format(java.math.BigDecimal, StringBuffer, java.text.FieldPosition);
-    method public abstract StringBuffer format(android.icu.math.BigDecimal, StringBuffer, java.text.FieldPosition);
-    method public StringBuffer format(android.icu.util.CurrencyAmount, StringBuffer, java.text.FieldPosition);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
-    method public android.icu.util.Currency getCurrency();
-    method public static final android.icu.text.NumberFormat getCurrencyInstance();
-    method public static android.icu.text.NumberFormat getCurrencyInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getCurrencyInstance(android.icu.util.ULocale);
-    method public static final android.icu.text.NumberFormat getInstance();
-    method public static android.icu.text.NumberFormat getInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getInstance(android.icu.util.ULocale);
-    method public static final android.icu.text.NumberFormat getInstance(int);
-    method public static android.icu.text.NumberFormat getInstance(java.util.Locale, int);
-    method public static android.icu.text.NumberFormat getInstance(android.icu.util.ULocale, int);
-    method public static final android.icu.text.NumberFormat getIntegerInstance();
-    method public static android.icu.text.NumberFormat getIntegerInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getIntegerInstance(android.icu.util.ULocale);
-    method public int getMaximumFractionDigits();
-    method public int getMaximumIntegerDigits();
-    method public int getMinimumFractionDigits();
-    method public int getMinimumIntegerDigits();
-    method public static final android.icu.text.NumberFormat getNumberInstance();
-    method public static android.icu.text.NumberFormat getNumberInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getNumberInstance(android.icu.util.ULocale);
-    method protected static String getPattern(android.icu.util.ULocale, int);
-    method public static final android.icu.text.NumberFormat getPercentInstance();
-    method public static android.icu.text.NumberFormat getPercentInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getPercentInstance(android.icu.util.ULocale);
-    method public int getRoundingMode();
-    method public static final android.icu.text.NumberFormat getScientificInstance();
-    method public static android.icu.text.NumberFormat getScientificInstance(java.util.Locale);
-    method public static android.icu.text.NumberFormat getScientificInstance(android.icu.util.ULocale);
-    method public boolean isGroupingUsed();
-    method public boolean isParseIntegerOnly();
-    method public boolean isParseStrict();
-    method public abstract Number parse(String, java.text.ParsePosition);
-    method public Number parse(String) throws java.text.ParseException;
-    method public android.icu.util.CurrencyAmount parseCurrency(CharSequence, java.text.ParsePosition);
-    method public final Object parseObject(String, java.text.ParsePosition);
-    method public void setContext(android.icu.text.DisplayContext);
-    method public void setCurrency(android.icu.util.Currency);
-    method public void setGroupingUsed(boolean);
-    method public void setMaximumFractionDigits(int);
-    method public void setMaximumIntegerDigits(int);
-    method public void setMinimumFractionDigits(int);
-    method public void setMinimumIntegerDigits(int);
-    method public void setParseIntegerOnly(boolean);
-    method public void setParseStrict(boolean);
-    method public void setRoundingMode(int);
-    field public static final int ACCOUNTINGCURRENCYSTYLE = 7; // 0x7
-    field public static final int CASHCURRENCYSTYLE = 8; // 0x8
-    field public static final int CURRENCYSTYLE = 1; // 0x1
-    field public static final int FRACTION_FIELD = 1; // 0x1
-    field public static final int INTEGERSTYLE = 4; // 0x4
-    field public static final int INTEGER_FIELD = 0; // 0x0
-    field public static final int ISOCURRENCYSTYLE = 5; // 0x5
-    field public static final int NUMBERSTYLE = 0; // 0x0
-    field public static final int PERCENTSTYLE = 2; // 0x2
-    field public static final int PLURALCURRENCYSTYLE = 6; // 0x6
-    field public static final int SCIENTIFICSTYLE = 3; // 0x3
-    field public static final int STANDARDCURRENCYSTYLE = 9; // 0x9
-  }
-
-  public static class NumberFormat.Field extends java.text.Format.Field {
-    ctor protected NumberFormat.Field(String);
-    field public static final android.icu.text.NumberFormat.Field CURRENCY;
-    field public static final android.icu.text.NumberFormat.Field DECIMAL_SEPARATOR;
-    field public static final android.icu.text.NumberFormat.Field EXPONENT;
-    field public static final android.icu.text.NumberFormat.Field EXPONENT_SIGN;
-    field public static final android.icu.text.NumberFormat.Field EXPONENT_SYMBOL;
-    field public static final android.icu.text.NumberFormat.Field FRACTION;
-    field public static final android.icu.text.NumberFormat.Field GROUPING_SEPARATOR;
-    field public static final android.icu.text.NumberFormat.Field INTEGER;
-    field public static final android.icu.text.NumberFormat.Field PERCENT;
-    field public static final android.icu.text.NumberFormat.Field PERMILLE;
-    field public static final android.icu.text.NumberFormat.Field SIGN;
-  }
-
-  public class NumberingSystem {
-    ctor public NumberingSystem();
-    method public static String[] getAvailableNames();
-    method public String getDescription();
-    method public static android.icu.text.NumberingSystem getInstance(int, boolean, String);
-    method public static android.icu.text.NumberingSystem getInstance(java.util.Locale);
-    method public static android.icu.text.NumberingSystem getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.NumberingSystem getInstance();
-    method public static android.icu.text.NumberingSystem getInstanceByName(String);
-    method public String getName();
-    method public int getRadix();
-    method public boolean isAlgorithmic();
-    method public static boolean isValidDigitString(String);
-    field public static final android.icu.text.NumberingSystem LATIN;
-  }
-
-  public class PluralFormat extends android.icu.text.UFormat {
-    ctor public PluralFormat();
-    ctor public PluralFormat(android.icu.util.ULocale);
-    ctor public PluralFormat(java.util.Locale);
-    ctor public PluralFormat(android.icu.text.PluralRules);
-    ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules);
-    ctor public PluralFormat(java.util.Locale, android.icu.text.PluralRules);
-    ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType);
-    ctor public PluralFormat(java.util.Locale, android.icu.text.PluralRules.PluralType);
-    ctor public PluralFormat(String);
-    ctor public PluralFormat(android.icu.util.ULocale, String);
-    ctor public PluralFormat(android.icu.text.PluralRules, String);
-    ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules, String);
-    ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType, String);
-    method public void applyPattern(String);
-    method public boolean equals(android.icu.text.PluralFormat);
-    method public final String format(double);
-    method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public Number parse(String, java.text.ParsePosition);
-    method public Object parseObject(String, java.text.ParsePosition);
-    method public void setNumberFormat(android.icu.text.NumberFormat);
-    method public String toPattern();
-  }
-
-  public class PluralRules implements java.io.Serializable {
-    method public static android.icu.text.PluralRules createRules(String);
-    method public boolean equals(android.icu.text.PluralRules);
-    method public static android.icu.text.PluralRules forLocale(android.icu.util.ULocale);
-    method public static android.icu.text.PluralRules forLocale(java.util.Locale);
-    method public static android.icu.text.PluralRules forLocale(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType);
-    method public static android.icu.text.PluralRules forLocale(java.util.Locale, android.icu.text.PluralRules.PluralType);
-    method public java.util.Collection<java.lang.Double> getAllKeywordValues(String);
-    method public java.util.Set<java.lang.String> getKeywords();
-    method public java.util.Collection<java.lang.Double> getSamples(String);
-    method public double getUniqueKeywordValue(String);
-    method public static android.icu.text.PluralRules parseDescription(String) throws java.text.ParseException;
-    method public String select(double);
-    field public static final android.icu.text.PluralRules DEFAULT;
-    field public static final String KEYWORD_FEW = "few";
-    field public static final String KEYWORD_MANY = "many";
-    field public static final String KEYWORD_ONE = "one";
-    field public static final String KEYWORD_OTHER = "other";
-    field public static final String KEYWORD_TWO = "two";
-    field public static final String KEYWORD_ZERO = "zero";
-    field public static final double NO_UNIQUE_VALUE = -0.00123456777;
-  }
-
-  public enum PluralRules.PluralType {
-    enum_constant public static final android.icu.text.PluralRules.PluralType CARDINAL;
-    enum_constant public static final android.icu.text.PluralRules.PluralType ORDINAL;
-  }
-
-  public final class RelativeDateTimeFormatter {
-    method public String combineDateAndTime(String, String);
-    method public String format(double, android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.RelativeUnit);
-    method public String format(android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit);
-    method public String format(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
-    method public String formatNumeric(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
-    method public android.icu.text.DisplayContext getCapitalizationContext();
-    method public android.icu.text.RelativeDateTimeFormatter.Style getFormatStyle();
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance();
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance(java.util.Locale);
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale, android.icu.text.NumberFormat);
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale, android.icu.text.NumberFormat, android.icu.text.RelativeDateTimeFormatter.Style, android.icu.text.DisplayContext);
-    method public static android.icu.text.RelativeDateTimeFormatter getInstance(java.util.Locale, android.icu.text.NumberFormat);
-    method public android.icu.text.NumberFormat getNumberFormat();
-  }
-
-  public enum RelativeDateTimeFormatter.AbsoluteUnit {
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit DAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit FRIDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit MONDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit MONTH;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit NOW;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit SATURDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit SUNDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit THURSDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit TUESDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit WEDNESDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit WEEK;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit YEAR;
-  }
-
-  public enum RelativeDateTimeFormatter.Direction {
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction LAST;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction LAST_2;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction NEXT;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction NEXT_2;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction PLAIN;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction THIS;
-  }
-
-  public enum RelativeDateTimeFormatter.RelativeDateTimeUnit {
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit DAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit FRIDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit HOUR;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MINUTE;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONTH;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit QUARTER;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SATURDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SECOND;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SUNDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit THURSDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit TUESDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEDNESDAY;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEEK;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit YEAR;
-  }
-
-  public enum RelativeDateTimeFormatter.RelativeUnit {
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit DAYS;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit HOURS;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit MINUTES;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit MONTHS;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit SECONDS;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit WEEKS;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit YEARS;
-  }
-
-  public enum RelativeDateTimeFormatter.Style {
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style LONG;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style NARROW;
-    enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style SHORT;
-  }
-
-  public interface Replaceable {
-    method public int char32At(int);
-    method public char charAt(int);
-    method public void copy(int, int, int);
-    method public void getChars(int, int, char[], int);
-    method public boolean hasMetaData();
-    method public int length();
-    method public void replace(int, int, String);
-    method public void replace(int, int, char[], int, int);
-  }
-
-  public final class RuleBasedCollator extends android.icu.text.Collator {
-    ctor public RuleBasedCollator(String) throws java.lang.Exception;
-    method public android.icu.text.RuleBasedCollator cloneAsThawed();
-    method public int compare(String, String);
-    method public android.icu.text.CollationElementIterator getCollationElementIterator(String);
-    method public android.icu.text.CollationElementIterator getCollationElementIterator(java.text.CharacterIterator);
-    method public android.icu.text.CollationElementIterator getCollationElementIterator(android.icu.text.UCharacterIterator);
-    method public android.icu.text.CollationKey getCollationKey(String);
-    method public void getContractionsAndExpansions(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet, boolean) throws java.lang.Exception;
-    method public boolean getNumericCollation();
-    method public String getRules();
-    method public String getRules(boolean);
-    method public android.icu.util.VersionInfo getUCAVersion();
-    method public int getVariableTop();
-    method public android.icu.util.VersionInfo getVersion();
-    method public boolean isAlternateHandlingShifted();
-    method public boolean isCaseLevel();
-    method public boolean isFrenchCollation();
-    method public boolean isLowerCaseFirst();
-    method public boolean isUpperCaseFirst();
-    method public void setAlternateHandlingDefault();
-    method public void setAlternateHandlingShifted(boolean);
-    method public void setCaseFirstDefault();
-    method public void setCaseLevel(boolean);
-    method public void setCaseLevelDefault();
-    method public void setDecompositionDefault();
-    method public void setFrenchCollation(boolean);
-    method public void setFrenchCollationDefault();
-    method public void setLowerCaseFirst(boolean);
-    method public android.icu.text.RuleBasedCollator setMaxVariable(int);
-    method public void setNumericCollation(boolean);
-    method public void setNumericCollationDefault();
-    method public void setStrengthDefault();
-    method public void setUpperCaseFirst(boolean);
-  }
-
-  public final class ScientificNumberFormatter {
-    method public String format(Object);
-    method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.util.ULocale, String, String);
-    method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.text.DecimalFormat, String, String);
-    method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.util.ULocale);
-    method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.text.DecimalFormat);
-  }
-
-  public abstract class SearchIterator {
-    ctor protected SearchIterator(java.text.CharacterIterator, android.icu.text.BreakIterator);
-    method public final int first();
-    method public final int following(int);
-    method public android.icu.text.BreakIterator getBreakIterator();
-    method public android.icu.text.SearchIterator.ElementComparisonType getElementComparisonType();
-    method public abstract int getIndex();
-    method public int getMatchLength();
-    method public int getMatchStart();
-    method public String getMatchedText();
-    method public java.text.CharacterIterator getTarget();
-    method protected abstract int handleNext(int);
-    method protected abstract int handlePrevious(int);
-    method public boolean isOverlapping();
-    method public final int last();
-    method public int next();
-    method public final int preceding(int);
-    method public int previous();
-    method public void reset();
-    method public void setBreakIterator(android.icu.text.BreakIterator);
-    method public void setElementComparisonType(android.icu.text.SearchIterator.ElementComparisonType);
-    method public void setIndex(int);
-    method protected void setMatchLength(int);
-    method public void setOverlapping(boolean);
-    method public void setTarget(java.text.CharacterIterator);
-    field public static final int DONE = -1; // 0xffffffff
-    field protected android.icu.text.BreakIterator breakIterator;
-    field protected int matchLength;
-    field protected java.text.CharacterIterator targetText;
-  }
-
-  public enum SearchIterator.ElementComparisonType {
-    enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType ANY_BASE_WEIGHT_IS_WILDCARD;
-    enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType PATTERN_BASE_WEIGHT_IS_WILDCARD;
-    enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType STANDARD_ELEMENT_COMPARISON;
-  }
-
-  public class SelectFormat extends java.text.Format {
-    ctor public SelectFormat(String);
-    method public void applyPattern(String);
-    method public final String format(String);
-    method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public Object parseObject(String, java.text.ParsePosition);
-    method public String toPattern();
-  }
-
-  public class SimpleDateFormat extends android.icu.text.DateFormat {
-    ctor public SimpleDateFormat();
-    ctor public SimpleDateFormat(String);
-    ctor public SimpleDateFormat(String, java.util.Locale);
-    ctor public SimpleDateFormat(String, android.icu.util.ULocale);
-    ctor public SimpleDateFormat(String, String, android.icu.util.ULocale);
-    ctor public SimpleDateFormat(String, android.icu.text.DateFormatSymbols);
-    method public void applyLocalizedPattern(String);
-    method public void applyPattern(String);
-    method public StringBuffer format(android.icu.util.Calendar, StringBuffer, java.text.FieldPosition);
-    method public java.util.Date get2DigitYearStart();
-    method public android.icu.text.DateFormatSymbols getDateFormatSymbols();
-    method public android.icu.text.NumberFormat getNumberFormat(char);
-    method protected android.icu.text.DateFormatSymbols getSymbols();
-    method public android.icu.text.TimeZoneFormat getTimeZoneFormat();
-    method protected int matchQuarterString(String, int, int, String[], android.icu.util.Calendar);
-    method protected int matchString(String, int, int, String[], android.icu.util.Calendar);
-    method public void parse(String, android.icu.util.Calendar, java.text.ParsePosition);
-    method protected android.icu.text.DateFormat.Field patternCharToDateFormatField(char);
-    method public void set2DigitYearStart(java.util.Date);
-    method public void setDateFormatSymbols(android.icu.text.DateFormatSymbols);
-    method public void setNumberFormat(String, android.icu.text.NumberFormat);
-    method public void setTimeZoneFormat(android.icu.text.TimeZoneFormat);
-    method protected String subFormat(char, int, int, java.text.FieldPosition, android.icu.text.DateFormatSymbols, android.icu.util.Calendar) throws java.lang.IllegalArgumentException;
-    method protected int subParse(String, int, char, int, boolean, boolean, boolean[], android.icu.util.Calendar);
-    method public String toLocalizedPattern();
-    method public String toPattern();
-    method protected String zeroPaddingNumber(long, int, int);
-  }
-
-  public class StringPrepParseException extends java.text.ParseException {
-    ctor public StringPrepParseException(String, int);
-    ctor public StringPrepParseException(String, int, String, int);
-    ctor public StringPrepParseException(String, int, String, int, int);
-    method public int getError();
-    field public static final int ACE_PREFIX_ERROR = 6; // 0x6
-    field public static final int BUFFER_OVERFLOW_ERROR = 9; // 0x9
-    field public static final int CHECK_BIDI_ERROR = 4; // 0x4
-    field public static final int DOMAIN_NAME_TOO_LONG_ERROR = 11; // 0xb
-    field public static final int ILLEGAL_CHAR_FOUND = 1; // 0x1
-    field public static final int INVALID_CHAR_FOUND = 0; // 0x0
-    field public static final int LABEL_TOO_LONG_ERROR = 8; // 0x8
-    field public static final int PROHIBITED_ERROR = 2; // 0x2
-    field public static final int STD3_ASCII_RULES_ERROR = 5; // 0x5
-    field public static final int UNASSIGNED_ERROR = 3; // 0x3
-    field public static final int VERIFICATION_ERROR = 7; // 0x7
-    field public static final int ZERO_LENGTH_LABEL = 10; // 0xa
-  }
-
-  public final class StringSearch extends android.icu.text.SearchIterator {
-    ctor public StringSearch(String, java.text.CharacterIterator, android.icu.text.RuleBasedCollator, android.icu.text.BreakIterator);
-    ctor public StringSearch(String, java.text.CharacterIterator, android.icu.text.RuleBasedCollator);
-    ctor public StringSearch(String, java.text.CharacterIterator, java.util.Locale);
-    ctor public StringSearch(String, java.text.CharacterIterator, android.icu.util.ULocale);
-    ctor public StringSearch(String, String);
-    method public android.icu.text.RuleBasedCollator getCollator();
-    method public int getIndex();
-    method public String getPattern();
-    method protected int handleNext(int);
-    method protected int handlePrevious(int);
-    method public boolean isCanonical();
-    method public void setCanonical(boolean);
-    method public void setCollator(android.icu.text.RuleBasedCollator);
-    method public void setPattern(String);
-  }
-
-  public interface SymbolTable {
-    method public char[] lookup(String);
-    method public android.icu.text.UnicodeMatcher lookupMatcher(int);
-    method public String parseReference(String, java.text.ParsePosition, int);
-    field public static final char SYMBOL_REF = 36; // 0x0024 '$'
-  }
-
-  public class TimeZoneFormat extends android.icu.text.UFormat implements android.icu.util.Freezable<android.icu.text.TimeZoneFormat> java.io.Serializable {
-    ctor protected TimeZoneFormat(android.icu.util.ULocale);
-    method public android.icu.text.TimeZoneFormat cloneAsThawed();
-    method public final String format(android.icu.text.TimeZoneFormat.Style, android.icu.util.TimeZone, long);
-    method public String format(android.icu.text.TimeZoneFormat.Style, android.icu.util.TimeZone, long, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>);
-    method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition);
-    method public final String formatOffsetISO8601Basic(int, boolean, boolean, boolean);
-    method public final String formatOffsetISO8601Extended(int, boolean, boolean, boolean);
-    method public String formatOffsetLocalizedGMT(int);
-    method public String formatOffsetShortLocalizedGMT(int);
-    method public android.icu.text.TimeZoneFormat freeze();
-    method public java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption> getDefaultParseOptions();
-    method public String getGMTOffsetDigits();
-    method public String getGMTOffsetPattern(android.icu.text.TimeZoneFormat.GMTOffsetPatternType);
-    method public String getGMTPattern();
-    method public String getGMTZeroFormat();
-    method public static android.icu.text.TimeZoneFormat getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.TimeZoneFormat getInstance(java.util.Locale);
-    method public android.icu.text.TimeZoneNames getTimeZoneNames();
-    method public boolean isFrozen();
-    method public android.icu.util.TimeZone parse(android.icu.text.TimeZoneFormat.Style, String, java.text.ParsePosition, java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption>, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>);
-    method public android.icu.util.TimeZone parse(android.icu.text.TimeZoneFormat.Style, String, java.text.ParsePosition, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>);
-    method public final android.icu.util.TimeZone parse(String, java.text.ParsePosition);
-    method public final android.icu.util.TimeZone parse(String) throws java.text.ParseException;
-    method public Object parseObject(String, java.text.ParsePosition);
-    method public final int parseOffsetISO8601(String, java.text.ParsePosition);
-    method public int parseOffsetLocalizedGMT(String, java.text.ParsePosition);
-    method public int parseOffsetShortLocalizedGMT(String, java.text.ParsePosition);
-    method public android.icu.text.TimeZoneFormat setDefaultParseOptions(java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption>);
-    method public android.icu.text.TimeZoneFormat setGMTOffsetDigits(String);
-    method public android.icu.text.TimeZoneFormat setGMTOffsetPattern(android.icu.text.TimeZoneFormat.GMTOffsetPatternType, String);
-    method public android.icu.text.TimeZoneFormat setGMTPattern(String);
-    method public android.icu.text.TimeZoneFormat setGMTZeroFormat(String);
-    method public android.icu.text.TimeZoneFormat setTimeZoneNames(android.icu.text.TimeZoneNames);
-  }
-
-  public enum TimeZoneFormat.GMTOffsetPatternType {
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_H;
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_HM;
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_HMS;
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_H;
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_HM;
-    enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_HMS;
-  }
-
-  public enum TimeZoneFormat.ParseOption {
-    enum_constant public static final android.icu.text.TimeZoneFormat.ParseOption ALL_STYLES;
-    enum_constant public static final android.icu.text.TimeZoneFormat.ParseOption TZ_DATABASE_ABBREVIATIONS;
-  }
-
-  public enum TimeZoneFormat.Style {
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style EXEMPLAR_LOCATION;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_LOCATION;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_LONG;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_SHORT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_FIXED;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_FULL;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_FIXED;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_FULL;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_SHORT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_SHORT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_FIXED;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_FULL;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_LOCAL_FIXED;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_LOCAL_FULL;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style LOCALIZED_GMT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style LOCALIZED_GMT_SHORT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style SPECIFIC_LONG;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style SPECIFIC_SHORT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ZONE_ID;
-    enum_constant public static final android.icu.text.TimeZoneFormat.Style ZONE_ID_SHORT;
-  }
-
-  public enum TimeZoneFormat.TimeType {
-    enum_constant public static final android.icu.text.TimeZoneFormat.TimeType DAYLIGHT;
-    enum_constant public static final android.icu.text.TimeZoneFormat.TimeType STANDARD;
-    enum_constant public static final android.icu.text.TimeZoneFormat.TimeType UNKNOWN;
-  }
-
-  public abstract class TimeZoneNames implements java.io.Serializable {
-    method public abstract java.util.Set<java.lang.String> getAvailableMetaZoneIDs();
-    method public abstract java.util.Set<java.lang.String> getAvailableMetaZoneIDs(String);
-    method public final String getDisplayName(String, android.icu.text.TimeZoneNames.NameType, long);
-    method public String getExemplarLocationName(String);
-    method public static android.icu.text.TimeZoneNames getInstance(android.icu.util.ULocale);
-    method public static android.icu.text.TimeZoneNames getInstance(java.util.Locale);
-    method public abstract String getMetaZoneDisplayName(String, android.icu.text.TimeZoneNames.NameType);
-    method public abstract String getMetaZoneID(String, long);
-    method public abstract String getReferenceZoneID(String, String);
-    method public static android.icu.text.TimeZoneNames getTZDBInstance(android.icu.util.ULocale);
-    method public abstract String getTimeZoneDisplayName(String, android.icu.text.TimeZoneNames.NameType);
-  }
-
-  public enum TimeZoneNames.NameType {
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType EXEMPLAR_LOCATION;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_DAYLIGHT;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_GENERIC;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_STANDARD;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_DAYLIGHT;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_GENERIC;
-    enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_STANDARD;
-  }
-
-  public abstract class Transliterator {
-    method public static final android.icu.text.Transliterator createFromRules(String, String, int);
-    method public void filteredTransliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, boolean);
-    method public final void finishTransliteration(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
-    method public static final java.util.Enumeration<java.lang.String> getAvailableIDs();
-    method public static final java.util.Enumeration<java.lang.String> getAvailableSources();
-    method public static final java.util.Enumeration<java.lang.String> getAvailableTargets(String);
-    method public static final java.util.Enumeration<java.lang.String> getAvailableVariants(String, String);
-    method public static final String getDisplayName(String);
-    method public static String getDisplayName(String, java.util.Locale);
-    method public static String getDisplayName(String, android.icu.util.ULocale);
-    method public android.icu.text.Transliterator[] getElements();
-    method public final android.icu.text.UnicodeFilter getFilter();
-    method public final String getID();
-    method public static final android.icu.text.Transliterator getInstance(String);
-    method public static android.icu.text.Transliterator getInstance(String, int);
-    method public final android.icu.text.Transliterator getInverse();
-    method public final int getMaximumContextLength();
-    method public final android.icu.text.UnicodeSet getSourceSet();
-    method public android.icu.text.UnicodeSet getTargetSet();
-    method public void setFilter(android.icu.text.UnicodeFilter);
-    method public String toRules(boolean);
-    method public final int transliterate(android.icu.text.Replaceable, int, int);
-    method public final void transliterate(android.icu.text.Replaceable);
-    method public final String transliterate(String);
-    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, String);
-    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, int);
-    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
-    field public static final int FORWARD = 0; // 0x0
-    field public static final int REVERSE = 1; // 0x1
-  }
-
-  public static class Transliterator.Position {
-    ctor public Transliterator.Position();
-    ctor public Transliterator.Position(int, int, int);
-    ctor public Transliterator.Position(int, int, int, int);
-    ctor public Transliterator.Position(android.icu.text.Transliterator.Position);
-    method public void set(android.icu.text.Transliterator.Position);
-    method public final void validate(int);
-    field public int contextLimit;
-    field public int contextStart;
-    field public int limit;
-    field public int start;
-  }
-
-  public abstract class UCharacterIterator implements java.lang.Cloneable {
-    ctor protected UCharacterIterator();
-    method public Object clone() throws java.lang.CloneNotSupportedException;
-    method public abstract int current();
-    method public int currentCodePoint();
-    method public java.text.CharacterIterator getCharacterIterator();
-    method public abstract int getIndex();
-    method public static final android.icu.text.UCharacterIterator getInstance(android.icu.text.Replaceable);
-    method public static final android.icu.text.UCharacterIterator getInstance(String);
-    method public static final android.icu.text.UCharacterIterator getInstance(char[]);
-    method public static final android.icu.text.UCharacterIterator getInstance(char[], int, int);
-    method public static final android.icu.text.UCharacterIterator getInstance(StringBuffer);
-    method public static final android.icu.text.UCharacterIterator getInstance(java.text.CharacterIterator);
-    method public abstract int getLength();
-    method public abstract int getText(char[], int);
-    method public final int getText(char[]);
-    method public String getText();
-    method public int moveCodePointIndex(int);
-    method public int moveIndex(int);
-    method public abstract int next();
-    method public int nextCodePoint();
-    method public abstract int previous();
-    method public int previousCodePoint();
-    method public abstract void setIndex(int);
-    method public void setToLimit();
-    method public void setToStart();
-    field public static final int DONE = -1; // 0xffffffff
-  }
-
-  public abstract class UFormat extends java.text.Format {
-    ctor public UFormat();
-  }
-
-  public abstract class UnicodeFilter implements android.icu.text.UnicodeMatcher {
-    method public abstract boolean contains(int);
-    method public int matches(android.icu.text.Replaceable, int[], int, boolean);
-  }
-
-  public interface UnicodeMatcher {
-    method public void addMatchSetTo(android.icu.text.UnicodeSet);
-    method public int matches(android.icu.text.Replaceable, int[], int, boolean);
-    method public boolean matchesIndexValue(int);
-    method public String toPattern(boolean);
-    field public static final char ETHER = 65535; // 0xffff '\uffff'
-    field public static final int U_MATCH = 2; // 0x2
-    field public static final int U_MISMATCH = 0; // 0x0
-    field public static final int U_PARTIAL_MATCH = 1; // 0x1
-  }
-
-  public class UnicodeSet extends android.icu.text.UnicodeFilter implements java.lang.Comparable<android.icu.text.UnicodeSet> android.icu.util.Freezable<android.icu.text.UnicodeSet> java.lang.Iterable<java.lang.String> {
-    ctor public UnicodeSet();
-    ctor public UnicodeSet(android.icu.text.UnicodeSet);
-    ctor public UnicodeSet(int, int);
-    ctor public UnicodeSet(int...);
-    ctor public UnicodeSet(String);
-    ctor public UnicodeSet(String, boolean);
-    ctor public UnicodeSet(String, int);
-    ctor public UnicodeSet(String, java.text.ParsePosition, android.icu.text.SymbolTable);
-    ctor public UnicodeSet(String, java.text.ParsePosition, android.icu.text.SymbolTable, int);
-    method public StringBuffer _generatePattern(StringBuffer, boolean);
-    method public StringBuffer _generatePattern(StringBuffer, boolean, boolean);
-    method public android.icu.text.UnicodeSet add(int, int);
-    method public final android.icu.text.UnicodeSet add(int);
-    method public final android.icu.text.UnicodeSet add(CharSequence);
-    method public android.icu.text.UnicodeSet add(Iterable<?>);
-    method public android.icu.text.UnicodeSet addAll(int, int);
-    method public final android.icu.text.UnicodeSet addAll(CharSequence);
-    method public android.icu.text.UnicodeSet addAll(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet addAll(Iterable<?>);
-    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet addAll(T...);
-    method public <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
-    method public void addMatchSetTo(android.icu.text.UnicodeSet);
-    method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
-    method public final android.icu.text.UnicodeSet applyPattern(String);
-    method public android.icu.text.UnicodeSet applyPattern(String, boolean);
-    method public android.icu.text.UnicodeSet applyPattern(String, int);
-    method public android.icu.text.UnicodeSet applyPropertyAlias(String, String);
-    method public android.icu.text.UnicodeSet applyPropertyAlias(String, String, android.icu.text.SymbolTable);
-    method public int charAt(int);
-    method public android.icu.text.UnicodeSet clear();
-    method public Object clone();
-    method public android.icu.text.UnicodeSet cloneAsThawed();
-    method public android.icu.text.UnicodeSet closeOver(int);
-    method public android.icu.text.UnicodeSet compact();
-    method public int compareTo(android.icu.text.UnicodeSet);
-    method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
-    method public int compareTo(Iterable<java.lang.String>);
-    method public android.icu.text.UnicodeSet complement(int, int);
-    method public final android.icu.text.UnicodeSet complement(int);
-    method public android.icu.text.UnicodeSet complement();
-    method public final android.icu.text.UnicodeSet complement(CharSequence);
-    method public final android.icu.text.UnicodeSet complementAll(CharSequence);
-    method public android.icu.text.UnicodeSet complementAll(android.icu.text.UnicodeSet);
-    method public boolean contains(int);
-    method public boolean contains(int, int);
-    method public final boolean contains(CharSequence);
-    method public boolean containsAll(android.icu.text.UnicodeSet);
-    method public boolean containsAll(String);
-    method public <T extends java.lang.CharSequence> boolean containsAll(Iterable<T>);
-    method public boolean containsNone(int, int);
-    method public boolean containsNone(android.icu.text.UnicodeSet);
-    method public boolean containsNone(CharSequence);
-    method public <T extends java.lang.CharSequence> boolean containsNone(Iterable<T>);
-    method public final boolean containsSome(int, int);
-    method public final boolean containsSome(android.icu.text.UnicodeSet);
-    method public final boolean containsSome(CharSequence);
-    method public final <T extends java.lang.CharSequence> boolean containsSome(Iterable<T>);
-    method public android.icu.text.UnicodeSet freeze();
-    method public static android.icu.text.UnicodeSet from(CharSequence);
-    method public static android.icu.text.UnicodeSet fromAll(CharSequence);
-    method public int getRangeCount();
-    method public int getRangeEnd(int);
-    method public int getRangeStart(int);
-    method public int indexOf(int);
-    method public boolean isEmpty();
-    method public boolean isFrozen();
-    method public java.util.Iterator<java.lang.String> iterator();
-    method public boolean matchesIndexValue(int);
-    method public Iterable<android.icu.text.UnicodeSet.EntryRange> ranges();
-    method public android.icu.text.UnicodeSet remove(int, int);
-    method public final android.icu.text.UnicodeSet remove(int);
-    method public final android.icu.text.UnicodeSet remove(CharSequence);
-    method public final android.icu.text.UnicodeSet removeAll(CharSequence);
-    method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
-    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet removeAll(Iterable<T>);
-    method public final android.icu.text.UnicodeSet removeAllStrings();
-    method public android.icu.text.UnicodeSet retain(int, int);
-    method public final android.icu.text.UnicodeSet retain(int);
-    method public final android.icu.text.UnicodeSet retain(CharSequence);
-    method public final android.icu.text.UnicodeSet retainAll(CharSequence);
-    method public android.icu.text.UnicodeSet retainAll(android.icu.text.UnicodeSet);
-    method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet retainAll(Iterable<T>);
-    method public android.icu.text.UnicodeSet set(int, int);
-    method public android.icu.text.UnicodeSet set(android.icu.text.UnicodeSet);
-    method public int size();
-    method public int span(CharSequence, android.icu.text.UnicodeSet.SpanCondition);
-    method public int span(CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
-    method public int spanBack(CharSequence, android.icu.text.UnicodeSet.SpanCondition);
-    method public int spanBack(CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
-    method public java.util.Collection<java.lang.String> strings();
-    method public String toPattern(boolean);
-    field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
-    field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
-    field public static final int CASE = 2; // 0x2
-    field public static final int CASE_INSENSITIVE = 2; // 0x2
-    field public static final android.icu.text.UnicodeSet EMPTY;
-    field public static final int IGNORE_SPACE = 1; // 0x1
-    field public static final int MAX_VALUE = 1114111; // 0x10ffff
-    field public static final int MIN_VALUE = 0; // 0x0
-  }
-
-  public enum UnicodeSet.ComparisonStyle {
-    enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle LEXICOGRAPHIC;
-    enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle LONGER_FIRST;
-    enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle SHORTER_FIRST;
-  }
-
-  public static class UnicodeSet.EntryRange {
-    field public int codepoint;
-    field public int codepointEnd;
-  }
-
-  public enum UnicodeSet.SpanCondition {
-    enum_constant public static final android.icu.text.UnicodeSet.SpanCondition CONDITION_COUNT;
-    enum_constant public static final android.icu.text.UnicodeSet.SpanCondition CONTAINED;
-    enum_constant public static final android.icu.text.UnicodeSet.SpanCondition NOT_CONTAINED;
-    enum_constant public static final android.icu.text.UnicodeSet.SpanCondition SIMPLE;
-  }
-
-  public class UnicodeSetIterator {
-    ctor public UnicodeSetIterator(android.icu.text.UnicodeSet);
-    ctor public UnicodeSetIterator();
-    method public String getString();
-    method public boolean next();
-    method public boolean nextRange();
-    method public void reset(android.icu.text.UnicodeSet);
-    method public void reset();
-    field public static int IS_STRING;
-    field public int codepoint;
-    field public int codepointEnd;
-    field public String string;
-  }
-
-  public class UnicodeSetSpanner {
-    ctor public UnicodeSetSpanner(android.icu.text.UnicodeSet);
-    method public int countIn(CharSequence);
-    method public int countIn(CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod);
-    method public int countIn(CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod, android.icu.text.UnicodeSet.SpanCondition);
-    method public String deleteFrom(CharSequence);
-    method public String deleteFrom(CharSequence, android.icu.text.UnicodeSet.SpanCondition);
-    method public android.icu.text.UnicodeSet getUnicodeSet();
-    method public String replaceFrom(CharSequence, CharSequence);
-    method public String replaceFrom(CharSequence, CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod);
-    method public String replaceFrom(CharSequence, CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod, android.icu.text.UnicodeSet.SpanCondition);
-    method public CharSequence trim(CharSequence);
-    method public CharSequence trim(CharSequence, android.icu.text.UnicodeSetSpanner.TrimOption);
-    method public CharSequence trim(CharSequence, android.icu.text.UnicodeSetSpanner.TrimOption, android.icu.text.UnicodeSet.SpanCondition);
-  }
-
-  public enum UnicodeSetSpanner.CountMethod {
-    enum_constant public static final android.icu.text.UnicodeSetSpanner.CountMethod MIN_ELEMENTS;
-    enum_constant public static final android.icu.text.UnicodeSetSpanner.CountMethod WHOLE_SPAN;
-  }
-
-  public enum UnicodeSetSpanner.TrimOption {
-    enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption BOTH;
-    enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption LEADING;
-    enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption TRAILING;
-  }
-
-}
-
-package android.icu.util {
-
-  public class BuddhistCalendar extends android.icu.util.GregorianCalendar {
-    ctor public BuddhistCalendar();
-    ctor public BuddhistCalendar(android.icu.util.TimeZone);
-    ctor public BuddhistCalendar(java.util.Locale);
-    ctor public BuddhistCalendar(android.icu.util.ULocale);
-    ctor public BuddhistCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public BuddhistCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public BuddhistCalendar(java.util.Date);
-    ctor public BuddhistCalendar(int, int, int);
-    ctor public BuddhistCalendar(int, int, int, int, int, int);
-    field public static final int BE = 0; // 0x0
-  }
-
-  public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable<android.icu.util.Calendar> java.io.Serializable {
-    ctor protected Calendar();
-    ctor protected Calendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor protected Calendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    method public void add(int, int);
-    method public boolean after(Object);
-    method public boolean before(Object);
-    method public final void clear();
-    method public final void clear(int);
-    method public Object clone();
-    method public int compareTo(android.icu.util.Calendar);
-    method protected void complete();
-    method protected void computeFields();
-    method protected final void computeGregorianFields(int);
-    method protected int computeGregorianMonthStart(int, int);
-    method protected int computeJulianDay();
-    method @Deprecated protected int computeMillisInDay();
-    method protected void computeTime();
-    method @Deprecated protected int computeZoneOffset(long, int);
-    method public int fieldDifference(java.util.Date, int);
-    method protected String fieldName(int);
-    method protected static final long floorDivide(long, long);
-    method protected static final int floorDivide(int, int);
-    method protected static final int floorDivide(int, int, int[]);
-    method protected static final int floorDivide(long, int, int[]);
-    method public final int get(int);
-    method public int getActualMaximum(int);
-    method public int getActualMinimum(int);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public android.icu.text.DateFormat getDateTimeFormat(int, int, java.util.Locale);
-    method public android.icu.text.DateFormat getDateTimeFormat(int, int, android.icu.util.ULocale);
-    method public String getDisplayName(java.util.Locale);
-    method public String getDisplayName(android.icu.util.ULocale);
-    method public final int getFieldCount();
-    method protected int[][][] getFieldResolutionTable();
-    method public int getFirstDayOfWeek();
-    method public final int getGreatestMinimum(int);
-    method protected final int getGregorianDayOfMonth();
-    method protected final int getGregorianDayOfYear();
-    method protected final int getGregorianMonth();
-    method protected final int getGregorianYear();
-    method public static android.icu.util.Calendar getInstance();
-    method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone);
-    method public static android.icu.util.Calendar getInstance(java.util.Locale);
-    method public static android.icu.util.Calendar getInstance(android.icu.util.ULocale);
-    method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone, java.util.Locale);
-    method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone, android.icu.util.ULocale);
-    method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean);
-    method public final int getLeastMaximum(int);
-    method protected int getLimit(int, int);
-    method public final int getMaximum(int);
-    method public int getMinimalDaysInFirstWeek();
-    method public final int getMinimum(int);
-    method public int getRepeatedWallTimeOption();
-    method public int getSkippedWallTimeOption();
-    method protected final int getStamp(int);
-    method public final java.util.Date getTime();
-    method public long getTimeInMillis();
-    method public android.icu.util.TimeZone getTimeZone();
-    method public String getType();
-    method public android.icu.util.Calendar.WeekData getWeekData();
-    method public static android.icu.util.Calendar.WeekData getWeekDataForRegion(String);
-    method protected static final int gregorianMonthLength(int, int);
-    method protected static final int gregorianPreviousMonthLength(int, int);
-    method protected void handleComputeFields(int);
-    method protected int handleComputeJulianDay(int);
-    method protected abstract int handleComputeMonthStart(int, int, boolean);
-    method protected int[] handleCreateFields();
-    method protected android.icu.text.DateFormat handleGetDateFormat(String, java.util.Locale);
-    method protected android.icu.text.DateFormat handleGetDateFormat(String, String, java.util.Locale);
-    method protected android.icu.text.DateFormat handleGetDateFormat(String, android.icu.util.ULocale);
-    method protected abstract int handleGetExtendedYear();
-    method protected abstract int handleGetLimit(int, int);
-    method protected int handleGetMonthLength(int, int);
-    method protected int handleGetYearLength(int);
-    method protected final int internalGet(int);
-    method protected final int internalGet(int, int);
-    method protected final long internalGetTimeInMillis();
-    method protected final void internalSet(int, int);
-    method public boolean isEquivalentTo(android.icu.util.Calendar);
-    method protected static final boolean isGregorianLeapYear(int);
-    method public boolean isLenient();
-    method public final boolean isSet(int);
-    method public boolean isWeekend(java.util.Date);
-    method public boolean isWeekend();
-    method protected static final int julianDayToDayOfWeek(int);
-    method protected static final long julianDayToMillis(int);
-    method protected static final int millisToJulianDay(long);
-    method protected int newerField(int, int);
-    method protected int newestStamp(int, int, int);
-    method protected void pinField(int);
-    method protected void prepareGetActual(int, boolean);
-    method protected int resolveFields(int[][][]);
-    method public final void roll(int, boolean);
-    method public void roll(int, int);
-    method public final void set(int, int);
-    method public final void set(int, int, int);
-    method public final void set(int, int, int, int, int);
-    method public final void set(int, int, int, int, int, int);
-    method public void setFirstDayOfWeek(int);
-    method public void setLenient(boolean);
-    method public void setMinimalDaysInFirstWeek(int);
-    method public void setRepeatedWallTimeOption(int);
-    method public void setSkippedWallTimeOption(int);
-    method public final void setTime(java.util.Date);
-    method public void setTimeInMillis(long);
-    method public void setTimeZone(android.icu.util.TimeZone);
-    method public android.icu.util.Calendar setWeekData(android.icu.util.Calendar.WeekData);
-    method protected void validateField(int);
-    method protected final void validateField(int, int, int);
-    method protected void validateFields();
-    method protected int weekNumber(int, int, int);
-    method protected final int weekNumber(int, int);
-    field public static final int AM = 0; // 0x0
-    field public static final int AM_PM = 9; // 0x9
-    field public static final int APRIL = 3; // 0x3
-    field public static final int AUGUST = 7; // 0x7
-    field @Deprecated protected static final int BASE_FIELD_COUNT = 23; // 0x17
-    field public static final int DATE = 5; // 0x5
-    field public static final int DAY_OF_MONTH = 5; // 0x5
-    field public static final int DAY_OF_WEEK = 7; // 0x7
-    field public static final int DAY_OF_WEEK_IN_MONTH = 8; // 0x8
-    field public static final int DAY_OF_YEAR = 6; // 0x6
-    field public static final int DECEMBER = 11; // 0xb
-    field public static final int DOW_LOCAL = 18; // 0x12
-    field public static final int DST_OFFSET = 16; // 0x10
-    field protected static final int EPOCH_JULIAN_DAY = 2440588; // 0x253d8c
-    field public static final int ERA = 0; // 0x0
-    field public static final int EXTENDED_YEAR = 19; // 0x13
-    field public static final int FEBRUARY = 1; // 0x1
-    field public static final int FRIDAY = 6; // 0x6
-    field protected static final int GREATEST_MINIMUM = 1; // 0x1
-    field public static final int HOUR = 10; // 0xa
-    field public static final int HOUR_OF_DAY = 11; // 0xb
-    field protected static final int INTERNALLY_SET = 1; // 0x1
-    field public static final int IS_LEAP_MONTH = 22; // 0x16
-    field public static final int JANUARY = 0; // 0x0
-    field protected static final int JAN_1_1_JULIAN_DAY = 1721426; // 0x1a4452
-    field public static final int JULIAN_DAY = 20; // 0x14
-    field public static final int JULY = 6; // 0x6
-    field public static final int JUNE = 5; // 0x5
-    field protected static final int LEAST_MAXIMUM = 2; // 0x2
-    field public static final int MARCH = 2; // 0x2
-    field protected static final int MAXIMUM = 3; // 0x3
-    field protected static final java.util.Date MAX_DATE;
-    field @Deprecated protected static final int MAX_FIELD_COUNT = 32; // 0x20
-    field protected static final int MAX_JULIAN = 2130706432; // 0x7f000000
-    field protected static final long MAX_MILLIS = 183882168921600000L; // 0x28d47dbbf19b000L
-    field public static final int MAY = 4; // 0x4
-    field public static final int MILLISECOND = 14; // 0xe
-    field public static final int MILLISECONDS_IN_DAY = 21; // 0x15
-    field protected static final int MINIMUM = 0; // 0x0
-    field protected static final int MINIMUM_USER_STAMP = 2; // 0x2
-    field public static final int MINUTE = 12; // 0xc
-    field protected static final java.util.Date MIN_DATE;
-    field protected static final int MIN_JULIAN = -2130706432; // 0x81000000
-    field protected static final long MIN_MILLIS = -184303902528000000L; // 0xfd713893bf19b000L
-    field public static final int MONDAY = 2; // 0x2
-    field public static final int MONTH = 2; // 0x2
-    field public static final int NOVEMBER = 10; // 0xa
-    field public static final int OCTOBER = 9; // 0x9
-    field protected static final long ONE_DAY = 86400000L; // 0x5265c00L
-    field protected static final int ONE_HOUR = 3600000; // 0x36ee80
-    field protected static final int ONE_MINUTE = 60000; // 0xea60
-    field protected static final int ONE_SECOND = 1000; // 0x3e8
-    field protected static final long ONE_WEEK = 604800000L; // 0x240c8400L
-    field public static final int PM = 1; // 0x1
-    field protected static final int RESOLVE_REMAP = 32; // 0x20
-    field public static final int SATURDAY = 7; // 0x7
-    field public static final int SECOND = 13; // 0xd
-    field public static final int SEPTEMBER = 8; // 0x8
-    field public static final int SUNDAY = 1; // 0x1
-    field public static final int THURSDAY = 5; // 0x5
-    field public static final int TUESDAY = 3; // 0x3
-    field public static final int UNDECIMBER = 12; // 0xc
-    field protected static final int UNSET = 0; // 0x0
-    field public static final int WALLTIME_FIRST = 1; // 0x1
-    field public static final int WALLTIME_LAST = 0; // 0x0
-    field public static final int WALLTIME_NEXT_VALID = 2; // 0x2
-    field public static final int WEDNESDAY = 4; // 0x4
-    field public static final int WEEK_OF_MONTH = 4; // 0x4
-    field public static final int WEEK_OF_YEAR = 3; // 0x3
-    field public static final int YEAR = 1; // 0x1
-    field public static final int YEAR_WOY = 17; // 0x11
-    field public static final int ZONE_OFFSET = 15; // 0xf
-  }
-
-  public static final class Calendar.WeekData {
-    ctor public Calendar.WeekData(int, int, int, int, int, int);
-    field public final int firstDayOfWeek;
-    field public final int minimalDaysInFirstWeek;
-    field public final int weekendCease;
-    field public final int weekendCeaseMillis;
-    field public final int weekendOnset;
-    field public final int weekendOnsetMillis;
-  }
-
-  public class ChineseCalendar extends android.icu.util.Calendar {
-    ctor public ChineseCalendar();
-    ctor public ChineseCalendar(java.util.Date);
-    ctor public ChineseCalendar(int, int, int, int);
-    ctor public ChineseCalendar(int, int, int, int, int, int, int);
-    ctor public ChineseCalendar(int, int, int, int, int);
-    ctor public ChineseCalendar(int, int, int, int, int, int, int, int);
-    ctor public ChineseCalendar(java.util.Locale);
-    ctor public ChineseCalendar(android.icu.util.TimeZone);
-    ctor public ChineseCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public ChineseCalendar(android.icu.util.ULocale);
-    ctor public ChineseCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method protected android.icu.text.DateFormat handleGetDateFormat(String, String, android.icu.util.ULocale);
-    method protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-  }
-
-  public final class CopticCalendar extends android.icu.util.Calendar {
-    ctor public CopticCalendar();
-    ctor public CopticCalendar(android.icu.util.TimeZone);
-    ctor public CopticCalendar(java.util.Locale);
-    ctor public CopticCalendar(android.icu.util.ULocale);
-    ctor public CopticCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public CopticCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public CopticCalendar(int, int, int);
-    ctor public CopticCalendar(java.util.Date);
-    ctor public CopticCalendar(int, int, int, int, int, int);
-    method @Deprecated protected void handleComputeFields(int);
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method @Deprecated protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-    field public static final int AMSHIR = 5; // 0x5
-    field public static final int BABA = 1; // 0x1
-    field public static final int BARAMHAT = 6; // 0x6
-    field public static final int BARAMOUDA = 7; // 0x7
-    field public static final int BASHANS = 8; // 0x8
-    field public static final int EPEP = 10; // 0xa
-    field public static final int HATOR = 2; // 0x2
-    field public static final int KIAHK = 3; // 0x3
-    field public static final int MESRA = 11; // 0xb
-    field public static final int NASIE = 12; // 0xc
-    field public static final int PAONA = 9; // 0x9
-    field public static final int TOBA = 4; // 0x4
-    field public static final int TOUT = 0; // 0x0
-  }
-
-  public class Currency extends android.icu.util.MeasureUnit {
-    ctor protected Currency(String);
-    method public static android.icu.util.Currency fromJavaCurrency(java.util.Currency);
-    method public static java.util.Set<android.icu.util.Currency> getAvailableCurrencies();
-    method public static String[] getAvailableCurrencyCodes(android.icu.util.ULocale, java.util.Date);
-    method public static String[] getAvailableCurrencyCodes(java.util.Locale, java.util.Date);
-    method public static java.util.Locale[] getAvailableLocales();
-    method public static android.icu.util.ULocale[] getAvailableULocales();
-    method public String getCurrencyCode();
-    method public int getDefaultFractionDigits();
-    method public int getDefaultFractionDigits(android.icu.util.Currency.CurrencyUsage);
-    method public String getDisplayName();
-    method public String getDisplayName(java.util.Locale);
-    method public static android.icu.util.Currency getInstance(java.util.Locale);
-    method public static android.icu.util.Currency getInstance(android.icu.util.ULocale);
-    method public static android.icu.util.Currency getInstance(String);
-    method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean);
-    method public String getName(java.util.Locale, int, boolean[]);
-    method public String getName(android.icu.util.ULocale, int, boolean[]);
-    method public String getName(java.util.Locale, int, String, boolean[]);
-    method public String getName(android.icu.util.ULocale, int, String, boolean[]);
-    method public int getNumericCode();
-    method public double getRoundingIncrement();
-    method public double getRoundingIncrement(android.icu.util.Currency.CurrencyUsage);
-    method public String getSymbol();
-    method public String getSymbol(java.util.Locale);
-    method public String getSymbol(android.icu.util.ULocale);
-    method public static boolean isAvailable(String, java.util.Date, java.util.Date);
-    method public java.util.Currency toJavaCurrency();
-    field public static final int LONG_NAME = 1; // 0x1
-    field public static final int NARROW_SYMBOL_NAME = 3; // 0x3
-    field public static final int PLURAL_LONG_NAME = 2; // 0x2
-    field public static final int SYMBOL_NAME = 0; // 0x0
-  }
-
-  public enum Currency.CurrencyUsage {
-    enum_constant public static final android.icu.util.Currency.CurrencyUsage CASH;
-    enum_constant public static final android.icu.util.Currency.CurrencyUsage STANDARD;
-  }
-
-  public class CurrencyAmount extends android.icu.util.Measure {
-    ctor public CurrencyAmount(Number, android.icu.util.Currency);
-    ctor public CurrencyAmount(double, android.icu.util.Currency);
-    ctor public CurrencyAmount(Number, java.util.Currency);
-    ctor public CurrencyAmount(double, java.util.Currency);
-    method public android.icu.util.Currency getCurrency();
-  }
-
-  public final class DateInterval implements java.io.Serializable {
-    ctor public DateInterval(long, long);
-    method public long getFromDate();
-    method public long getToDate();
-  }
-
-  public final class EthiopicCalendar extends android.icu.util.Calendar {
-    ctor public EthiopicCalendar();
-    ctor public EthiopicCalendar(android.icu.util.TimeZone);
-    ctor public EthiopicCalendar(java.util.Locale);
-    ctor public EthiopicCalendar(android.icu.util.ULocale);
-    ctor public EthiopicCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public EthiopicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public EthiopicCalendar(int, int, int);
-    ctor public EthiopicCalendar(java.util.Date);
-    ctor public EthiopicCalendar(int, int, int, int, int, int);
-    method @Deprecated protected void handleComputeFields(int);
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method @Deprecated protected int handleGetExtendedYear();
-    method @Deprecated protected int handleGetLimit(int, int);
-    method public boolean isAmeteAlemEra();
-    method public void setAmeteAlemEra(boolean);
-    field public static final int GENBOT = 8; // 0x8
-    field public static final int HAMLE = 10; // 0xa
-    field public static final int HEDAR = 2; // 0x2
-    field public static final int MEGABIT = 6; // 0x6
-    field public static final int MESKEREM = 0; // 0x0
-    field public static final int MIAZIA = 7; // 0x7
-    field public static final int NEHASSE = 11; // 0xb
-    field public static final int PAGUMEN = 12; // 0xc
-    field public static final int SENE = 9; // 0x9
-    field public static final int TAHSAS = 3; // 0x3
-    field public static final int TEKEMT = 1; // 0x1
-    field public static final int TER = 4; // 0x4
-    field public static final int YEKATIT = 5; // 0x5
-  }
-
-  public interface Freezable<T> extends java.lang.Cloneable {
-    method public T cloneAsThawed();
-    method public T freeze();
-    method public boolean isFrozen();
-  }
-
-  public class GregorianCalendar extends android.icu.util.Calendar {
-    ctor public GregorianCalendar();
-    ctor public GregorianCalendar(android.icu.util.TimeZone);
-    ctor public GregorianCalendar(java.util.Locale);
-    ctor public GregorianCalendar(android.icu.util.ULocale);
-    ctor public GregorianCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public GregorianCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public GregorianCalendar(int, int, int);
-    ctor public GregorianCalendar(int, int, int, int, int);
-    ctor public GregorianCalendar(int, int, int, int, int, int);
-    method public final java.util.Date getGregorianChange();
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-    method public boolean isLeapYear(int);
-    method public void setGregorianChange(java.util.Date);
-    field public static final int AD = 1; // 0x1
-    field public static final int BC = 0; // 0x0
-    field protected transient boolean invertGregorian;
-    field protected transient boolean isGregorian;
-  }
-
-  public class HebrewCalendar extends android.icu.util.Calendar {
-    ctor public HebrewCalendar();
-    ctor public HebrewCalendar(android.icu.util.TimeZone);
-    ctor public HebrewCalendar(java.util.Locale);
-    ctor public HebrewCalendar(android.icu.util.ULocale);
-    ctor public HebrewCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public HebrewCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public HebrewCalendar(int, int, int);
-    ctor public HebrewCalendar(java.util.Date);
-    ctor public HebrewCalendar(int, int, int, int, int, int);
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-    method @Deprecated protected void validateField(int);
-    field public static final int ADAR = 6; // 0x6
-    field public static final int ADAR_1 = 5; // 0x5
-    field public static final int AV = 11; // 0xb
-    field public static final int ELUL = 12; // 0xc
-    field public static final int HESHVAN = 1; // 0x1
-    field public static final int IYAR = 8; // 0x8
-    field public static final int KISLEV = 2; // 0x2
-    field public static final int NISAN = 7; // 0x7
-    field public static final int SHEVAT = 4; // 0x4
-    field public static final int SIVAN = 9; // 0x9
-    field public static final int TAMUZ = 10; // 0xa
-    field public static final int TEVET = 3; // 0x3
-    field public static final int TISHRI = 0; // 0x0
-  }
-
-  public class ICUUncheckedIOException extends java.lang.RuntimeException {
-    ctor public ICUUncheckedIOException();
-    ctor public ICUUncheckedIOException(String);
-    ctor public ICUUncheckedIOException(Throwable);
-    ctor public ICUUncheckedIOException(String, Throwable);
-  }
-
-  public class IllformedLocaleException extends java.lang.RuntimeException {
-    ctor public IllformedLocaleException();
-    ctor public IllformedLocaleException(String);
-    ctor public IllformedLocaleException(String, int);
-    method public int getErrorIndex();
-  }
-
-  public class IndianCalendar extends android.icu.util.Calendar {
-    ctor public IndianCalendar();
-    ctor public IndianCalendar(android.icu.util.TimeZone);
-    ctor public IndianCalendar(java.util.Locale);
-    ctor public IndianCalendar(android.icu.util.ULocale);
-    ctor public IndianCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public IndianCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public IndianCalendar(java.util.Date);
-    ctor public IndianCalendar(int, int, int);
-    ctor public IndianCalendar(int, int, int, int, int, int);
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-    field public static final int AGRAHAYANA = 8; // 0x8
-    field public static final int ASADHA = 3; // 0x3
-    field public static final int ASVINA = 6; // 0x6
-    field public static final int BHADRA = 5; // 0x5
-    field public static final int CHAITRA = 0; // 0x0
-    field public static final int IE = 0; // 0x0
-    field public static final int JYAISTHA = 2; // 0x2
-    field public static final int KARTIKA = 7; // 0x7
-    field public static final int MAGHA = 10; // 0xa
-    field public static final int PAUSA = 9; // 0x9
-    field public static final int PHALGUNA = 11; // 0xb
-    field public static final int SRAVANA = 4; // 0x4
-    field public static final int VAISAKHA = 1; // 0x1
-  }
-
-  public class IslamicCalendar extends android.icu.util.Calendar {
-    ctor public IslamicCalendar();
-    ctor public IslamicCalendar(android.icu.util.TimeZone);
-    ctor public IslamicCalendar(java.util.Locale);
-    ctor public IslamicCalendar(android.icu.util.ULocale);
-    ctor public IslamicCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public IslamicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public IslamicCalendar(java.util.Date);
-    ctor public IslamicCalendar(int, int, int);
-    ctor public IslamicCalendar(int, int, int, int, int, int);
-    method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
-    method protected int handleComputeMonthStart(int, int, boolean);
-    method protected int handleGetExtendedYear();
-    method protected int handleGetLimit(int, int);
-    method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
-    field public static final int DHU_AL_HIJJAH = 11; // 0xb
-    field public static final int DHU_AL_QIDAH = 10; // 0xa
-    field public static final int JUMADA_1 = 4; // 0x4
-    field public static final int JUMADA_2 = 5; // 0x5
-    field public static final int MUHARRAM = 0; // 0x0
-    field public static final int RABI_1 = 2; // 0x2
-    field public static final int RABI_2 = 3; // 0x3
-    field public static final int RAJAB = 6; // 0x6
-    field public static final int RAMADAN = 8; // 0x8
-    field public static final int SAFAR = 1; // 0x1
-    field public static final int SHABAN = 7; // 0x7
-    field public static final int SHAWWAL = 9; // 0x9
-  }
-
-  public enum IslamicCalendar.CalculationType {
-    enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC;
-    enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_CIVIL;
-    enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_TBLA;
-    enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_UMALQURA;
-  }
-
-  public class JapaneseCalendar extends android.icu.util.GregorianCalendar {
-    ctor public JapaneseCalendar();
-    ctor public JapaneseCalendar(android.icu.util.TimeZone);
-    ctor public JapaneseCalendar(java.util.Locale);
-    ctor public JapaneseCalendar(android.icu.util.ULocale);
-    ctor public JapaneseCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public JapaneseCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public JapaneseCalendar(java.util.Date);
-    ctor public JapaneseCalendar(int, int, int, int);
-    ctor public JapaneseCalendar(int, int, int);
-    ctor public JapaneseCalendar(int, int, int, int, int, int);
-    field public static final int HEISEI;
-    field public static final int MEIJI;
-    field public static final int REIWA;
-    field public static final int SHOWA;
-    field public static final int TAISHO;
-  }
-
-  public final class LocaleData {
-    method public static android.icu.util.VersionInfo getCLDRVersion();
-    method public String getDelimiter(int);
-    method public static android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
-    method public static android.icu.util.LocaleData getInstance();
-    method public static android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
-    method public boolean getNoSubstitute();
-    method public static android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
-    method public void setNoSubstitute(boolean);
-    field public static final int ALT_QUOTATION_END = 3; // 0x3
-    field public static final int ALT_QUOTATION_START = 2; // 0x2
-    field public static final int QUOTATION_END = 1; // 0x1
-    field public static final int QUOTATION_START = 0; // 0x0
-  }
-
-  public static final class LocaleData.MeasurementSystem {
-    field public static final android.icu.util.LocaleData.MeasurementSystem SI;
-    field public static final android.icu.util.LocaleData.MeasurementSystem UK;
-    field public static final android.icu.util.LocaleData.MeasurementSystem US;
-  }
-
-  public static final class LocaleData.PaperSize {
-    method public int getHeight();
-    method public int getWidth();
-  }
-
-  public class Measure {
-    ctor public Measure(Number, android.icu.util.MeasureUnit);
-    method public Number getNumber();
-    method public android.icu.util.MeasureUnit getUnit();
-  }
-
-  public class MeasureUnit implements java.io.Serializable {
-    method public static java.util.Set<android.icu.util.MeasureUnit> getAvailable(String);
-    method public static java.util.Set<android.icu.util.MeasureUnit> getAvailable();
-    method public static java.util.Set<java.lang.String> getAvailableTypes();
-    method public String getSubtype();
-    method public String getType();
-    field public static final android.icu.util.MeasureUnit ACRE;
-    field public static final android.icu.util.MeasureUnit ACRE_FOOT;
-    field public static final android.icu.util.MeasureUnit AMPERE;
-    field public static final android.icu.util.MeasureUnit ARC_MINUTE;
-    field public static final android.icu.util.MeasureUnit ARC_SECOND;
-    field public static final android.icu.util.MeasureUnit ASTRONOMICAL_UNIT;
-    field public static final android.icu.util.MeasureUnit ATMOSPHERE;
-    field public static final android.icu.util.MeasureUnit BIT;
-    field public static final android.icu.util.MeasureUnit BUSHEL;
-    field public static final android.icu.util.MeasureUnit BYTE;
-    field public static final android.icu.util.MeasureUnit CALORIE;
-    field public static final android.icu.util.MeasureUnit CARAT;
-    field public static final android.icu.util.MeasureUnit CELSIUS;
-    field public static final android.icu.util.MeasureUnit CENTILITER;
-    field public static final android.icu.util.MeasureUnit CENTIMETER;
-    field public static final android.icu.util.MeasureUnit CENTURY;
-    field public static final android.icu.util.MeasureUnit CUBIC_CENTIMETER;
-    field public static final android.icu.util.MeasureUnit CUBIC_FOOT;
-    field public static final android.icu.util.MeasureUnit CUBIC_INCH;
-    field public static final android.icu.util.MeasureUnit CUBIC_KILOMETER;
-    field public static final android.icu.util.MeasureUnit CUBIC_METER;
-    field public static final android.icu.util.MeasureUnit CUBIC_MILE;
-    field public static final android.icu.util.MeasureUnit CUBIC_YARD;
-    field public static final android.icu.util.MeasureUnit CUP;
-    field public static final android.icu.util.MeasureUnit CUP_METRIC;
-    field public static final android.icu.util.TimeUnit DAY;
-    field public static final android.icu.util.MeasureUnit DECILITER;
-    field public static final android.icu.util.MeasureUnit DECIMETER;
-    field public static final android.icu.util.MeasureUnit DEGREE;
-    field public static final android.icu.util.MeasureUnit FAHRENHEIT;
-    field public static final android.icu.util.MeasureUnit FATHOM;
-    field public static final android.icu.util.MeasureUnit FLUID_OUNCE;
-    field public static final android.icu.util.MeasureUnit FOODCALORIE;
-    field public static final android.icu.util.MeasureUnit FOOT;
-    field public static final android.icu.util.MeasureUnit FURLONG;
-    field public static final android.icu.util.MeasureUnit GALLON;
-    field public static final android.icu.util.MeasureUnit GALLON_IMPERIAL;
-    field public static final android.icu.util.MeasureUnit GENERIC_TEMPERATURE;
-    field public static final android.icu.util.MeasureUnit GIGABIT;
-    field public static final android.icu.util.MeasureUnit GIGABYTE;
-    field public static final android.icu.util.MeasureUnit GIGAHERTZ;
-    field public static final android.icu.util.MeasureUnit GIGAWATT;
-    field public static final android.icu.util.MeasureUnit GRAM;
-    field public static final android.icu.util.MeasureUnit G_FORCE;
-    field public static final android.icu.util.MeasureUnit HECTARE;
-    field public static final android.icu.util.MeasureUnit HECTOLITER;
-    field public static final android.icu.util.MeasureUnit HECTOPASCAL;
-    field public static final android.icu.util.MeasureUnit HERTZ;
-    field public static final android.icu.util.MeasureUnit HORSEPOWER;
-    field public static final android.icu.util.TimeUnit HOUR;
-    field public static final android.icu.util.MeasureUnit INCH;
-    field public static final android.icu.util.MeasureUnit INCH_HG;
-    field public static final android.icu.util.MeasureUnit JOULE;
-    field public static final android.icu.util.MeasureUnit KARAT;
-    field public static final android.icu.util.MeasureUnit KELVIN;
-    field public static final android.icu.util.MeasureUnit KILOBIT;
-    field public static final android.icu.util.MeasureUnit KILOBYTE;
-    field public static final android.icu.util.MeasureUnit KILOCALORIE;
-    field public static final android.icu.util.MeasureUnit KILOGRAM;
-    field public static final android.icu.util.MeasureUnit KILOHERTZ;
-    field public static final android.icu.util.MeasureUnit KILOJOULE;
-    field public static final android.icu.util.MeasureUnit KILOMETER;
-    field public static final android.icu.util.MeasureUnit KILOMETER_PER_HOUR;
-    field public static final android.icu.util.MeasureUnit KILOWATT;
-    field public static final android.icu.util.MeasureUnit KILOWATT_HOUR;
-    field public static final android.icu.util.MeasureUnit KNOT;
-    field public static final android.icu.util.MeasureUnit LIGHT_YEAR;
-    field public static final android.icu.util.MeasureUnit LITER;
-    field public static final android.icu.util.MeasureUnit LITER_PER_100KILOMETERS;
-    field public static final android.icu.util.MeasureUnit LITER_PER_KILOMETER;
-    field public static final android.icu.util.MeasureUnit LUX;
-    field public static final android.icu.util.MeasureUnit MEGABIT;
-    field public static final android.icu.util.MeasureUnit MEGABYTE;
-    field public static final android.icu.util.MeasureUnit MEGAHERTZ;
-    field public static final android.icu.util.MeasureUnit MEGALITER;
-    field public static final android.icu.util.MeasureUnit MEGAWATT;
-    field public static final android.icu.util.MeasureUnit METER;
-    field public static final android.icu.util.MeasureUnit METER_PER_SECOND;
-    field public static final android.icu.util.MeasureUnit METER_PER_SECOND_SQUARED;
-    field public static final android.icu.util.MeasureUnit METRIC_TON;
-    field public static final android.icu.util.MeasureUnit MICROGRAM;
-    field public static final android.icu.util.MeasureUnit MICROMETER;
-    field public static final android.icu.util.MeasureUnit MICROSECOND;
-    field public static final android.icu.util.MeasureUnit MILE;
-    field public static final android.icu.util.MeasureUnit MILE_PER_GALLON;
-    field public static final android.icu.util.MeasureUnit MILE_PER_GALLON_IMPERIAL;
-    field public static final android.icu.util.MeasureUnit MILE_PER_HOUR;
-    field public static final android.icu.util.MeasureUnit MILE_SCANDINAVIAN;
-    field public static final android.icu.util.MeasureUnit MILLIAMPERE;
-    field public static final android.icu.util.MeasureUnit MILLIBAR;
-    field public static final android.icu.util.MeasureUnit MILLIGRAM;
-    field public static final android.icu.util.MeasureUnit MILLIGRAM_PER_DECILITER;
-    field public static final android.icu.util.MeasureUnit MILLILITER;
-    field public static final android.icu.util.MeasureUnit MILLIMETER;
-    field public static final android.icu.util.MeasureUnit MILLIMETER_OF_MERCURY;
-    field public static final android.icu.util.MeasureUnit MILLIMOLE_PER_LITER;
-    field public static final android.icu.util.MeasureUnit MILLISECOND;
-    field public static final android.icu.util.MeasureUnit MILLIWATT;
-    field public static final android.icu.util.TimeUnit MINUTE;
-    field public static final android.icu.util.TimeUnit MONTH;
-    field public static final android.icu.util.MeasureUnit NANOMETER;
-    field public static final android.icu.util.MeasureUnit NANOSECOND;
-    field public static final android.icu.util.MeasureUnit NAUTICAL_MILE;
-    field public static final android.icu.util.MeasureUnit OHM;
-    field public static final android.icu.util.MeasureUnit OUNCE;
-    field public static final android.icu.util.MeasureUnit OUNCE_TROY;
-    field public static final android.icu.util.MeasureUnit PARSEC;
-    field public static final android.icu.util.MeasureUnit PART_PER_MILLION;
-    field public static final android.icu.util.MeasureUnit PERCENT;
-    field public static final android.icu.util.MeasureUnit PERMILLE;
-    field public static final android.icu.util.MeasureUnit PETABYTE;
-    field public static final android.icu.util.MeasureUnit PICOMETER;
-    field public static final android.icu.util.MeasureUnit PINT;
-    field public static final android.icu.util.MeasureUnit PINT_METRIC;
-    field public static final android.icu.util.MeasureUnit POINT;
-    field public static final android.icu.util.MeasureUnit POUND;
-    field public static final android.icu.util.MeasureUnit POUND_PER_SQUARE_INCH;
-    field public static final android.icu.util.MeasureUnit QUART;
-    field public static final android.icu.util.MeasureUnit RADIAN;
-    field public static final android.icu.util.MeasureUnit REVOLUTION_ANGLE;
-    field public static final android.icu.util.TimeUnit SECOND;
-    field public static final android.icu.util.MeasureUnit SQUARE_CENTIMETER;
-    field public static final android.icu.util.MeasureUnit SQUARE_FOOT;
-    field public static final android.icu.util.MeasureUnit SQUARE_INCH;
-    field public static final android.icu.util.MeasureUnit SQUARE_KILOMETER;
-    field public static final android.icu.util.MeasureUnit SQUARE_METER;
-    field public static final android.icu.util.MeasureUnit SQUARE_MILE;
-    field public static final android.icu.util.MeasureUnit SQUARE_YARD;
-    field public static final android.icu.util.MeasureUnit STONE;
-    field public static final android.icu.util.MeasureUnit TABLESPOON;
-    field public static final android.icu.util.MeasureUnit TEASPOON;
-    field public static final android.icu.util.MeasureUnit TERABIT;
-    field public static final android.icu.util.MeasureUnit TERABYTE;
-    field public static final android.icu.util.MeasureUnit TON;
-    field public static final android.icu.util.MeasureUnit VOLT;
-    field public static final android.icu.util.MeasureUnit WATT;
-    field public static final android.icu.util.TimeUnit WEEK;
-    field public static final android.icu.util.MeasureUnit YARD;
-    field public static final android.icu.util.TimeUnit YEAR;
-  }
-
-  public class Output<T> {
-    ctor public Output();
-    ctor public Output(T);
-    field public T value;
-  }
-
-  public interface RangeValueIterator {
-    method public boolean next(android.icu.util.RangeValueIterator.Element);
-    method public void reset();
-  }
-
-  public static class RangeValueIterator.Element {
-    ctor public RangeValueIterator.Element();
-    field public int limit;
-    field public int start;
-    field public int value;
-  }
-
-  public class TaiwanCalendar extends android.icu.util.GregorianCalendar {
-    ctor public TaiwanCalendar();
-    ctor public TaiwanCalendar(android.icu.util.TimeZone);
-    ctor public TaiwanCalendar(java.util.Locale);
-    ctor public TaiwanCalendar(android.icu.util.ULocale);
-    ctor public TaiwanCalendar(android.icu.util.TimeZone, java.util.Locale);
-    ctor public TaiwanCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
-    ctor public TaiwanCalendar(java.util.Date);
-    ctor public TaiwanCalendar(int, int, int);
-    ctor public TaiwanCalendar(int, int, int, int, int, int);
-    field public static final int BEFORE_MINGUO = 0; // 0x0
-    field public static final int MINGUO = 1; // 0x1
-  }
-
-  public class TimeUnit extends android.icu.util.MeasureUnit {
-    method public static android.icu.util.TimeUnit[] values();
-  }
-
-  public abstract class TimeZone implements java.lang.Cloneable android.icu.util.Freezable<android.icu.util.TimeZone> java.io.Serializable {
-    ctor public TimeZone();
-    method public Object clone();
-    method public android.icu.util.TimeZone cloneAsThawed();
-    method public static int countEquivalentIDs(String);
-    method public android.icu.util.TimeZone freeze();
-    method public static java.util.Set<java.lang.String> getAvailableIDs(android.icu.util.TimeZone.SystemTimeZoneType, String, Integer);
-    method public static String[] getAvailableIDs(int);
-    method public static String[] getAvailableIDs(String);
-    method public static String[] getAvailableIDs();
-    method public static String getCanonicalID(String);
-    method public static String getCanonicalID(String, boolean[]);
-    method public int getDSTSavings();
-    method public static android.icu.util.TimeZone getDefault();
-    method public final String getDisplayName();
-    method public final String getDisplayName(java.util.Locale);
-    method public final String getDisplayName(android.icu.util.ULocale);
-    method public final String getDisplayName(boolean, int);
-    method public String getDisplayName(boolean, int, java.util.Locale);
-    method public String getDisplayName(boolean, int, android.icu.util.ULocale);
-    method public static String getEquivalentID(String, int);
-    method public static android.icu.util.TimeZone getFrozenTimeZone(String);
-    method public String getID();
-    method public static String getIDForWindowsID(String, String);
-    method public abstract int getOffset(int, int, int, int, int, int);
-    method public int getOffset(long);
-    method public void getOffset(long, boolean, int[]);
-    method public abstract int getRawOffset();
-    method public static String getRegion(String);
-    method public static String getTZDataVersion();
-    method public static android.icu.util.TimeZone getTimeZone(String);
-    method public static android.icu.util.TimeZone getTimeZone(String, int);
-    method public static String getWindowsID(String);
-    method public boolean hasSameRules(android.icu.util.TimeZone);
-    method public abstract boolean inDaylightTime(java.util.Date);
-    method public boolean isFrozen();
-    method public boolean observesDaylightTime();
-    method public void setID(String);
-    method public abstract void setRawOffset(int);
-    method public abstract boolean useDaylightTime();
-    field public static final int GENERIC_LOCATION = 7; // 0x7
-    field public static final android.icu.util.TimeZone GMT_ZONE;
-    field public static final int LONG = 1; // 0x1
-    field public static final int LONG_GENERIC = 3; // 0x3
-    field public static final int LONG_GMT = 5; // 0x5
-    field public static final int SHORT = 0; // 0x0
-    field public static final int SHORT_COMMONLY_USED = 6; // 0x6
-    field public static final int SHORT_GENERIC = 2; // 0x2
-    field public static final int SHORT_GMT = 4; // 0x4
-    field public static final int TIMEZONE_ICU = 0; // 0x0
-    field public static final int TIMEZONE_JDK = 1; // 0x1
-    field public static final android.icu.util.TimeZone UNKNOWN_ZONE;
-    field public static final String UNKNOWN_ZONE_ID = "Etc/Unknown";
-  }
-
-  public enum TimeZone.SystemTimeZoneType {
-    enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType ANY;
-    enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType CANONICAL;
-    enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType CANONICAL_LOCATION;
-  }
-
-  public final class ULocale implements java.lang.Comparable<android.icu.util.ULocale> java.io.Serializable {
-    ctor public ULocale(String);
-    ctor public ULocale(String, String);
-    ctor public ULocale(String, String, String);
-    method public static android.icu.util.ULocale acceptLanguage(String, android.icu.util.ULocale[], boolean[]);
-    method public static android.icu.util.ULocale acceptLanguage(android.icu.util.ULocale[], android.icu.util.ULocale[], boolean[]);
-    method public static android.icu.util.ULocale acceptLanguage(String, boolean[]);
-    method public static android.icu.util.ULocale acceptLanguage(android.icu.util.ULocale[], boolean[]);
-    method public static android.icu.util.ULocale addLikelySubtags(android.icu.util.ULocale);
-    method public static String canonicalize(String);
-    method public Object clone();
-    method public int compareTo(android.icu.util.ULocale);
-    method public static android.icu.util.ULocale createCanonical(String);
-    method public static android.icu.util.ULocale forLanguageTag(String);
-    method public static android.icu.util.ULocale forLocale(java.util.Locale);
-    method public static android.icu.util.ULocale[] getAvailableLocales();
-    method public String getBaseName();
-    method public static String getBaseName(String);
-    method public String getCharacterOrientation();
-    method public String getCountry();
-    method public static String getCountry(String);
-    method public static android.icu.util.ULocale getDefault();
-    method public static android.icu.util.ULocale getDefault(android.icu.util.ULocale.Category);
-    method public String getDisplayCountry();
-    method public String getDisplayCountry(android.icu.util.ULocale);
-    method public static String getDisplayCountry(String, String);
-    method public static String getDisplayCountry(String, android.icu.util.ULocale);
-    method public static String getDisplayKeyword(String);
-    method public static String getDisplayKeyword(String, String);
-    method public static String getDisplayKeyword(String, android.icu.util.ULocale);
-    method public String getDisplayKeywordValue(String);
-    method public String getDisplayKeywordValue(String, android.icu.util.ULocale);
-    method public static String getDisplayKeywordValue(String, String, String);
-    method public static String getDisplayKeywordValue(String, String, android.icu.util.ULocale);
-    method public String getDisplayLanguage();
-    method public String getDisplayLanguage(android.icu.util.ULocale);
-    method public static String getDisplayLanguage(String, String);
-    method public static String getDisplayLanguage(String, android.icu.util.ULocale);
-    method public String getDisplayLanguageWithDialect();
-    method public String getDisplayLanguageWithDialect(android.icu.util.ULocale);
-    method public static String getDisplayLanguageWithDialect(String, String);
-    method public static String getDisplayLanguageWithDialect(String, android.icu.util.ULocale);
-    method public String getDisplayName();
-    method public String getDisplayName(android.icu.util.ULocale);
-    method public static String getDisplayName(String, String);
-    method public static String getDisplayName(String, android.icu.util.ULocale);
-    method public String getDisplayNameWithDialect();
-    method public String getDisplayNameWithDialect(android.icu.util.ULocale);
-    method public static String getDisplayNameWithDialect(String, String);
-    method public static String getDisplayNameWithDialect(String, android.icu.util.ULocale);
-    method public String getDisplayScript();
-    method public String getDisplayScript(android.icu.util.ULocale);
-    method public static String getDisplayScript(String, String);
-    method public static String getDisplayScript(String, android.icu.util.ULocale);
-    method public String getDisplayVariant();
-    method public String getDisplayVariant(android.icu.util.ULocale);
-    method public static String getDisplayVariant(String, String);
-    method public static String getDisplayVariant(String, android.icu.util.ULocale);
-    method public String getExtension(char);
-    method public java.util.Set<java.lang.Character> getExtensionKeys();
-    method public static String getFallback(String);
-    method public android.icu.util.ULocale getFallback();
-    method public String getISO3Country();
-    method public static String getISO3Country(String);
-    method public String getISO3Language();
-    method public static String getISO3Language(String);
-    method public static String[] getISOCountries();
-    method public static String[] getISOLanguages();
-    method public String getKeywordValue(String);
-    method public static String getKeywordValue(String, String);
-    method public java.util.Iterator<java.lang.String> getKeywords();
-    method public static java.util.Iterator<java.lang.String> getKeywords(String);
-    method public String getLanguage();
-    method public static String getLanguage(String);
-    method public String getLineOrientation();
-    method public String getName();
-    method public static String getName(String);
-    method public String getScript();
-    method public static String getScript(String);
-    method public java.util.Set<java.lang.String> getUnicodeLocaleAttributes();
-    method public java.util.Set<java.lang.String> getUnicodeLocaleKeys();
-    method public String getUnicodeLocaleType(String);
-    method public String getVariant();
-    method public static String getVariant(String);
-    method public boolean isRightToLeft();
-    method public static android.icu.util.ULocale minimizeSubtags(android.icu.util.ULocale);
-    method public android.icu.util.ULocale setKeywordValue(String, String);
-    method public static String setKeywordValue(String, String, String);
-    method public String toLanguageTag();
-    method public static String toLegacyKey(String);
-    method public static String toLegacyType(String, String);
-    method public java.util.Locale toLocale();
-    method public static String toUnicodeLocaleKey(String);
-    method public static String toUnicodeLocaleType(String, String);
-    field public static final android.icu.util.ULocale CANADA;
-    field public static final android.icu.util.ULocale CANADA_FRENCH;
-    field public static final android.icu.util.ULocale CHINA;
-    field public static final android.icu.util.ULocale CHINESE;
-    field public static final android.icu.util.ULocale ENGLISH;
-    field public static final android.icu.util.ULocale FRANCE;
-    field public static final android.icu.util.ULocale FRENCH;
-    field public static final android.icu.util.ULocale GERMAN;
-    field public static final android.icu.util.ULocale GERMANY;
-    field public static final android.icu.util.ULocale ITALIAN;
-    field public static final android.icu.util.ULocale ITALY;
-    field public static final android.icu.util.ULocale JAPAN;
-    field public static final android.icu.util.ULocale JAPANESE;
-    field public static final android.icu.util.ULocale KOREA;
-    field public static final android.icu.util.ULocale KOREAN;
-    field public static final android.icu.util.ULocale PRC;
-    field public static final char PRIVATE_USE_EXTENSION = 120; // 0x0078 'x'
-    field public static final android.icu.util.ULocale ROOT;
-    field public static final android.icu.util.ULocale SIMPLIFIED_CHINESE;
-    field public static final android.icu.util.ULocale TAIWAN;
-    field public static final android.icu.util.ULocale TRADITIONAL_CHINESE;
-    field public static final android.icu.util.ULocale UK;
-    field public static final char UNICODE_LOCALE_EXTENSION = 117; // 0x0075 'u'
-    field public static final android.icu.util.ULocale US;
-  }
-
-  public static final class ULocale.Builder {
-    ctor public ULocale.Builder();
-    method public android.icu.util.ULocale.Builder addUnicodeLocaleAttribute(String);
-    method public android.icu.util.ULocale build();
-    method public android.icu.util.ULocale.Builder clear();
-    method public android.icu.util.ULocale.Builder clearExtensions();
-    method public android.icu.util.ULocale.Builder removeUnicodeLocaleAttribute(String);
-    method public android.icu.util.ULocale.Builder setExtension(char, String);
-    method public android.icu.util.ULocale.Builder setLanguage(String);
-    method public android.icu.util.ULocale.Builder setLanguageTag(String);
-    method public android.icu.util.ULocale.Builder setLocale(android.icu.util.ULocale);
-    method public android.icu.util.ULocale.Builder setRegion(String);
-    method public android.icu.util.ULocale.Builder setScript(String);
-    method public android.icu.util.ULocale.Builder setUnicodeLocaleKeyword(String, String);
-    method public android.icu.util.ULocale.Builder setVariant(String);
-  }
-
-  public enum ULocale.Category {
-    enum_constant public static final android.icu.util.ULocale.Category DISPLAY;
-    enum_constant public static final android.icu.util.ULocale.Category FORMAT;
-  }
-
-  public final class UniversalTimeScale {
-    method public static android.icu.math.BigDecimal bigDecimalFrom(double, int);
-    method public static android.icu.math.BigDecimal bigDecimalFrom(long, int);
-    method public static android.icu.math.BigDecimal bigDecimalFrom(android.icu.math.BigDecimal, int);
-    method public static long from(long, int);
-    method public static long getTimeScaleValue(int, int);
-    method public static android.icu.math.BigDecimal toBigDecimal(long, int);
-    method public static android.icu.math.BigDecimal toBigDecimal(android.icu.math.BigDecimal, int);
-    method public static long toLong(long, int);
-    field public static final int DB2_TIME = 8; // 0x8
-    field public static final int DOTNET_DATE_TIME = 4; // 0x4
-    field public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6; // 0x6
-    field public static final int EPOCH_OFFSET_VALUE = 1; // 0x1
-    field public static final int EXCEL_TIME = 7; // 0x7
-    field public static final int FROM_MAX_VALUE = 3; // 0x3
-    field public static final int FROM_MIN_VALUE = 2; // 0x2
-    field public static final int ICU4C_TIME = 2; // 0x2
-    field public static final int JAVA_TIME = 0; // 0x0
-    field public static final int MAC_OLD_TIME = 5; // 0x5
-    field public static final int MAC_TIME = 6; // 0x6
-    field @Deprecated public static final int MAX_SCALE = 10; // 0xa
-    field public static final int TO_MAX_VALUE = 5; // 0x5
-    field public static final int TO_MIN_VALUE = 4; // 0x4
-    field public static final int UNITS_VALUE = 0; // 0x0
-    field public static final int UNIX_MICROSECONDS_TIME = 9; // 0x9
-    field public static final int UNIX_TIME = 1; // 0x1
-    field public static final int WINDOWS_FILE_TIME = 3; // 0x3
-  }
-
-  public interface ValueIterator {
-    method public boolean next(android.icu.util.ValueIterator.Element);
-    method public void reset();
-    method public void setRange(int, int);
-  }
-
-  public static final class ValueIterator.Element {
-    ctor public ValueIterator.Element();
-    field public int integer;
-    field public Object value;
-  }
-
-  public final class VersionInfo implements java.lang.Comparable<android.icu.util.VersionInfo> {
-    method public int compareTo(android.icu.util.VersionInfo);
-    method public static android.icu.util.VersionInfo getInstance(String);
-    method public static android.icu.util.VersionInfo getInstance(int, int, int, int);
-    method public static android.icu.util.VersionInfo getInstance(int, int, int);
-    method public static android.icu.util.VersionInfo getInstance(int, int);
-    method public static android.icu.util.VersionInfo getInstance(int);
-    method public int getMajor();
-    method public int getMicro();
-    method public int getMilli();
-    method public int getMinor();
-    field public static final android.icu.util.VersionInfo ICU_VERSION;
-    field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
-    field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
-    field public static final android.icu.util.VersionInfo UNICODE_10_0;
-    field public static final android.icu.util.VersionInfo UNICODE_11_0;
-    field public static final android.icu.util.VersionInfo UNICODE_12_0;
-    field public static final android.icu.util.VersionInfo UNICODE_12_1;
-    field public static final android.icu.util.VersionInfo UNICODE_13_0;
-    field public static final android.icu.util.VersionInfo UNICODE_1_0;
-    field public static final android.icu.util.VersionInfo UNICODE_1_0_1;
-    field public static final android.icu.util.VersionInfo UNICODE_1_1_0;
-    field public static final android.icu.util.VersionInfo UNICODE_1_1_5;
-    field public static final android.icu.util.VersionInfo UNICODE_2_0;
-    field public static final android.icu.util.VersionInfo UNICODE_2_1_2;
-    field public static final android.icu.util.VersionInfo UNICODE_2_1_5;
-    field public static final android.icu.util.VersionInfo UNICODE_2_1_8;
-    field public static final android.icu.util.VersionInfo UNICODE_2_1_9;
-    field public static final android.icu.util.VersionInfo UNICODE_3_0;
-    field public static final android.icu.util.VersionInfo UNICODE_3_0_1;
-    field public static final android.icu.util.VersionInfo UNICODE_3_1_0;
-    field public static final android.icu.util.VersionInfo UNICODE_3_1_1;
-    field public static final android.icu.util.VersionInfo UNICODE_3_2;
-    field public static final android.icu.util.VersionInfo UNICODE_4_0;
-    field public static final android.icu.util.VersionInfo UNICODE_4_0_1;
-    field public static final android.icu.util.VersionInfo UNICODE_4_1;
-    field public static final android.icu.util.VersionInfo UNICODE_5_0;
-    field public static final android.icu.util.VersionInfo UNICODE_5_1;
-    field public static final android.icu.util.VersionInfo UNICODE_5_2;
-    field public static final android.icu.util.VersionInfo UNICODE_6_0;
-    field public static final android.icu.util.VersionInfo UNICODE_6_1;
-    field public static final android.icu.util.VersionInfo UNICODE_6_2;
-    field public static final android.icu.util.VersionInfo UNICODE_6_3;
-    field public static final android.icu.util.VersionInfo UNICODE_7_0;
-    field public static final android.icu.util.VersionInfo UNICODE_8_0;
-    field public static final android.icu.util.VersionInfo UNICODE_9_0;
-  }
-
-}
-
 package android.inputmethodservice {
 
   public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback {
@@ -23860,6 +19070,20 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
+  public final class GnssMeasurementRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean isFullTracking();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
+  }
+
+  public static final class GnssMeasurementRequest.Builder {
+    ctor public GnssMeasurementRequest.Builder();
+    ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
+    method @NonNull public android.location.GnssMeasurementRequest build();
+    method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
+  }
+
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.location.GnssClock getClock();
@@ -24004,7 +19228,7 @@
     method public float getBearingAccuracyDegrees();
     method public long getElapsedRealtimeNanos();
     method public double getElapsedRealtimeUncertaintyNanos();
-    method @Deprecated public android.os.Bundle getExtras();
+    method public android.os.Bundle getExtras();
     method public double getLatitude();
     method public double getLongitude();
     method public String getProvider();
@@ -24033,7 +19257,7 @@
     method public void setBearingAccuracyDegrees(float);
     method public void setElapsedRealtimeNanos(long);
     method public void setElapsedRealtimeUncertaintyNanos(double);
-    method @Deprecated public void setExtras(android.os.Bundle);
+    method public void setExtras(@Nullable android.os.Bundle);
     method public void setLatitude(double);
     method public void setLongitude(double);
     method public void setProvider(String);
@@ -24086,6 +19310,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
     method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
@@ -24104,10 +19329,10 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
@@ -24125,6 +19350,7 @@
     field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
     field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
     field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
+    field public static final String FUSED_PROVIDER = "fused";
     field public static final String GPS_PROVIDER = "gps";
     field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
     field public static final String KEY_LOCATION_CHANGED = "location";
@@ -24255,6 +19481,7 @@
     method public int getFlags();
     method public int getUsage();
     method public int getVolumeControlStream();
+    method @NonNull public static String usageToString(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALLOW_CAPTURE_BY_ALL = 1; // 0x1
     field public static final int ALLOW_CAPTURE_BY_NONE = 3; // 0x3
@@ -24306,6 +19533,7 @@
 
   public final class AudioDeviceInfo {
     method @NonNull public String getAddress();
+    method @NonNull public java.util.List<android.media.AudioProfile> getAudioProfiles();
     method @NonNull public int[] getChannelCounts();
     method @NonNull public int[] getChannelIndexMasks();
     method @NonNull public int[] getChannelMasks();
@@ -24458,19 +19686,23 @@
   public class AudioManager {
     method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
     method public int abandonAudioFocusRequest(@NonNull android.media.AudioFocusRequest);
+    method public void addOnCommunicationDeviceChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
     method public void adjustStreamVolume(int, int, int);
     method public void adjustSuggestedStreamVolume(int, int, int);
     method public void adjustVolume(int, int);
+    method public void clearDeviceForCommunication();
     method public void dispatchMediaKeyEvent(android.view.KeyEvent);
     method public int generateAudioSessionId();
     method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
     method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
     method public int getAllowedCapturePolicy();
     method public int getAudioHwSyncForSession(int);
+    method @Nullable public android.media.AudioDeviceInfo getDeviceForCommunication();
     method public android.media.AudioDeviceInfo[] getDevices(int);
     method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
     method public int getMode();
     method public String getParameters(String);
+    method public static int getPlaybackOffloadSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
     method public String getProperty(String);
     method public int getRingerMode();
     method @Deprecated public int getRouting(int);
@@ -24501,11 +19733,13 @@
     method @Deprecated public void registerMediaButtonEventReceiver(android.app.PendingIntent);
     method @Deprecated public void registerRemoteControlClient(android.media.RemoteControlClient);
     method @Deprecated public boolean registerRemoteController(android.media.RemoteController);
+    method public void removeOnCommunicationDeviceChangedListener(@NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
     method @Deprecated public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
     method public int requestAudioFocus(@NonNull android.media.AudioFocusRequest);
     method public void setAllowedCapturePolicy(int);
     method @Deprecated public void setBluetoothA2dpOn(boolean);
     method public void setBluetoothScoOn(boolean);
+    method public boolean setDeviceForCommunication(@NonNull android.media.AudioDeviceInfo);
     method public void setMicrophoneMute(boolean);
     method public void setMode(int);
     method public void setParameters(String);
@@ -24589,6 +19823,9 @@
     field public static final int MODE_NORMAL = 0; // 0x0
     field public static final int MODE_RINGTONE = 1; // 0x1
     field @Deprecated public static final int NUM_STREAMS = 5; // 0x5
+    field public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2
+    field public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = 0; // 0x0
+    field public static final int PLAYBACK_OFFLOAD_SUPPORTED = 1; // 0x1
     field public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
     field public static final String PROPERTY_OUTPUT_SAMPLE_RATE = "android.media.property.OUTPUT_SAMPLE_RATE";
     field public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED";
@@ -24640,6 +19877,10 @@
     method public void onAudioFocusChange(int);
   }
 
+  public static interface AudioManager.OnCommunicationDeviceChangedListener {
+    method public void onCommunicationDeviceChanged(@Nullable android.media.AudioDeviceInfo);
+  }
+
   public final class AudioMetadata {
     method @NonNull public static android.media.AudioMetadataMap createMap();
   }
@@ -24691,6 +19932,7 @@
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.AudioAttributes getAudioAttributes();
+    method @Nullable public android.media.AudioDeviceInfo getAudioDevice();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioPlaybackConfiguration> CREATOR;
   }
@@ -24723,6 +19965,13 @@
     method @NonNull public android.media.AudioPresentation.Builder setProgramId(int);
   }
 
+  public class AudioProfile {
+    method @NonNull public int[] getChannelIndexMasks();
+    method @NonNull public int[] getChannelMasks();
+    method public int getFormat();
+    method @NonNull public int[] getSampleRates();
+  }
+
   public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
     ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
@@ -28900,6 +24149,7 @@
     field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
+    field public static final long ACTION_SET_PLAYBACK_SPEED = 4194304L; // 0x400000L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
@@ -34713,6 +29963,7 @@
     field public static final String ID;
     field public static final String MANUFACTURER;
     field public static final String MODEL;
+    field @NonNull public static final String ODM_SKU;
     field public static final String PRODUCT;
     field @Deprecated public static final String RADIO;
     field @Deprecated public static final String SERIAL;
@@ -34863,6 +30114,27 @@
     method public void onCancel();
   }
 
+  public abstract class CombinedVibrationEffect implements android.os.Parcelable {
+    method @NonNull public static android.os.CombinedVibrationEffect createSynced(@NonNull android.os.VibrationEffect);
+    method public int describeContents();
+    method @NonNull public static android.os.CombinedVibrationEffect.SequentialCombination startSequential();
+    method @NonNull public static android.os.CombinedVibrationEffect.SyncedCombination startSynced();
+    field @NonNull public static final android.os.Parcelable.Creator<android.os.CombinedVibrationEffect> CREATOR;
+  }
+
+  public static final class CombinedVibrationEffect.SequentialCombination {
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(int, @NonNull android.os.VibrationEffect, int);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect.SequentialCombination addNext(@NonNull android.os.CombinedVibrationEffect, int);
+    method @NonNull public android.os.CombinedVibrationEffect combine();
+  }
+
+  public static final class CombinedVibrationEffect.SyncedCombination {
+    method @NonNull public android.os.CombinedVibrationEffect.SyncedCombination addVibrator(int, @NonNull android.os.VibrationEffect);
+    method @NonNull public android.os.CombinedVibrationEffect combine();
+  }
+
   public class ConditionVariable {
     ctor public ConditionVariable();
     ctor public ConditionVariable(boolean);
@@ -36089,6 +31361,13 @@
     field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1
   }
 
+  public abstract class VibratorManager {
+    method @NonNull public abstract android.os.Vibrator getDefaultVibrator();
+    method @NonNull public abstract android.os.Vibrator getVibrator(int);
+    method @NonNull public abstract int[] getVibratorIds();
+    method public abstract void vibrate(@NonNull android.os.CombinedVibrationEffect);
+  }
+
   public class WorkSource implements android.os.Parcelable {
     ctor public WorkSource();
     ctor public WorkSource(android.os.WorkSource);
@@ -36305,6 +31584,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();
@@ -38356,8 +33636,8 @@
   }
 
   protected static interface ContactsContract.DataColumns {
-    field public static final String CARRIER_PRESENCE = "carrier_presence";
-    field public static final int CARRIER_PRESENCE_VT_CAPABLE = 1; // 0x1
+    field @Deprecated public static final String CARRIER_PRESENCE = "carrier_presence";
+    field @Deprecated public static final int CARRIER_PRESENCE_VT_CAPABLE = 1; // 0x1
     field public static final String DATA1 = "data1";
     field public static final String DATA10 = "data10";
     field public static final String DATA11 = "data11";
@@ -38715,8 +33995,8 @@
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int ADN_EF_TYPE = 1; // 0x1
     field @NonNull public static final android.os.Parcelable.Creator<android.provider.ContactsContract.SimAccount> CREATOR;
-    field public static final int FDN_EF_TYPE = 3; // 0x3
-    field public static final int SDN_EF_TYPE = 2; // 0x2
+    field public static final int FDN_EF_TYPE = 2; // 0x2
+    field public static final int SDN_EF_TYPE = 3; // 0x3
     field public static final int UNKNOWN_EF_TYPE = 0; // 0x0
   }
 
@@ -45407,9 +40687,10 @@
     field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
     field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
     field public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY = "unloggable_numbers_string_array";
+    field public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
     field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
     field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
-    field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
+    field @Deprecated public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
     field public static final String KEY_USE_RCS_SIP_OPTIONS_BOOL = "use_rcs_sip_options_bool";
     field public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = "use_wfc_home_network_mode_in_roaming_network_bool";
     field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
@@ -45449,12 +40730,79 @@
   }
 
   public static final class CarrierConfigManager.Ims {
+    field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
+    field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
     field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
     field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
     field public static final String KEY_PREFIX = "ims.";
+    field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
   }
 
+  public static final class CarrierConfigManager.Iwlan {
+    field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
+    field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
+    field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
+    field public static final int DH_GROUP_1536_BIT_MODP = 5; // 0x5
+    field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
+    field public static final int DH_GROUP_3072_BIT_MODP = 15; // 0xf
+    field public static final int DH_GROUP_4096_BIT_MODP = 16; // 0x10
+    field public static final int DH_GROUP_NONE = 0; // 0x0
+    field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
+    field public static final int ENCRYPTION_ALGORITHM_AES_CTR = 13; // 0xd
+    field public static final int EPDG_ADDRESS_CELLULAR_LOC = 3; // 0x3
+    field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
+    field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
+    field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
+    field public static final int ID_TYPE_FQDN = 2; // 0x2
+    field public static final int ID_TYPE_KEY_ID = 11; // 0xb
+    field public static final int ID_TYPE_RFC822_ADDR = 3; // 0x3
+    field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
+    field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
+    field public static final String KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL = "iwlan.add_ke_to_child_session_rekey_bool";
+    field public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL = "iwlan.add_wifi_mac_addr_to_nai_bool";
+    field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
+    field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
+    field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
+    field public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_ctr_key_size_int_array";
+    field public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY = "iwlan.diffie_hellman_groups_int_array";
+    field public static final String KEY_DPD_TIMER_SEC_INT = "iwlan.dpd_timer_sec_int";
+    field public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY = "iwlan.epdg_address_priority_int_array";
+    field public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT = "iwlan.epdg_authentication_method_int";
+    field public static final String KEY_EPDG_PCO_ID_IPV4_INT = "iwlan.epdg_pco_id_ipv4_int";
+    field public static final String KEY_EPDG_PCO_ID_IPV6_INT = "iwlan.epdg_pco_id_ipv6_int";
+    field public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING = "iwlan.epdg_static_address_roaming_string";
+    field public static final String KEY_EPDG_STATIC_ADDRESS_STRING = "iwlan.epdg_static_address_string";
+    field public static final String KEY_IKE_LOCAL_ID_TYPE_INT = "iwlan.ike_local_id_type_int";
+    field public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT = "iwlan.ike_rekey_hard_timer_in_sec";
+    field public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT = "iwlan.ike_rekey_soft_timer_sec_int";
+    field public static final String KEY_IKE_REMOTE_ID_TYPE_INT = "iwlan.ike_remote_id_type_int";
+    field public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_cbc_key_size_int_array";
+    field public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_ctr_key_size_int_array";
+    field public static final int KEY_LEN_AES_128 = 128; // 0x80
+    field public static final int KEY_LEN_AES_192 = 192; // 0xc0
+    field public static final int KEY_LEN_AES_256 = 256; // 0x100
+    field public static final int KEY_LEN_UNUSED = 0; // 0x0
+    field public static final String KEY_MAX_RETRIES_INT = "iwlan.max_retries_int";
+    field public static final String KEY_MCC_MNCS_STRING_ARRAY = "iwlan.mcc_mncs_string_array";
+    field public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT = "iwlan.natt_keep_alive_timer_sec_int";
+    field public static final String KEY_PREFIX = "iwlan.";
+    field public static final String KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY = "iwlan.retransmit_timer_sec_int_array";
+    field public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_child_session_encryption_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
+    field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
+    field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
+    field public static final int PSEUDORANDOM_FUNCTION_SHA2_256 = 5; // 0x5
+    field public static final int PSEUDORANDOM_FUNCTION_SHA2_384 = 6; // 0x6
+    field public static final int PSEUDORANDOM_FUNCTION_SHA2_512 = 7; // 0x7
+  }
+
   public abstract class CellIdentity implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public CharSequence getOperatorAlphaLong();
@@ -45659,7 +41007,8 @@
   public final class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable {
     method public int describeContents();
     method public int getAsuLevel();
-    method public int getCqi();
+    method @IntRange(from=0, to=15) public int getCqi();
+    method @IntRange(from=1, to=6) public int getCqiTableIndex();
     method public int getDbm();
     method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
     method public int getRsrp();
@@ -45674,6 +41023,8 @@
   public final class CellSignalStrengthNr extends android.telephony.CellSignalStrength implements android.os.Parcelable {
     method public int describeContents();
     method public int getAsuLevel();
+    method @IntRange(from=0, to=15) @NonNull public java.util.List<java.lang.Integer> getCsiCqiReport();
+    method @IntRange(from=1, to=3) public int getCsiCqiTableIndex();
     method public int getCsiRsrp();
     method public int getCsiRsrq();
     method public int getCsiSinr();
@@ -45841,6 +41192,28 @@
     field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
     field public static final int IRAT_HANDOVER_FAILED = 2194; // 0x892
     field public static final int IS707B_MAX_ACCESS_PROBES = 2089; // 0x829
+    field public static final int IWLAN_AUTHORIZATION_REJECTED = 9003; // 0x232b
+    field public static final int IWLAN_DNS_RESOLUTION_NAME_FAILURE = 16388; // 0x4004
+    field public static final int IWLAN_DNS_RESOLUTION_TIMEOUT = 16389; // 0x4005
+    field public static final int IWLAN_IKEV2_AUTH_FAILURE = 16385; // 0x4001
+    field public static final int IWLAN_IKEV2_CERT_INVALID = 16387; // 0x4003
+    field public static final int IWLAN_IKEV2_CONFIG_FAILURE = 16384; // 0x4000
+    field public static final int IWLAN_IKEV2_MSG_TIMEOUT = 16386; // 0x4002
+    field public static final int IWLAN_ILLEGAL_ME = 9006; // 0x232e
+    field public static final int IWLAN_IMEI_NOT_ACCEPTED = 11005; // 0x2afd
+    field public static final int IWLAN_MAX_CONNECTION_REACHED = 8193; // 0x2001
+    field public static final int IWLAN_NETWORK_FAILURE = 10500; // 0x2904
+    field public static final int IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED = 9000; // 0x2328
+    field public static final int IWLAN_NO_APN_SUBSCRIPTION = 9002; // 0x232a
+    field public static final int IWLAN_PDN_CONNECTION_REJECTION = 8192; // 0x2000
+    field public static final int IWLAN_PLMN_NOT_ALLOWED = 11011; // 0x2b03
+    field public static final int IWLAN_RAT_TYPE_NOT_ALLOWED = 11001; // 0x2af9
+    field public static final int IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS = 8244; // 0x2034
+    field public static final int IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 8241; // 0x2031
+    field public static final int IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS = 8245; // 0x2035
+    field public static final int IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 8242; // 0x2032
+    field public static final int IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED = 11055; // 0x2b2f
+    field public static final int IWLAN_USER_UNKNOWN = 9001; // 0x2329
     field public static final int LIMITED_TO_IPV4 = 2234; // 0x8ba
     field public static final int LIMITED_TO_IPV6 = 2235; // 0x8bb
     field public static final int LLC_SNDCP = 25; // 0x19
@@ -46927,6 +42300,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
     method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
     method public int getCallState();
     method public int getCardIdForDefaultEuicc();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
@@ -46950,6 +42324,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public String getManualNetworkSelectionPlmn();
     method @Nullable public String getManufacturerCode();
     method @Nullable public String getManufacturerCode(int);
+    method public static long getMaximumCallComposerPictureSize();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int);
     method public String getMmsUAProfUrl();
@@ -46999,7 +42374,7 @@
     method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
     method public boolean isConcurrentVoiceAndDataSupported();
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isDataConnectionAllowed();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabled();
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabledForReason(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
     method public boolean isEmergencyNumber(@NonNull String);
@@ -47015,7 +42390,6 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
-    method @Deprecated public void listen(long, @NonNull android.telephony.PhoneStateListener);
     method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
@@ -47023,6 +42397,7 @@
     method @Deprecated public String sendEnvelopeWithStatus(String);
     method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
     method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>);
@@ -47059,9 +42434,12 @@
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
     field public static final int APPTYPE_SIM = 1; // 0x1
+    field public static final int APPTYPE_UNKNOWN = 0; // 0x0
     field public static final int APPTYPE_USIM = 2; // 0x2
     field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
     field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
+    field public static final int CALL_COMPOSER_STATUS_OFF = 0; // 0x0
+    field public static final int CALL_COMPOSER_STATUS_ON = 1; // 0x1
     field public static final int CALL_STATE_IDLE = 0; // 0x0
     field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
     field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -51019,7 +46397,6 @@
     method public int getFlags();
     method @Nullable public android.net.Uri getLinkUri();
     method public int getSource();
-    method @NonNull public android.util.Pair<android.view.ContentInfo,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
     field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
     field public static final int SOURCE_APP = 0; // 0x0
     field public static final int SOURCE_AUTOFILL = 4; // 0x4
@@ -51335,9 +46712,11 @@
     method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges();
     method public String getName();
     method public int getProductId();
+    method @NonNull public android.hardware.SensorManager getSensorManager();
     method public int getSources();
     method public int getVendorId();
     method public android.os.Vibrator getVibrator();
+    method @NonNull public android.os.VibratorManager getVibratorManager();
     method public boolean[] hasKeys(int...);
     method public boolean hasMicrophone();
     method public boolean isEnabled();
@@ -53179,6 +48558,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);
@@ -54189,6 +49569,7 @@
     method public void setFlags(int, int);
     method public void setFormat(int);
     method public void setGravity(int);
+    method @RequiresPermission(android.Manifest.permission.HIDE_OVERLAY_WINDOWS) public final void setHideOverlayWindows(boolean);
     method public void setIcon(@DrawableRes int);
     method public void setLayout(int, int);
     method public void setLocalFocus(boolean, boolean);
@@ -55917,6 +51298,7 @@
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(String, android.os.Bundle);
+    method public default boolean performSpellCheck();
     method public boolean reportFullscreenMode(boolean);
     method public boolean requestCursorUpdates(int);
     method public boolean sendKeyEvent(android.view.KeyEvent);
@@ -56801,6 +52183,7 @@
     method public void setCookieAndSequence(int, int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.textservice.SuggestionsInfo> CREATOR;
+    field public static final int RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS = 16; // 0x10
     field public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 4; // 0x4
     field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
     field public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 8; // 0x8
@@ -62647,6 +58030,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/module-lib-current.txt b/core/api/module-lib-current.txt
index d83c0ad..8e99d3c 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -80,6 +80,8 @@
 
   public class MediaMetadataRetriever implements java.lang.AutoCloseable {
     field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
+    field public static final int METADATA_KEY_XMP_LENGTH = 42; // 0x2a
+    field public static final int METADATA_KEY_XMP_OFFSET = 41; // 0x29
   }
 
 }
@@ -122,6 +124,20 @@
 
 }
 
+package android.net {
+
+  public final class TcpRepairWindow {
+    ctor public TcpRepairWindow(int, int, int, int, int, int);
+    field public final int maxWindow;
+    field public final int rcvWnd;
+    field public final int rcvWndScale;
+    field public final int rcvWup;
+    field public final int sndWl1;
+    field public final int sndWnd;
+  }
+
+}
+
 package android.os {
 
   public class Binder implements android.os.IBinder {
diff --git a/core/api/removed.txt b/core/api/removed.txt
index f2dfb84..990388a 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -213,14 +213,6 @@
 
 }
 
-package android.icu.util {
-
-  public class JapaneseCalendar extends android.icu.util.GregorianCalendar {
-    field @Deprecated public static final int CURRENT_ERA;
-  }
-
-}
-
 package android.location {
 
   public class Location implements android.os.Parcelable {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 7e12e2e..5679c89 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -36,6 +36,7 @@
     field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
     field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
+    field public static final String BIND_GBA_SERVICE = "android.permission.BIND_GBA_SERVICE";
     field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
     field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
     field public static final String BIND_MUSIC_RECOGNITION_SERVICE = "android.permission.BIND_MUSIC_RECOGNITION_SERVICE";
@@ -56,8 +57,10 @@
     field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
     field @Deprecated public static final String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
     field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED";
+    field public static final String CAMERA_OPEN_CLOSE_LISTENER = "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
     field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD";
     field public static final String CAPTURE_MEDIA_OUTPUT = "android.permission.CAPTURE_MEDIA_OUTPUT";
+    field public static final String CAPTURE_TUNER_AUDIO_INPUT = "android.permission.CAPTURE_TUNER_AUDIO_INPUT";
     field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT";
     field public static final String CAPTURE_VOICE_COMMUNICATION_OUTPUT = "android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT";
     field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
@@ -92,7 +95,7 @@
     field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES";
     field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
     field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
-    field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
+    field @Deprecated public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
     field public static final String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
     field public static final String INSTALL_DYNAMIC_SYSTEM = "android.permission.INSTALL_DYNAMIC_SYSTEM";
     field public static final String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
@@ -127,6 +130,7 @@
     field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
     field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
     field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
+    field public static final String MANAGE_SEARCH_UI = "android.permission.MANAGE_SEARCH_UI";
     field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
     field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
     field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
@@ -210,6 +214,7 @@
     field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
     field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
+    field public static final String ROTATE_SURFACE_FLINGER = "android.permission.ROTATE_SURFACE_FLINGER";
     field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
     field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
@@ -1341,6 +1346,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);
@@ -1367,6 +1373,149 @@
     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.search {
+
+  public final class Query implements android.os.Parcelable {
+    ctor public Query(@NonNull String, long, @Nullable android.os.Bundle);
+    method public int describeContents();
+    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public String getInput();
+    method @NonNull public long getTimestamp();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.Query> CREATOR;
+  }
+
+  public final class SearchAction implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public CharSequence getContentDescription();
+    method @Nullable public android.os.Bundle getExtras();
+    method @Nullable public android.graphics.drawable.Icon getIcon();
+    method @NonNull public String getId();
+    method @Nullable public android.content.Intent getIntent();
+    method @Nullable public android.app.PendingIntent getPendingIntent();
+    method @Nullable public CharSequence getSubtitle();
+    method @NonNull public CharSequence getTitle();
+    method @Nullable public android.os.UserHandle getUserHandle();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchAction> CREATOR;
+  }
+
+  public static final class SearchAction.Builder {
+    ctor public SearchAction.Builder(@NonNull String, @NonNull String);
+    method @NonNull public android.app.search.SearchAction build();
+    method @NonNull public android.app.search.SearchAction.Builder setContentDescription(@Nullable CharSequence);
+    method @NonNull public android.app.search.SearchAction.Builder setExtras(@Nullable android.os.Bundle);
+    method @NonNull public android.app.search.SearchAction.Builder setIcon(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.app.search.SearchAction.Builder setIntent(@Nullable android.content.Intent);
+    method @NonNull public android.app.search.SearchAction.Builder setPendingIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.search.SearchAction.Builder setSubtitle(@Nullable CharSequence);
+    method @NonNull public android.app.search.SearchAction.Builder setUserHandle(@Nullable android.os.UserHandle);
+  }
+
+  public final class SearchContext implements android.os.Parcelable {
+    ctor public SearchContext(int, int, @Nullable android.os.Bundle);
+    method public int describeContents();
+    method @Nullable public android.os.Bundle getExtras();
+    method @Nullable public String getPackageName();
+    method @NonNull public int getResultTypes();
+    method @NonNull public int getTimeoutMillis();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchContext> CREATOR;
+  }
+
+  public final class SearchSession implements java.lang.AutoCloseable {
+    method public void close();
+    method public void destroy();
+    method protected void finalize();
+    method public void notifyEvent(@NonNull android.app.search.Query, @NonNull android.app.search.SearchTargetEvent);
+    method @Nullable public void query(@NonNull android.app.search.Query, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.search.SearchTarget>>);
+  }
+
+  public final class SearchSessionId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchSessionId> CREATOR;
+  }
+
+  public final class SearchTarget implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
+    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public String getId();
+    method @NonNull public String getLayoutType();
+    method @NonNull public String getPackageName();
+    method @NonNull public String getParentId();
+    method public int getResultType();
+    method public float getScore();
+    method @Nullable public android.app.search.SearchAction getSearchAction();
+    method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
+    method @Nullable public android.net.Uri getSliceUri();
+    method @NonNull public android.os.UserHandle getUserHandle();
+    method public boolean shouldHide();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchTarget> CREATOR;
+  }
+
+  public static final class SearchTarget.Builder {
+    ctor public SearchTarget.Builder(int, @NonNull String, @NonNull String);
+    method @NonNull public android.app.search.SearchTarget build();
+    method @NonNull public android.app.search.SearchTarget.Builder setAppWidgetProviderInfo(@NonNull android.appwidget.AppWidgetProviderInfo);
+    method @NonNull public android.app.search.SearchTarget.Builder setExtras(@Nullable android.os.Bundle);
+    method @NonNull public android.app.search.SearchTarget.Builder setPackageName(@NonNull String);
+    method @NonNull public android.app.search.SearchTarget.Builder setParentId(@NonNull String);
+    method @NonNull public android.app.search.SearchTarget.Builder setScore(float);
+    method @NonNull public android.app.search.SearchTarget.Builder setSearchAction(@Nullable android.app.search.SearchAction);
+    method @NonNull public android.app.search.SearchTarget.Builder setShortcutInfo(@NonNull android.content.pm.ShortcutInfo);
+    method @NonNull public android.app.search.SearchTarget.Builder setShouldHide(boolean);
+    method @NonNull public android.app.search.SearchTarget.Builder setSliceUri(@NonNull android.net.Uri);
+    method @NonNull public android.app.search.SearchTarget.Builder setUserHandle(@NonNull android.os.UserHandle);
+  }
+
+  public final class SearchTargetEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAction();
+    method public int getFlags();
+    method @Nullable public String getLaunchLocation();
+    method @NonNull public String getTargetId();
+    method @NonNull public java.util.List<java.lang.String> getTargetIds();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int ACTION_DRAGNDROP = 7; // 0x7
+    field public static final int ACTION_LAUNCH_KEYBOARD_FOCUS = 6; // 0x6
+    field public static final int ACTION_LAUNCH_TOUCH = 5; // 0x5
+    field public static final int ACTION_LONGPRESS = 4; // 0x4
+    field public static final int ACTION_SURFACE_INVISIBLE = 8; // 0x8
+    field public static final int ACTION_SURFACE_VISIBLE = 1; // 0x1
+    field public static final int ACTION_TAP = 3; // 0x3
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchTargetEvent> CREATOR;
+    field public static final int FLAG_IME_SHOWN = 1; // 0x1
+  }
+
+  public static final class SearchTargetEvent.Builder {
+    ctor public SearchTargetEvent.Builder(@NonNull String, int);
+    ctor public SearchTargetEvent.Builder(@NonNull java.util.List<java.lang.String>, int);
+    method @NonNull public android.app.search.SearchTargetEvent build();
+    method @NonNull public android.app.search.SearchTargetEvent.Builder setFlags(int);
+    method @NonNull public android.app.search.SearchTargetEvent.Builder setLaunchLocation(@Nullable String);
+  }
+
+  public final class SearchUiManager {
+    method @NonNull public android.app.search.SearchSession createSearchSession(@NonNull android.app.search.SearchContext);
+  }
+
 }
 
 package android.app.time {
@@ -1671,6 +1820,7 @@
     field @NonNull public static final android.os.ParcelUuid HOGP;
     field @NonNull public static final android.os.ParcelUuid HSP;
     field @NonNull public static final android.os.ParcelUuid HSP_AG;
+    field @NonNull public static final android.os.ParcelUuid LE_AUDIO;
     field @NonNull public static final android.os.ParcelUuid MAP;
     field @NonNull public static final android.os.ParcelUuid MAS;
     field @NonNull public static final android.os.ParcelUuid MNS;
@@ -1783,12 +1933,14 @@
     field public static final String EUICC_CARD_SERVICE = "euicc_card";
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
+    field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
     field public static final String NETD_SERVICE = "netd";
     field public static final String NETWORK_SCORE_SERVICE = "network_score";
     field public static final String OEM_LOCK_SERVICE = "oem_lock";
     field public static final String PERMISSION_SERVICE = "permission";
     field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
     field public static final String ROLLBACK_SERVICE = "rollback";
+    field public static final String SEARCH_UI_SERVICE = "search_ui";
     field public static final String SECURE_ELEMENT_SERVICE = "secure_element";
     field public static final String STATS_MANAGER = "stats";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
@@ -1970,6 +2122,9 @@
   public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     method public boolean isEncryptionAware();
     method public boolean isInstantApp();
+    method public boolean isOem();
+    method public boolean isProduct();
+    method public boolean isVendor();
     field public String credentialProtectedDataDir;
     field public int targetSandboxVersion;
   }
@@ -2294,6 +2449,7 @@
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000
     field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
+    field public static final int PROTECTION_FLAG_ROLE = 67108864; // 0x4000000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
     field @Nullable public final String backgroundPermission;
@@ -2457,6 +2613,11 @@
     field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000
   }
 
+  public abstract static class CameraManager.AvailabilityCallback {
+    method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String);
+  }
+
 }
 
 package android.hardware.camera2.params {
@@ -4155,7 +4316,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
-    method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.LOCATION_HARDWARE}) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -4164,7 +4325,6 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
     method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
     method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
-    field public static final String FUSED_PROVIDER = "fused";
   }
 
   public final class LocationRequest implements android.os.Parcelable {
@@ -4370,6 +4530,7 @@
     field public static final int PLAYER_STATE_STARTED = 2; // 0x2
     field public static final int PLAYER_STATE_STOPPED = 4; // 0x4
     field public static final int PLAYER_STATE_UNKNOWN = -1; // 0xffffffff
+    field public static final int PLAYER_TYPE_AAUDIO = 13; // 0xd
     field public static final int PLAYER_TYPE_JAM_AUDIOTRACK = 1; // 0x1
     field public static final int PLAYER_TYPE_JAM_MEDIAPLAYER = 2; // 0x2
     field public static final int PLAYER_TYPE_JAM_SOUNDPOOL = 3; // 0x3
@@ -5911,8 +6072,8 @@
 
   public class DvbsFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder builder();
+    method public boolean canHandleDiseqcRxMessage();
     method @Nullable public android.media.tv.tuner.frontend.DvbsCodeRate getCodeRate();
-    method public boolean getCouldHandleDiseqcRxMessage();
     method public int getInputStreamId();
     method public int getModulation();
     method public int getPilot();
@@ -5964,8 +6125,8 @@
 
   public static class DvbsFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCanHandleDiseqcRxMessage(boolean);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
-    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCouldHandleDiseqcRxMessage(boolean);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -6946,6 +7107,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();
@@ -7882,12 +8056,14 @@
 
   public class RecoverySystem {
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static boolean isPreparedForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
+    method @Deprecated @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException;
     method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
     method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
@@ -8379,6 +8555,18 @@
 
 package android.provider {
 
+  public class CallLog {
+    method @RequiresPermission(android.Manifest.permission.WRITE_CALL_LOG) public static void storeCallComposerPictureAsUser(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull java.io.InputStream, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.net.Uri,android.provider.CallLog.CallComposerLoggingException>);
+  }
+
+  public static class CallLog.CallComposerLoggingException extends java.lang.Throwable {
+    method public int getErrorCode();
+    field public static final int ERROR_INPUT_CLOSED = 3; // 0x3
+    field public static final int ERROR_REMOTE_END_CLOSED = 1; // 0x1
+    field public static final int ERROR_STORAGE_FULL = 2; // 0x2
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+  }
+
   @Deprecated public static final class ContactsContract.MetadataSync implements android.provider.BaseColumns android.provider.ContactsContract.MetadataSyncColumns {
     field @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
     field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
@@ -8445,6 +8633,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";
@@ -9541,6 +9730,19 @@
 
 }
 
+package android.service.search {
+
+  public abstract class SearchUiService extends android.app.Service {
+    ctor public SearchUiService();
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public void onCreateSearchSession(@NonNull android.app.search.SearchContext, @NonNull android.app.search.SearchSessionId);
+    method @MainThread public abstract void onDestroy(@NonNull android.app.search.SearchSessionId);
+    method @MainThread public abstract void onNotifyEvent(@NonNull android.app.search.SearchSessionId, @NonNull android.app.search.Query, @NonNull android.app.search.SearchTargetEvent);
+    method @MainThread public abstract void onQuery(@NonNull android.app.search.SearchSessionId, @NonNull android.app.search.Query, @NonNull java.util.function.Consumer<java.util.List<android.app.search.SearchTarget>>);
+  }
+
+}
+
 package android.service.settings.suggestions {
 
   public final class Suggestion implements android.os.Parcelable {
@@ -9582,6 +9784,7 @@
     ctor public ExternalStorageService();
     method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onEndSession(@NonNull String) throws java.io.IOException;
+    method public void onFreeCacheRequested(@NonNull java.util.UUID, long);
     method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
     method public abstract void onVolumeStateChanged(@NonNull android.os.storage.StorageVolume) throws java.io.IOException;
     field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2
@@ -9619,6 +9822,38 @@
 
 }
 
+package android.service.timezone {
+
+  public abstract class TimeZoneProviderService extends android.app.Service {
+    ctor public TimeZoneProviderService();
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onStartUpdates(long);
+    method public abstract void onStopUpdates();
+    method public final void reportPermanentFailure(@NonNull Throwable);
+    method public final void reportSuggestion(@NonNull android.service.timezone.TimeZoneProviderSuggestion);
+    method public final void reportUncertain();
+    field public static final String BIND_PERMISSION = "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
+    field public static final String PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.PrimaryLocationTimeZoneProviderService";
+    field public static final String SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.SecondaryLocationTimeZoneProviderService";
+  }
+
+  public final class TimeZoneProviderSuggestion implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getElapsedRealtimeMillis();
+    method @NonNull public java.util.List<java.lang.String> getTimeZoneIds();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.timezone.TimeZoneProviderSuggestion> CREATOR;
+  }
+
+  public static final class TimeZoneProviderSuggestion.Builder {
+    ctor public TimeZoneProviderSuggestion.Builder();
+    method @NonNull public android.service.timezone.TimeZoneProviderSuggestion build();
+    method @NonNull public android.service.timezone.TimeZoneProviderSuggestion.Builder setElapsedRealtimeMillis(long);
+    method @NonNull public android.service.timezone.TimeZoneProviderSuggestion.Builder setTimeZoneIds(@NonNull java.util.List<java.lang.String>);
+  }
+
+}
+
 package android.service.trust {
 
   public class TrustAgentService extends android.app.Service {
@@ -10811,6 +11046,7 @@
     method public boolean disableCellBroadcastRange(int, int, int);
     method public boolean enableCellBroadcastRange(int, int, int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS) public void resetAllCellBroadcastRanges();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
     field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
@@ -10891,6 +11127,7 @@
   }
 
   public class TelephonyManager {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
     method public int checkCarrierPrivilegesForPackage(String);
@@ -11010,8 +11247,10 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
     method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -11061,6 +11300,12 @@
     field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+    field public static final int GBA_FAILURE_REASON_FEATURE_NOT_READY = 2; // 0x2
+    field public static final int GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED = 1; // 0x1
+    field public static final int GBA_FAILURE_REASON_INCORRECT_NAF_ID = 4; // 0x4
+    field public static final int GBA_FAILURE_REASON_NETWORK_FAILURE = 3; // 0x3
+    field public static final int GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED = 5; // 0x5
+    field public static final int GBA_FAILURE_REASON_UNKNOWN = 0; // 0x0
     field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
     field public static final int KEY_TYPE_EPDG = 1; // 0x1
     field public static final int KEY_TYPE_WLAN = 2; // 0x2
@@ -11095,6 +11340,11 @@
     field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2
     field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1
     field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0
+    field public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1; // 0x1
+    field public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2; // 0x2
+    field public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4; // 0x4
+    field public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3; // 0x3
+    field public static final int SET_SIM_POWER_STATE_SUCCESS = 0; // 0x0
     field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
     field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
     field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
@@ -11114,6 +11364,12 @@
     field public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4; // 0x4
   }
 
+  public static class TelephonyManager.BootstrapAuthenticationCallback {
+    ctor public TelephonyManager.BootstrapAuthenticationCallback();
+    method public void onAuthenticationFailure(int);
+    method public void onKeysAvailable(@NonNull byte[], @NonNull String);
+  }
+
   public static interface TelephonyManager.CallForwardingInfoCallback {
     method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo);
     method public void onError(int);
@@ -11252,7 +11508,6 @@
     method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setSlotIndex(int);
     method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setThrottleExpiryTimeMillis(long);
     method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setTransportType(int);
-    field public static final long NO_THROTTLE_EXPIRY_TIME = -1L; // 0xffffffffffffffffL
   }
 
   public final class DataCallResponse implements android.os.Parcelable {
@@ -11556,6 +11811,141 @@
 
 }
 
+package android.telephony.gba {
+
+  public class GbaService extends android.app.Service {
+    ctor public GbaService();
+    method public void onAuthenticationRequest(int, int, int, @NonNull android.net.Uri, @NonNull byte[], boolean);
+    method public final void reportAuthenticationFailure(int, int) throws java.lang.RuntimeException;
+    method public final void reportKeysAvailable(int, @NonNull byte[], @NonNull String) throws java.lang.RuntimeException;
+    field public static final String SERVICE_INTERFACE = "android.telephony.gba.GbaService";
+  }
+
+  public class TlsParams {
+    method public static boolean isTlsCipherSuiteSupported(int);
+    field public static final int GROUP_SECP256R1 = 23; // 0x17
+    field public static final int GROUP_SECP384R1 = 24; // 0x18
+    field public static final int GROUP_X25519 = 29; // 0x1d
+    field public static final int GROUP_X448 = 30; // 0x1e
+    field public static final int PROTOCOL_VERSION_TLS_1_2 = 771; // 0x303
+    field public static final int PROTOCOL_VERSION_TLS_1_3 = 772; // 0x304
+    field public static final int SIG_ECDSA_BRAINPOOLP256R1TLS13_SHA256 = 2074; // 0x81a
+    field public static final int SIG_ECDSA_BRAINPOOLP384R1TLS13_SHA384 = 2075; // 0x81b
+    field public static final int SIG_ECDSA_BRAINPOOLP512R1TLS13_SHA512 = 2076; // 0x81c
+    field public static final int SIG_ECDSA_SECP256R1_SHA256 = 1027; // 0x403
+    field public static final int SIG_ECDSA_SECP384R1_SHA384 = 1283; // 0x503
+    field public static final int SIG_ECDSA_SECP521R1_SHA512 = 1539; // 0x603
+    field public static final int SIG_ECDSA_SHA1 = 515; // 0x203
+    field public static final int SIG_RSA_PKCS1_SHA1 = 513; // 0x201
+    field public static final int SIG_RSA_PKCS1_SHA256 = 1025; // 0x401
+    field public static final int SIG_RSA_PKCS1_SHA256_LEGACY = 1056; // 0x420
+    field public static final int SIG_RSA_PKCS1_SHA384 = 1281; // 0x501
+    field public static final int SIG_RSA_PKCS1_SHA384_LEGACY = 1312; // 0x520
+    field public static final int SIG_RSA_PKCS1_SHA512 = 1537; // 0x601
+    field public static final int SIG_RSA_PKCS1_SHA512_LEGACY = 1568; // 0x620
+    field public static final int SIG_RSA_PSS_RSAE_SHA256 = 2052; // 0x804
+    field public static final int SIG_RSA_PSS_RSAE_SHA384 = 2053; // 0x805
+    field public static final int SIG_RSA_PSS_RSAE_SHA512 = 2054; // 0x806
+    field public static final int TLS_AES_128_CCM_SHA256 = 4868; // 0x1304
+    field public static final int TLS_AES_128_GCM_SHA256 = 4865; // 0x1301
+    field public static final int TLS_AES_256_GCM_SHA384 = 4866; // 0x1302
+    field public static final int TLS_CHACHA20_POLY1305_SHA256 = 4867; // 0x1303
+    field public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // 0x13
+    field public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // 0x32
+    field public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 64; // 0x40
+    field public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // 0x38
+    field public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 106; // 0x6a
+    field public static final int TLS_DHE_PSK_WITH_AES_128_CCM = 49318; // 0xc0a6
+    field public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 170; // 0xaa
+    field public static final int TLS_DHE_PSK_WITH_AES_256_CCM = 49319; // 0xc0a7
+    field public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 171; // 0xab
+    field public static final int TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52397; // 0xccad
+    field public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // 0x16
+    field public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // 0x33
+    field public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 103; // 0x67
+    field public static final int TLS_DHE_RSA_WITH_AES_128_CCM = 49310; // 0xc09e
+    field public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 158; // 0x9e
+    field public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // 0x39
+    field public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 107; // 0x6b
+    field public static final int TLS_DHE_RSA_WITH_AES_256_CCM = 49311; // 0xc09f
+    field public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 159; // 0x9f
+    field public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52394; // 0xccaa
+    field public static final int TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA = 27; // 0x1b
+    field public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA = 52; // 0x34
+    field public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 108; // 0x6c
+    field public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA = 58; // 0x3a
+    field public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 109; // 0x6d
+    field public static final int TLS_DH_ANON_WITH_RC4_128_MD5 = 24; // 0x18
+    field public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // 0xd
+    field public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // 0x30
+    field public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 62; // 0x3e
+    field public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // 0x36
+    field public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 104; // 0x68
+    field public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // 0x10
+    field public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // 0x31
+    field public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 63; // 0x3f
+    field public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // 0x37
+    field public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 105; // 0x69
+    field public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 49195; // 0xc02b
+    field public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 49196; // 0xc02c
+    field public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393; // 0xcca9
+    field public static final int TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = 53253; // 0xd005
+    field public static final int TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 53249; // 0xd001
+    field public static final int TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = 53250; // 0xd002
+    field public static final int TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52396; // 0xccac
+    field public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 49199; // 0xc02f
+    field public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 49200; // 0xc030
+    field public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392; // 0xcca8
+    field public static final int TLS_NULL_WITH_NULL_NULL = 0; // 0x0
+    field public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 10; // 0xa
+    field public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 47; // 0x2f
+    field public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 60; // 0x3c
+    field public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 53; // 0x35
+    field public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 61; // 0x3d
+    field public static final int TLS_RSA_WITH_NULL_MD5 = 1; // 0x1
+    field public static final int TLS_RSA_WITH_NULL_SHA = 2; // 0x2
+    field public static final int TLS_RSA_WITH_NULL_SHA256 = 59; // 0x3b
+    field public static final int TLS_RSA_WITH_RC4_128_MD5 = 4; // 0x4
+    field public static final int TLS_RSA_WITH_RC4_128_SHA = 5; // 0x5
+  }
+
+  public final class UaSecurityProtocolIdentifier implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getOrg();
+    method public int getProtocol();
+    method public int getTlsCipherSuite();
+    method @NonNull public byte[] toByteArray();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.gba.UaSecurityProtocolIdentifier> CREATOR;
+    field public static final int ORG_3GPP = 1; // 0x1
+    field public static final int ORG_3GPP2 = 2; // 0x2
+    field public static final int ORG_GSMA = 4; // 0x4
+    field public static final int ORG_LOCAL = 255; // 0xff
+    field public static final int ORG_NONE = 0; // 0x0
+    field public static final int ORG_OMA = 3; // 0x3
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI = 256; // 0x100
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER = 5; // 0x5
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS = 3; // 0x3
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION = 2; // 0x2
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE = 6; // 0x6
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_MBMS = 1; // 0x1
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS = 4; // 0x4
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE = 0; // 0x0
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER = 131072; // 0x20000
+    field public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT = 65536; // 0x10000
+  }
+
+  public static final class UaSecurityProtocolIdentifier.Builder {
+    ctor public UaSecurityProtocolIdentifier.Builder();
+    ctor public UaSecurityProtocolIdentifier.Builder(@NonNull android.telephony.gba.UaSecurityProtocolIdentifier);
+    method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier build();
+    method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setOrg(int);
+    method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setProtocol(int);
+    method @NonNull public android.telephony.gba.UaSecurityProtocolIdentifier.Builder setTlsCipherSuite(int);
+  }
+
+}
+
 package android.telephony.ims {
 
   public final class AudioCodecAttributes implements android.os.Parcelable {
@@ -12108,18 +12498,29 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerRcsProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void triggerRcsReconfiguration();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterRcsProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
+    field public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
+    field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID";
     field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
     field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
     field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
     field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
     field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+    field public static final int STATUS_CAPABLE = 0; // 0x0
+    field public static final int STATUS_CARRIER_NOT_CAPABLE = 2; // 0x2
+    field public static final int STATUS_DEVICE_NOT_CAPABLE = 1; // 0x1
     field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
     field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
   }
@@ -12130,6 +12531,27 @@
     method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
+  public static class ProvisioningManager.RcsProvisioningCallback {
+    ctor public ProvisioningManager.RcsProvisioningCallback();
+    method public void onAutoConfigurationErrorReceived(int, @NonNull String);
+    method public void onConfigurationChanged(@NonNull byte[]);
+    method public void onConfigurationReset();
+    method public void onRemoved();
+  }
+
+  public final class RcsClientConfiguration implements android.os.Parcelable {
+    ctor public RcsClientConfiguration(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
+    method public int describeContents();
+    method @NonNull public String getClientVendor();
+    method @NonNull public String getClientVersion();
+    method @NonNull public String getRcsProfile();
+    method @NonNull public String getRcsVersion();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR;
+    field public static final String RCS_PROFILE_1_0 = "UP_1.0";
+    field public static final String RCS_PROFILE_2_3 = "UP_2.3";
+  }
+
   public class RcsUceAdapter {
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
   }
@@ -12153,6 +12575,7 @@
   }
 
   public interface SipDelegateConnection {
+    method public void closeDialog(@NonNull String);
     method public void notifyMessageReceiveError(@NonNull String, int);
     method public void notifyMessageReceived(@NonNull String);
     method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long);
@@ -12221,6 +12644,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+    method public void triggerFullNetworkRegistration(@NonNull android.telephony.ims.SipDelegateConnection, @IntRange(from=100, to=699) int, @Nullable String);
     field public static final int DENIED_REASON_INVALID = 4; // 0x4
     field public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; // 0x1
     field public static final int DENIED_REASON_NOT_ALLOWED = 2; // 0x2
@@ -12416,11 +12840,15 @@
     ctor public ImsConfigImplBase();
     method public int getConfigInt(int);
     method public String getConfigString(int);
+    method public final void notifyAutoConfigurationErrorReceived(int, @NonNull String);
     method public final void notifyProvisionedValueChanged(int, int);
     method public final void notifyProvisionedValueChanged(int, String);
     method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
+    method public void notifyRcsAutoConfigurationRemoved();
     method public int setConfig(int, int);
     method public int setConfig(int, String);
+    method public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration);
+    method public void triggerAutoConfiguration();
     field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
     field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
     field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
@@ -12465,6 +12893,9 @@
     method public final void onRegistering(int);
     method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
     method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+    method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String);
+    method public void triggerSipDelegateDeregistration();
+    method public void updateSipDelegateRegistration();
     field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
     field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
     field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index a3fb06c..8b3cee4 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -19,6 +19,10 @@
     
 
 
+IntentBuilderName: android.app.search.SearchAction#getIntent():
+    
+
+
 KotlinKeyword: android.app.Notification#when:
     
 
@@ -248,3 +252,9 @@
     
 SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
     
+
+
+UserHandleName: android.app.search.SearchAction.Builder#setUserHandle(android.os.UserHandle):
+    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle`
+UserHandleName: android.app.search.SearchTarget.Builder#setUserHandle(android.os.UserHandle):
+    
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ffb31c9..5b86e8d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -94,6 +94,8 @@
     method public static void resumeAppSwitches() throws android.os.RemoteException;
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
+    field public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L; // 0xa6929b8L
+    field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
     field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
     field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
@@ -139,7 +141,6 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean moveTopActivityToPinnedRootTask(int, @NonNull android.graphics.Rect);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void removeRootTasksInWindowingModes(@NonNull int[]);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void removeRootTasksWithActivityTypes(@NonNull int[]);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void requestPictureInPictureMode(@NonNull android.os.IBinder);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void resizePrimarySplitScreen(@NonNull android.graphics.Rect, @NonNull android.graphics.Rect);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void resizeTask(int, android.graphics.Rect);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
@@ -216,6 +217,7 @@
     field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
     field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
     field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
+    field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
     field public static final int OP_START_FOREGROUND = 76; // 0x4c
@@ -282,6 +284,7 @@
     method public java.util.List<android.app.RemoteAction> getActions();
     method public float getAspectRatio();
     method public android.graphics.Rect getSourceRectHint();
+    method public boolean isSeamlessResizeEnabled();
   }
 
   public class StatusBarManager {
@@ -378,10 +381,14 @@
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
     field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5
     field public static final int OPERATION_LOCK_NOW = 1; // 0x1
+    field public static final int OPERATION_LOGOUT_USER = 9; // 0x9
+    field public static final int OPERATION_REBOOT = 7; // 0x7
     field public static final int OPERATION_REMOVE_USER = 6; // 0x6
+    field public static final int OPERATION_SET_USER_RESTRICTION = 10; // 0xa
     field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3
     field public static final int OPERATION_STOP_USER = 4; // 0x4
     field public static final int OPERATION_SWITCH_USER = 2; // 0x2
+    field public static final int OPERATION_WIPE_DATA = 8; // 0x8
   }
 
   public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
@@ -740,6 +747,11 @@
     method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
   }
 
+  public abstract static class CameraManager.AvailabilityCallback {
+    method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String);
+  }
+
 }
 
 package android.hardware.display {
@@ -953,7 +965,6 @@
     method @NonNull public String[] getBackgroundThrottlingWhitelist();
     method @NonNull public String[] getIgnoreSettingsWhitelist();
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
-    field public static final String FUSED_PROVIDER = "fused";
   }
 
 }
@@ -977,6 +988,7 @@
   }
 
   public class AudioManager {
+    method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int);
     method public boolean hasRegisteredDynamicPolicy();
   }
 
@@ -1001,6 +1013,8 @@
     field public static final int DEVICE_ROLE_DISABLED = 2; // 0x2
     field public static final int DEVICE_ROLE_NONE = 0; // 0x0
     field public static final int DEVICE_ROLE_PREFERRED = 1; // 0x1
+    field public static final int OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2
+    field public static final int OFFLOAD_SUPPORTED = 1; // 0x1
     field public static final int STREAM_DEFAULT = -1; // 0xffffffff
   }
 
@@ -2006,6 +2020,10 @@
     field public static final int CALLBACK_ANIMATION = 1; // 0x1
   }
 
+  public final class ContentInfo {
+    method @NonNull public android.util.Pair<android.view.ContentInfo,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
+  }
+
   public final class Display {
     method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
     method public int getType();
@@ -2429,7 +2447,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);
@@ -2444,6 +2461,13 @@
     field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
   }
 
+  public final class StartingWindowInfo implements android.os.Parcelable {
+    ctor public StartingWindowInfo();
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.window.StartingWindowInfo> CREATOR;
+  }
+
   public final class TaskAppearedInfo implements android.os.Parcelable {
     ctor public TaskAppearedInfo(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl);
     method public int describeContents();
@@ -2455,7 +2479,7 @@
 
   public class TaskOrganizer extends android.window.WindowOrganizer {
     ctor public TaskOrganizer();
-    method @BinderThread public void addStartingWindow(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.os.IBinder);
+    method @BinderThread public void addStartingWindow(@NonNull android.window.StartingWindowInfo, @NonNull android.os.IBinder);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void createRootTask(int, int, @Nullable android.os.IBinder);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
@@ -2466,7 +2490,7 @@
     method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
     method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
     method @CallSuper @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.window.TaskAppearedInfo> registerOrganizer();
-    method @BinderThread public void removeStartingWindow(@NonNull android.app.ActivityManager.RunningTaskInfo);
+    method @BinderThread public void removeStartingWindow(int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
     method @CallSuper @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void unregisterOrganizer();
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 6470a04..7b57442f 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -93,7 +93,8 @@
  * {@link AccountAuthenticatorResponse#onError} when it is complete.
  * <li> If the authenticator cannot synchronously process the request and return a result then it
  * may choose to return null and then use the AccountManagerResponse to send the result
- * when it has completed the request.
+ * when it has completed the request. This asynchronous option is not available for the
+ * {@link #addAccount} method, which must complete synchronously.
  * </ul>
  * <p>
  * The following descriptions of each of the abstract authenticator methods will not describe the
@@ -101,7 +102,7 @@
  * parameters and the expected result.
  * <p>
  * When writing an activity to satisfy these requests one must pass in the AccountManagerResponse
- * and return the result via that response when the activity finishes (or whenever else  the
+ * and return the result via that response when the activity finishes (or whenever else the
  * activity author deems it is the correct time to respond).
  */
 public abstract class AbstractAccountAuthenticator {
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 4af22bf..bc7f4d6 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -16,16 +16,12 @@
 package android.accounts;
 
 import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.os.Process;
 import android.os.UserHandle;
 import android.util.Log;
@@ -37,6 +33,7 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 import java.util.HashMap;
@@ -60,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);
@@ -71,15 +71,8 @@
             return;
         }
 
-        try {
-            IBinder activityToken = getActivityToken();
-            mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken);
-            mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage(
-                    activityToken);
-        } catch (RemoteException re) {
-            // Couldn't figure out caller details
-            Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
-        }
+        mCallingUid = getLaunchedFromUid();
+        mCallingPackage = getLaunchedFromPackage();
 
         if (UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) &&
             getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME) != null) {
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 4b4ef00..2be88ab 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -15,16 +15,10 @@
  */
 package android.accounts;
 
-import android.app.ActivityTaskManager;
-import com.google.android.collect.Sets;
-
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.Intent;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
@@ -39,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;
@@ -143,23 +139,17 @@
             Log.v(TAG, "ChooseTypeAndAccountActivity.onCreate(savedInstanceState="
                     + savedInstanceState + ")");
         }
+        getWindow().addSystemFlags(
+                android.view.WindowManager.LayoutParams
+                        .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
-        String message = null;
-
-        try {
-            IBinder activityToken = getActivityToken();
-            mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken);
-            mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage(
-                    activityToken);
-            if (mCallingUid != 0 && mCallingPackage != null) {
-                Bundle restrictions = UserManager.get(this)
-                        .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid)));
-                mDisallowAddAccounts =
-                        restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false);
-            }
-        } catch (RemoteException re) {
-            // Couldn't figure out caller details
-            Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
+        mCallingUid = getLaunchedFromUid();
+        mCallingPackage = getLaunchedFromPackage();
+        if (mCallingUid != 0 && mCallingPackage != null) {
+            Bundle restrictions = UserManager.get(this)
+                    .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid)));
+            mDisallowAddAccounts =
+                    restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false);
         }
 
         // save some items we use frequently
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index 5dc6e60..74dae0e 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -16,18 +16,14 @@
 package android.accounts;
 
 import android.app.Activity;
-import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.text.TextUtils;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -85,13 +81,7 @@
             return;
         }
 
-        try {
-            IBinder activityToken = getActivityToken();
-            mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken);
-        } catch (RemoteException re) {
-            // Couldn't figure out caller details
-            Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
-        }
+        mCallingUid = getLaunchedFromUid();
 
         if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) {
             setResult(Activity.RESULT_CANCELED);
diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS
new file mode 100644
index 0000000..822a35c
--- /dev/null
+++ b/core/java/android/animation/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 47085
+
+romainguy@google.com
+tianliu@google.com
+alanv@google.com
+adamp@google.com
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f92768a..294a363 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6230,6 +6230,23 @@
     }
 
     /**
+     * Returns the uid who started this activity.
+     * @hide
+     */
+    public int getLaunchedFromUid() {
+        return ActivityClient.getInstance().getLaunchedFromUid(getActivityToken());
+    }
+
+    /**
+     * Returns the package who started this activity.
+     * @hide
+     */
+    @Nullable
+    public String getLaunchedFromPackage() {
+        return ActivityClient.getInstance().getLaunchedFromPackage(getActivityToken());
+    }
+
+    /**
      * Control whether this activity's main window is visible.  This is intended
      * only for the special case of an activity that is not going to show a
      * UI itself, but can't just finish prior to onResume() because it needs
@@ -7081,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/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 84ecd24..64d795c 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -221,6 +221,22 @@
         }
     }
 
+    public int getLaunchedFromUid(IBinder token) {
+        try {
+            return getActivityClientController().getLaunchedFromUid(token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    public String getLaunchedFromPackage(IBinder token) {
+        try {
+            return getActivityClientController().getLaunchedFromPackage(token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     Bundle getActivityOptions(IBinder token) {
         try {
             return getActivityClientController().getActivityOptions(token);
@@ -451,8 +467,20 @@
         return sInstance.get();
     }
 
+    /**
+     * If system server has passed the controller interface, store it so the subsequent access can
+     * speed up.
+     */
+    public static IActivityClientController setActivityClientController(
+            IActivityClientController activityClientController) {
+        // No lock because it is no harm to encounter race condition. The thread safe Singleton#get
+        // will take over that case.
+        return INTERFACE_SINGLETON.mKnownInstance = activityClientController;
+    }
+
     private static IActivityClientController getActivityClientController() {
-        return sActivityClientController.get();
+        final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance;
+        return controller != null ? controller : INTERFACE_SINGLETON.get();
     }
 
     private static final Singleton<ActivityClient> sInstance = new Singleton<ActivityClient>() {
@@ -462,8 +490,17 @@
         }
     };
 
-    private static final Singleton<IActivityClientController> sActivityClientController =
-            new Singleton<IActivityClientController>() {
+    private static final ActivityClientControllerSingleton INTERFACE_SINGLETON =
+            new ActivityClientControllerSingleton();
+
+    private static class ActivityClientControllerSingleton
+            extends Singleton<IActivityClientController> {
+        /**
+         * A quick look up to reduce potential extra binder transactions. E.g. getting activity
+         * task manager from service manager and controller from activity task manager.
+         */
+        IActivityClientController mKnownInstance;
+
         @Override
         protected IActivityClientController create() {
             try {
@@ -472,5 +509,5 @@
                 throw e.rethrowFromSystemServer();
             }
         }
-    };
+    }
 }
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 45a0e87..341393c 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -24,6 +24,4 @@
 parcelable ActivityManager.RunningServiceInfo;
 parcelable ActivityManager.RunningTaskInfo;
 /** @hide */
-parcelable ActivityManager.TaskThumbnail;
-/** @hide */
-parcelable ActivityManager.TaskSnapshot;
\ No newline at end of file
+parcelable ActivityManager.TaskThumbnail;
\ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 38a22d8..1227cc2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -31,6 +31,8 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -91,9 +93,6 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
-
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -870,6 +869,39 @@
     private static final boolean DEVELOPMENT_FORCE_LOW_RAM =
             SystemProperties.getBoolean("debug.force_low_ram", false);
 
+    /**
+     * Intent {@link Intent#ACTION_CLOSE_SYSTEM_DIALOGS} is too powerful to be unrestricted. We
+     * restrict its usage for a few legitimate use-cases only, regardless of targetSdk. For the
+     * other use-cases we drop the intent with a log message.
+     *
+     * Note that this is the lighter version of {@link ActivityManager
+     * #LOCK_DOWN_CLOSE_SYSTEM_DIALOGS} which is not gated on targetSdk in order to eliminate the
+     * abuse vector.
+     *
+     * @hide
+     */
+    @TestApi
+    @ChangeId
+    @Disabled
+    public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L;
+
+    /**
+     * Intent {@link Intent#ACTION_CLOSE_SYSTEM_DIALOGS} is too powerful to be unrestricted. So,
+     * apps targeting {@link Build.VERSION_CODES#S} or higher will crash if they try to send such
+     * intent and don't have permission {@code android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS}.
+     *
+     * Note that this is the more restrict version of {@link ActivityManager
+     * #DROP_CLOSE_SYSTEM_DIALOGS} that expects the app to stop sending aforementioned intent once
+     * it bumps its targetSdk to {@link Build.VERSION_CODES#S} or higher.
+     *
+     * @hide
+     */
+    @TestApi
+    @ChangeId
+    @Disabled
+    // @EnabledSince(targetSdkVersion = VERSION_CODES.S)
+    public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L;
+
     /** @hide */
     public int getFrontActivityScreenCompatMode() {
         try {
@@ -2082,351 +2114,6 @@
         return ActivityTaskManager.getInstance().getTasks(maxNum);
     }
 
-    /**
-     * Represents a task snapshot.
-     * @hide
-     */
-    public static class TaskSnapshot implements Parcelable {
-        // Identifier of this snapshot
-        private final long mId;
-        // Top activity in task when snapshot was taken
-        private final ComponentName mTopActivityComponent;
-        private final HardwareBuffer mSnapshot;
-        /** Indicates whether task was in landscape or portrait */
-        @Configuration.Orientation
-        private final int mOrientation;
-        /** See {@link android.view.Surface.Rotation} */
-        @Surface.Rotation
-        private int mRotation;
-        /** The size of the snapshot before scaling */
-        private final Point mTaskSize;
-        private final Rect mContentInsets;
-        // Whether this snapshot is a down-sampled version of the high resolution snapshot, used
-        // mainly for loading snapshots quickly from disk when user is flinging fast
-        private final boolean mIsLowResolution;
-        // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to
-        // the task having a secure window or having previews disabled
-        private final boolean mIsRealSnapshot;
-        private final int mWindowingMode;
-        private final @Appearance int mAppearance;
-        private final boolean mIsTranslucent;
-        // Must be one of the named color spaces, otherwise, always use SRGB color space.
-        private final ColorSpace mColorSpace;
-
-        public TaskSnapshot(long id,
-                @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot,
-                @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize,
-                Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot,
-                int windowingMode, @Appearance int appearance, boolean isTranslucent) {
-            mId = id;
-            mTopActivityComponent = topActivityComponent;
-            mSnapshot = snapshot;
-            mColorSpace = colorSpace.getId() < 0
-                    ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
-            mOrientation = orientation;
-            mRotation = rotation;
-            mTaskSize = new Point(taskSize);
-            mContentInsets = new Rect(contentInsets);
-            mIsLowResolution = isLowResolution;
-            mIsRealSnapshot = isRealSnapshot;
-            mWindowingMode = windowingMode;
-            mAppearance = appearance;
-            mIsTranslucent = isTranslucent;
-        }
-
-        private TaskSnapshot(Parcel source) {
-            mId = source.readLong();
-            mTopActivityComponent = ComponentName.readFromParcel(source);
-            mSnapshot = source.readParcelable(null /* classLoader */);
-            int colorSpaceId = source.readInt();
-            mColorSpace = colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length
-                    ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
-                    : ColorSpace.get(ColorSpace.Named.SRGB);
-            mOrientation = source.readInt();
-            mRotation = source.readInt();
-            mTaskSize = source.readParcelable(null /* classLoader */);
-            mContentInsets = source.readParcelable(null /* classLoader */);
-            mIsLowResolution = source.readBoolean();
-            mIsRealSnapshot = source.readBoolean();
-            mWindowingMode = source.readInt();
-            mAppearance = source.readInt();
-            mIsTranslucent = source.readBoolean();
-        }
-
-        /**
-         * @return Identifier of this snapshot.
-         */
-        public long getId() {
-            return mId;
-        }
-
-        /**
-         * @return The top activity component for the task at the point this snapshot was taken.
-         */
-        public ComponentName getTopActivityComponent() {
-            return mTopActivityComponent;
-        }
-
-        /**
-         * @return The graphic buffer representing the screenshot.
-         *
-         * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version
-         * creates a new object.
-         */
-        @UnsupportedAppUsage
-        public GraphicBuffer getSnapshot() {
-            return GraphicBuffer.createFromHardwareBuffer(mSnapshot);
-        }
-
-        /**
-         * @return The hardware buffer representing the screenshot.
-         */
-        public HardwareBuffer getHardwareBuffer() {
-            return mSnapshot;
-        }
-
-        /**
-         * @return The color space of hardware buffer representing the screenshot.
-         */
-        public ColorSpace getColorSpace() {
-            return mColorSpace;
-        }
-
-        /**
-         * @return The screen orientation the screenshot was taken in.
-         */
-        @UnsupportedAppUsage
-        public int getOrientation() {
-            return mOrientation;
-        }
-
-        /**
-         * @return The screen rotation the screenshot was taken in.
-         */
-        public int getRotation() {
-            return mRotation;
-        }
-
-        /**
-         * @return The size of the task at the point this snapshot was taken.
-         */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public Point getTaskSize() {
-            return mTaskSize;
-        }
-
-        /**
-         * @return The system/content insets on the snapshot. These can be clipped off in order to
-         *         remove any areas behind system bars in the snapshot.
-         */
-        @UnsupportedAppUsage
-        public Rect getContentInsets() {
-            return mContentInsets;
-        }
-
-        /**
-         * @return Whether this snapshot is a down-sampled version of the full resolution.
-         */
-        @UnsupportedAppUsage
-        public boolean isLowResolution() {
-            return mIsLowResolution;
-        }
-
-        /**
-         * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
-         * due to the task having a secure window or having previews disabled.
-         */
-        @UnsupportedAppUsage
-        public boolean isRealSnapshot() {
-            return mIsRealSnapshot;
-        }
-
-        /**
-         * @return Whether or not the snapshot is of a translucent app window (non-fullscreen or has
-         * a non-opaque pixel format).
-         */
-        public boolean isTranslucent() {
-            return mIsTranslucent;
-        }
-
-        /**
-         * @return The windowing mode of the task when this snapshot was taken.
-         */
-        public int getWindowingMode() {
-            return mWindowingMode;
-        }
-
-        /**
-         * @return The {@link Appearance} flags for the top most visible fullscreen window at the
-         *         time that the snapshot was taken.
-         */
-        public @Appearance int getAppearance() {
-            return mAppearance;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeLong(mId);
-            ComponentName.writeToParcel(mTopActivityComponent, dest);
-            dest.writeParcelable(mSnapshot != null && !mSnapshot.isClosed() ? mSnapshot : null,
-                    0);
-            dest.writeInt(mColorSpace.getId());
-            dest.writeInt(mOrientation);
-            dest.writeInt(mRotation);
-            dest.writeParcelable(mTaskSize, 0);
-            dest.writeParcelable(mContentInsets, 0);
-            dest.writeBoolean(mIsLowResolution);
-            dest.writeBoolean(mIsRealSnapshot);
-            dest.writeInt(mWindowingMode);
-            dest.writeInt(mAppearance);
-            dest.writeBoolean(mIsTranslucent);
-        }
-
-        @Override
-        public String toString() {
-            final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
-            final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
-            return "TaskSnapshot{"
-                    + " mId=" + mId
-                    + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
-                    + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
-                    + " mColorSpace=" + mColorSpace.toString()
-                    + " mOrientation=" + mOrientation
-                    + " mRotation=" + mRotation
-                    + " mTaskSize=" + mTaskSize.toString()
-                    + " mContentInsets=" + mContentInsets.toShortString()
-                    + " mIsLowResolution=" + mIsLowResolution
-                    + " mIsRealSnapshot=" + mIsRealSnapshot
-                    + " mWindowingMode=" + mWindowingMode
-                    + " mAppearance=" + mAppearance
-                    + " mIsTranslucent=" + mIsTranslucent;
-        }
-
-        public static final @android.annotation.NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
-            public TaskSnapshot createFromParcel(Parcel source) {
-                return new TaskSnapshot(source);
-            }
-            public TaskSnapshot[] newArray(int size) {
-                return new TaskSnapshot[size];
-            }
-        };
-
-        /** Builder for a {@link TaskSnapshot} object */
-        public static final class Builder {
-            private long mId;
-            private ComponentName mTopActivity;
-            private HardwareBuffer mSnapshot;
-            private ColorSpace mColorSpace;
-            private int mOrientation;
-            private int mRotation;
-            private Point mTaskSize;
-            private Rect mContentInsets;
-            private boolean mIsRealSnapshot;
-            private int mWindowingMode;
-            private @Appearance int mAppearance;
-            private boolean mIsTranslucent;
-            private int mPixelFormat;
-
-            public Builder setId(long id) {
-                mId = id;
-                return this;
-            }
-
-            public Builder setTopActivityComponent(ComponentName name) {
-                mTopActivity = name;
-                return this;
-            }
-
-            public Builder setSnapshot(HardwareBuffer buffer) {
-                mSnapshot = buffer;
-                return this;
-            }
-
-            public Builder setColorSpace(ColorSpace colorSpace) {
-                mColorSpace = colorSpace;
-                return this;
-            }
-
-            public Builder setOrientation(int orientation) {
-                mOrientation = orientation;
-                return this;
-            }
-
-            public Builder setRotation(int rotation) {
-                mRotation = rotation;
-                return this;
-            }
-
-            /**
-             * Sets the original size of the task
-             */
-            public Builder setTaskSize(Point size) {
-                mTaskSize = size;
-                return this;
-            }
-
-            public Builder setContentInsets(Rect contentInsets) {
-                mContentInsets = contentInsets;
-                return this;
-            }
-
-            public Builder setIsRealSnapshot(boolean realSnapshot) {
-                mIsRealSnapshot = realSnapshot;
-                return this;
-            }
-
-            public Builder setWindowingMode(int windowingMode) {
-                mWindowingMode = windowingMode;
-                return this;
-            }
-
-            public Builder setAppearance(@Appearance int appearance) {
-                mAppearance = appearance;
-                return this;
-            }
-
-            public Builder setIsTranslucent(boolean isTranslucent) {
-                mIsTranslucent = isTranslucent;
-                return this;
-            }
-
-            public int getPixelFormat() {
-                return mPixelFormat;
-            }
-
-            public Builder setPixelFormat(int pixelFormat) {
-                mPixelFormat = pixelFormat;
-                return this;
-            }
-
-            public TaskSnapshot build() {
-                return new TaskSnapshot(
-                        mId,
-                        mTopActivity,
-                        mSnapshot,
-                        mColorSpace,
-                        mOrientation,
-                        mRotation,
-                        mTaskSize,
-                        mContentInsets,
-                        // When building a TaskSnapshot with the Builder class, isLowResolution
-                        // is always false. Low-res snapshots are only created when loading from
-                        // disk.
-                        false /* isLowResolution */,
-                        mIsRealSnapshot,
-                        mWindowingMode,
-                        mAppearance,
-                        mIsTranslucent);
-
-            }
-        }
-    }
-
     /** @hide */
     @IntDef(flag = true, prefix = { "MOVE_TASK_" }, value = {
             MOVE_TASK_WITH_HOME,
@@ -4167,10 +3854,8 @@
             "android.permission.INTERACT_ACROSS_USERS_FULL"
     })
     public static int getCurrentUser() {
-        UserInfo ui;
         try {
-            ui = getService().getCurrentUser();
-            return ui != null ? ui.id : 0;
+            return getService().getCurrentUserId();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
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/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 03c1a01..2060252 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -419,20 +419,6 @@
     }
 
     /**
-     * Requests that an activity should enter picture-in-picture mode if possible.
-     * @hide
-     */
-    @TestApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
-    public void requestPictureInPictureMode(@NonNull IBinder token) {
-        try {
-            getService().requestPictureInPictureMode(token);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * @return whether the UI mode of the given config supports error dialogs (ANR, crash, etc).
      * @hide
      */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ed6dea8..6d564a3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6681,8 +6681,7 @@
     private InstrumentationInfo prepareInstrumentation(AppBindData data) {
         final InstrumentationInfo ii;
         try {
-            ii = new ApplicationPackageManager(
-                    null, getPackageManager(), getPermissionManager())
+            ii = new ApplicationPackageManager(null, getPackageManager())
                     .getInstrumentationInfo(data.instrumentationName, 0);
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException(
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4dd6a7e..20953c6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1166,8 +1166,21 @@
     public static final int OP_MANAGE_CREDENTIALS = AppProtoEnums.APP_OP_MANAGE_CREDENTIALS;
 
     /** @hide */
+    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 = 105;
+    public static final int _NUM_OP = 107;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1525,6 +1538,21 @@
      */
     public static final String OPSTR_MANAGE_CREDENTIALS = "android:manage_credentials";
 
+    /**
+     * Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+     *
+     * @hide
+     */
+    @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;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1604,6 +1632,7 @@
             OP_INTERACT_ACROSS_PROFILES,
             OP_LOADER_USAGE_STATS,
             OP_MANAGE_ONGOING_CALLS,
+            OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
     };
 
     /**
@@ -1720,6 +1749,8 @@
             OP_RECORD_AUDIO_HOTWORD,            // RECORD_AUDIO_HOTWORD
             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
     };
 
     /**
@@ -1831,6 +1862,8 @@
             OPSTR_RECORD_AUDIO_HOTWORD,
             OPSTR_MANAGE_ONGOING_CALLS,
             OPSTR_MANAGE_CREDENTIALS,
+            OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+            OPSTR_RECORD_AUDIO_OUTPUT,
     };
 
     /**
@@ -1943,6 +1976,8 @@
             "RECORD_AUDIO_HOTWORD",
             "MANAGE_ONGOING_CALLS",
             "MANAGE_CREDENTIALS",
+            "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
+            "RECORD_AUDIO_OUTPUT",
     };
 
     /**
@@ -2056,6 +2091,8 @@
             null, // no permission for OP_RECORD_AUDIO_HOTWORD
             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
     };
 
     /**
@@ -2169,6 +2206,8 @@
             null, // RECORD_AUDIO_HOTWORD
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
+            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            null, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2281,6 +2320,8 @@
             null, // RECORD_AUDIO_HOTWORD
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
+            null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            null, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2392,6 +2433,8 @@
             AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD
             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
     };
 
     /**
@@ -2507,6 +2550,8 @@
             false, // RECORD_AUDIO_HOTWORD
             true, // MANAGE_ONGOING_CALLS
             false, // MANAGE_CREDENTIALS
+            true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            false, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -6489,9 +6534,10 @@
          * @param code The op code.
          * @param uid The UID performing the operation.
          * @param packageName The package performing the operation.
+         * @param flags The flags of this op
          * @param result The result of the note.
          */
-        void onOpNoted(int code, int uid, String packageName, int result);
+        void onOpNoted(int code, int uid, String packageName, @OpFlags int flags, @Mode int result);
     }
 
     /**
@@ -6528,9 +6574,10 @@
          * @param op The op code.
          * @param uid The UID performing the operation.
          * @param packageName The package performing the operation.
+         * @param flags The flags of this op
          * @param result The result of the start.
          */
-        void onOpStarted(int op, int uid, String packageName, int result);
+        void onOpStarted(int op, int uid, String packageName, @OpFlags int flags, @Mode int result);
     }
 
     AppOpsManager(Context context, IAppOpsService service) {
@@ -7113,8 +7160,8 @@
              }
              cb = new IAppOpsStartedCallback.Stub() {
                  @Override
-                 public void opStarted(int op, int uid, String packageName, int mode) {
-                     callback.onOpStarted(op, uid, packageName, mode);
+                 public void opStarted(int op, int uid, String packageName, int flags, int mode) {
+                     callback.onOpStarted(op, uid, packageName, flags, mode);
                  }
              };
              mStartedWatchers.put(callback, cb);
@@ -7180,8 +7227,8 @@
             }
             cb = new IAppOpsNotedCallback.Stub() {
                 @Override
-                public void opNoted(int op, int uid, String packageName, int mode) {
-                    callback.onOpNoted(op, uid, packageName, mode);
+                public void opNoted(int op, int uid, String packageName, int flags, int mode) {
+                    callback.onOpNoted(op, uid, packageName, flags, mode);
                 }
             };
             mNotedWatchers.put(callback, cb);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 3642d31..186d1fe 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -59,8 +59,6 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManager.Property;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
@@ -95,8 +93,6 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
-import android.permission.IOnPermissionsChangeListener;
-import android.permission.IPermissionManager;
 import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.system.ErrnoException;
@@ -106,7 +102,6 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.DebugUtils;
 import android.util.LauncherIcons;
 import android.util.Log;
 
@@ -129,7 +124,6 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -137,14 +131,6 @@
 public class ApplicationPackageManager extends PackageManager {
     private static final String TAG = "ApplicationPackageManager";
     private static final boolean DEBUG_ICONS = false;
-    /**
-     * Note: Changing this won't do anything on it's own - you should also change the filtering in
-     * {@link #shouldTraceGrant}
-     *
-     * @hide
-     */
-    public static final boolean DEBUG_TRACE_GRANTS = false;
-    public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
 
     private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
 
@@ -171,6 +157,8 @@
     @GuardedBy("mLock")
     private UserManager mUserManager;
     @GuardedBy("mLock")
+    private PermissionManager mPermissionManager;
+    @GuardedBy("mLock")
     private PackageInstaller mInstaller;
     @GuardedBy("mLock")
     private ArtManager mArtManager;
@@ -190,6 +178,15 @@
         }
     }
 
+    private PermissionManager getPermissionManager() {
+        synchronized (mLock) {
+            if (mPermissionManager == null) {
+                mPermissionManager = mContext.getSystemService(PermissionManager.class);
+            }
+            return mPermissionManager;
+        }
+    }
+
     @Override
     public int getUserId() {
         return mContext.getUserId();
@@ -355,66 +352,41 @@
     @Override
     @SuppressWarnings("unchecked")
     public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
-        try {
-            final ParceledListSlice<PermissionGroupInfo> parceledList =
-                    mPermissionManager.getAllPermissionGroups(flags);
-            if (parceledList == null) {
-                return Collections.emptyList();
-            }
-            return parceledList.getList();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().getAllPermissionGroups(flags);
     }
 
     @Override
     public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags)
             throws NameNotFoundException {
-        try {
-            final PermissionGroupInfo pgi =
-                    mPermissionManager.getPermissionGroupInfo(groupName, flags);
-            if (pgi != null) {
-                return pgi;
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        final PermissionGroupInfo permissionGroupInfo = getPermissionManager()
+                .getPermissionGroupInfo(groupName, flags);
+        if (permissionGroupInfo == null) {
+            throw new NameNotFoundException(groupName);
         }
-        throw new NameNotFoundException(groupName);
+        return permissionGroupInfo;
     }
 
     @Override
     public PermissionInfo getPermissionInfo(String permName, int flags)
             throws NameNotFoundException {
-        try {
-            final String packageName = mContext.getOpPackageName();
-            final PermissionInfo pi =
-                    mPermissionManager.getPermissionInfo(permName, packageName, flags);
-            if (pi != null) {
-                return pi;
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        final PermissionInfo permissionInfo = getPermissionManager().getPermissionInfo(permName,
+                flags);
+        if (permissionInfo == null) {
+            throw new NameNotFoundException(permName);
         }
-        throw new NameNotFoundException(permName);
+        return permissionInfo;
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags)
             throws NameNotFoundException {
-        try {
-            final ParceledListSlice<PermissionInfo> parceledList =
-                    mPermissionManager.queryPermissionsByGroup(groupName, flags);
-            if (parceledList != null) {
-                final List<PermissionInfo> pi = parceledList.getList();
-                if (pi != null) {
-                    return pi;
-                }
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        final List<PermissionInfo> permissionInfos = getPermissionManager().queryPermissionsByGroup(
+                groupName, flags);
+        if (permissionInfos == null) {
+            throw new NameNotFoundException(groupName);
         }
-        throw new NameNotFoundException(groupName);
+        return permissionInfos;
     }
 
     @Override
@@ -724,11 +696,7 @@
 
     @Override
     public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
-        try {
-            return mPermissionManager.isPermissionRevokedByPolicy(permName, pkgName, getUserId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().isPermissionRevokedByPolicy(pkgName, permName);
     }
 
     /**
@@ -750,50 +718,23 @@
 
     @Override
     public boolean addPermission(PermissionInfo info) {
-        try {
-            return mPermissionManager.addPermission(info, false);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().addPermission(info, false);
     }
 
     @Override
     public boolean addPermissionAsync(PermissionInfo info) {
-        try {
-            return mPermissionManager.addPermission(info, true);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().addPermission(info, true);
     }
 
     @Override
     public void removePermission(String name) {
-        try {
-            mPermissionManager.removePermission(name);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        getPermissionManager().removePermission(name);
     }
 
     @Override
     public void grantRuntimePermission(String packageName, String permissionName,
             UserHandle user) {
-        if (DEBUG_TRACE_GRANTS
-                && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
-            Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " "
-                    + permissionName + " for user " + user.getIdentifier(), new RuntimeException());
-        }
-        try {
-            mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
-    public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) {
-        // To be modified when debugging
-        return false;
+        getPermissionManager().grantRuntimePermission(packageName, permissionName, user);
     }
 
     @Override
@@ -804,124 +745,55 @@
     @Override
     public void revokeRuntimePermission(String packageName, String permName, UserHandle user,
             String reason) {
-        if (DEBUG_TRACE_PERMISSION_UPDATES
-                && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
-            Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
-                    + permName + " for user " + user.getIdentifier() + " with reason " + reason,
-                    new RuntimeException());
-        }
-        try {
-            mPermissionManager
-                    .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        getPermissionManager().revokeRuntimePermission(packageName, permName, user, reason);
     }
 
     @Override
     public int getPermissionFlags(String permName, String packageName, UserHandle user) {
-        try {
-            return mPermissionManager
-                    .getPermissionFlags(permName, packageName, user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().getPermissionFlags(packageName, permName, user);
     }
 
     @Override
     public void updatePermissionFlags(String permName, String packageName,
             int flagMask, int flagValues, UserHandle user) {
-        if (DEBUG_TRACE_PERMISSION_UPDATES
-                && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
-            Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for "
-                    + packageName + " "
-                    + permName + " for user " + user.getIdentifier() + ": "
-                    + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
-                    + " := " + DebugUtils.flagsToString(
-                            PackageManager.class, "FLAG_PERMISSION_", flagValues),
-                    new RuntimeException());
-        }
-        try {
-            final boolean checkAdjustPolicyFlagPermission =
-                    mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
-            mPermissionManager.updatePermissionFlags(permName, packageName, flagMask,
-                    flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        getPermissionManager().updatePermissionFlags(packageName, permName, flagMask, flagValues,
+                user);
     }
 
     @Override
     public @NonNull Set<String> getWhitelistedRestrictedPermissions(
             @NonNull String packageName, @PermissionWhitelistFlags int flags) {
-        try {
-            final int userId = getUserId();
-            final List<String> whitelist = mPermissionManager
-                    .getWhitelistedRestrictedPermissions(packageName, flags, userId);
-            if (whitelist != null) {
-                return new ArraySet<>(whitelist);
-            }
-            return Collections.emptySet();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().getAllowlistedRestrictedPermissions(packageName, flags);
     }
 
     @Override
     public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
             @NonNull String permName, @PermissionWhitelistFlags int flags) {
-        try {
-            final int userId = getUserId();
-            return mPermissionManager
-                    .addWhitelistedRestrictedPermission(packageName, permName, flags, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().addAllowlistedRestrictedPermission(packageName, permName,
+                flags);
     }
 
     @Override
-    public boolean setAutoRevokeWhitelisted(
-            @NonNull String packageName, boolean whitelisted) {
-        try {
-            final int userId = getUserId();
-            return mPermissionManager.setAutoRevokeWhitelisted(packageName, whitelisted, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+    public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) {
+        return getPermissionManager().setAutoRevokeExempted(packageName, whitelisted);
     }
 
     @Override
     public boolean isAutoRevokeWhitelisted(@NonNull String packageName) {
-        try {
-            final int userId = getUserId();
-            return mPermissionManager.isAutoRevokeWhitelisted(packageName, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().isAutoRevokeExempted(packageName);
     }
 
     @Override
     public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
             @NonNull String permName, @PermissionWhitelistFlags int flags) {
-        try {
-            final int userId = getUserId();
-            return mPermissionManager
-                    .removeWhitelistedRestrictedPermission(packageName, permName, flags, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().removeAllowlistedRestrictedPermission(packageName, permName,
+                flags);
     }
 
     @Override
     @UnsupportedAppUsage
     public boolean shouldShowRequestPermissionRationale(String permName) {
-        try {
-            final String packageName = mContext.getPackageName();
-            return mPermissionManager
-                    .shouldShowRequestPermissionRationale(permName, packageName, getUserId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getPermissionManager().shouldShowRequestPermissionRationale(permName);
     }
 
     @Override
@@ -1880,34 +1752,12 @@
 
     @Override
     public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
-        synchronized (mPermissionListeners) {
-            if (mPermissionListeners.get(listener) != null) {
-                return;
-            }
-            OnPermissionsChangeListenerDelegate delegate =
-                    new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
-            try {
-                mPermissionManager.addOnPermissionsChangeListener(delegate);
-                mPermissionListeners.put(listener, delegate);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        getPermissionManager().addOnPermissionsChangeListener(listener);
     }
 
     @Override
     public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
-        synchronized (mPermissionListeners) {
-            IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
-            if (delegate != null) {
-                try {
-                    mPermissionManager.removeOnPermissionsChangeListener(delegate);
-                    mPermissionListeners.remove(listener);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-        }
+        getPermissionManager().removeOnPermissionsChangeListener(listener);
     }
 
     @UnsupportedAppUsage
@@ -1918,11 +1768,9 @@
         }
     }
 
-    protected ApplicationPackageManager(ContextImpl context, IPackageManager pm,
-            IPermissionManager permissionManager) {
+    protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) {
         mContext = context;
         mPM = pm;
-        mPermissionManager = permissionManager;
     }
 
     /**
@@ -3234,7 +3082,6 @@
     private final ContextImpl mContext;
     @UnsupportedAppUsage
     private final IPackageManager mPM;
-    private final IPermissionManager mPermissionManager;
 
     /** Assume locked until we hear otherwise */
     private volatile boolean mUserUnlocked = false;
@@ -3245,41 +3092,6 @@
     private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
             = new ArrayMap<ResourceName, WeakReference<CharSequence>>();
 
-    private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener>
-            mPermissionListeners = new ArrayMap<>();
-
-    public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub
-            implements Handler.Callback{
-        private static final int MSG_PERMISSIONS_CHANGED = 1;
-
-        private final OnPermissionsChangedListener mListener;
-        private final Handler mHandler;
-
-
-        public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener,
-                Looper looper) {
-            mListener = listener;
-            mHandler = new Handler(looper, this);
-        }
-
-        @Override
-        public void onPermissionsChanged(int uid) {
-            mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
-        }
-
-        @Override
-        public boolean handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_PERMISSIONS_CHANGED: {
-                    final int uid = msg.arg1;
-                    mListener.onPermissionsChanged(uid);
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
     @Override
     public boolean canRequestPackageInstalls() {
         try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 15e2c0d..700d8ff 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -72,7 +72,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
-import android.permission.IPermissionManager;
 import android.permission.PermissionManager;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -370,10 +369,9 @@
         }
 
         final IPackageManager pm = ActivityThread.getPackageManager();
-        final IPermissionManager permissionManager = ActivityThread.getPermissionManager();
-        if (pm != null && permissionManager != null) {
+        if (pm != null) {
             // Doesn't matter if we make more than one instance.
-            return (mPackageManager = new ApplicationPackageManager(this, pm, permissionManager));
+            return (mPackageManager = new ApplicationPackageManager(this, pm));
         }
 
         return null;
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index f9449f2..e1e0a8a 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -58,6 +58,8 @@
     int getTaskForActivity(in IBinder token, in boolean onlyRoot);
     ComponentName getCallingActivity(in IBinder token);
     String getCallingPackage(in IBinder token);
+    int getLaunchedFromUid(in IBinder token);
+    String getLaunchedFromPackage(in IBinder token);
     Bundle getActivityOptions(in IBinder token);
 
     void setRequestedOrientation(in IBinder token, int requestedOrientation);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 86625d3..94b2118 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -363,6 +363,7 @@
     boolean killProcessesBelowForeground(in String reason);
     @UnsupportedAppUsage
     UserInfo getCurrentUser();
+    int getCurrentUserId();
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
     @UnsupportedAppUsage
@@ -542,14 +543,6 @@
     /** Cancels the window transitions for the given task. */
     @UnsupportedAppUsage
     void cancelTaskWindowTransition(int taskId);
-    /**
-     * @param taskId the id of the task to retrieve the sAutoapshots for
-     * @param isLowResolution if set, if the snapshot needs to be loaded from disk, this will load
-     *                          a reduced resolution of it, which is much faster
-     * @return a graphic buffer representing a screenshot of a task
-     */
-    @UnsupportedAppUsage
-    ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
     void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
     void setPersistentVrThread(int tid);
 
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 4b25573..523c155 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -159,8 +159,6 @@
             int userId);
     boolean isTopActivityImmersive();
     ActivityManager.TaskDescription getTaskDescription(int taskId);
-    int getLaunchedFromUid(in IBinder activityToken);
-    String getLaunchedFromPackage(in IBinder activityToken);
     void reportAssistContextExtras(in IBinder assistToken, in Bundle extras,
             in AssistStructure structure, in AssistContent content, in Uri referrer);
 
@@ -193,7 +191,7 @@
      */
     IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
 
-    void releaseSomeActivities(in IApplicationThread app);
+    oneway void releaseSomeActivities(in IApplicationThread app);
     Bitmap getTaskDescriptionIcon(in String filename, int userId);
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
@@ -257,12 +255,9 @@
      *              etc.
      */
     void keyguardGoingAway(int flags);
-    ComponentName getActivityClassForToken(in IBinder token);
-    String getPackageForToken(in IBinder token);
 
     void suppressResizeConfigChanges(boolean suppress);
     boolean moveTopActivityToPinnedRootTask(int rootTaskId, in Rect bounds);
-    void requestPictureInPictureMode(in IBinder token);
 
     /**
      * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
@@ -312,7 +307,7 @@
      *                          a reduced resolution of it, which is much faster
      * @return a graphic buffer representing a screenshot of a task
      */
-    ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
+    android.window.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
 
     /**
      * It should only be called from home activity to remove its outdated snapshot. The home
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index dc7782a..301d188 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
+import android.window.TaskSnapshot;
 
 /** @hide */
 oneway interface ITaskStackListener {
@@ -141,7 +142,7 @@
     /**
      * Called when a task snapshot got updated.
      */
-    void onTaskSnapshotChanged(int taskId, in ActivityManager.TaskSnapshot snapshot);
+    void onTaskSnapshotChanged(int taskId, in TaskSnapshot snapshot);
 
     /**
      * Called when the resumed activity is in size compatibility mode and its override configuration
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
new file mode 100644
index 0000000..06ad9c9
--- /dev/null
+++ b/core/java/android/app/OWNERS
@@ -0,0 +1,34 @@
+
+# Remain no owner because multiple modules may touch this file.
+per-file ContextImpl.java = *
+
+# ActivityThread
+per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS
+per-file ActivityThread.java = file:/services/core/java/com/android/server/wm/OWNERS
+
+# Alarm
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
+
+# AppOps
+per-file *AppOp* = file:/core/java/android/permission/OWNERS
+
+# Notification
+per-file *Notification* = file:/packages/SystemUI/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* = 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 *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
+
+# Zygote
+per-file *Zygote* = file:/ZYGOTE_OWNERS
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 29c9c67..ea7eab2 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -48,7 +48,9 @@
         @Nullable
         private Rect mSourceRectHint;
 
-        private boolean mAutoEnterEnabled;
+        private Boolean mAutoEnterEnabled;
+
+        private Boolean mSeamlessResizeEnabled;
 
         /**
          * Sets the aspect ratio.  This aspect ratio is defined as the desired width / height, and
@@ -113,7 +115,7 @@
          *
          * If true, {@link Activity#onPictureInPictureRequested()} will never be called.
          *
-         * This property is false by default.
+         * This property is {@code false} by default.
          * @param autoEnterEnabled {@code true} if the system will automatically put the activity
          *                                     in picture-in-picture mode.
          *
@@ -126,6 +128,23 @@
         }
 
         /**
+         * Sets whether the system can seamlessly resize the window while the activity is in
+         * picture-in-picture mode. This should normally be the case for video content and
+         * when it's set to {@code false}, system will perform transitions to overcome the
+         * artifacts due to resize.
+         *
+         * This property is {@code true} by default for backwards compatibility.
+         * @param seamlessResizeEnabled {@code true} if the system can seamlessly resize the window
+         *                                          while activity is in picture-in-picture mode.
+         * @return this builder instance.
+         */
+        @NonNull
+        public Builder setSeamlessResizeEnabled(boolean seamlessResizeEnabled) {
+            mSeamlessResizeEnabled = seamlessResizeEnabled;
+            return this;
+        }
+
+        /**
          * @return an immutable {@link PictureInPictureParams} to be used when entering or updating
          * the activity in picture-in-picture.
          *
@@ -134,7 +153,7 @@
          */
         public PictureInPictureParams build() {
             PictureInPictureParams params = new PictureInPictureParams(mAspectRatio, mUserActions,
-                    mSourceRectHint, mAutoEnterEnabled);
+                    mSourceRectHint, mAutoEnterEnabled, mSeamlessResizeEnabled);
             return params;
         }
     }
@@ -161,8 +180,16 @@
 
     /**
      * Whether the system is allowed to automatically put the activity in picture-in-picture mode.
+     * {@link #isAutoEnterEnabled()} defaults to {@code false} if this is not set.
      */
-    private boolean mAutoEnterEnabled;
+    private Boolean mAutoEnterEnabled;
+
+    /**
+     * Whether system can seamlessly resize the window when activity is in picture-in-picture mode.
+     * {@link #isSeamlessResizeEnabled()} defaults to {@code true} if this is not set for
+     * backwards compatibility.
+     */
+    private Boolean mSeamlessResizeEnabled;
 
     /** {@hide} */
     PictureInPictureParams() {
@@ -183,15 +210,19 @@
         if (in.readInt() != 0) {
             mAutoEnterEnabled = in.readBoolean();
         }
+        if (in.readInt() != 0) {
+            mSeamlessResizeEnabled = in.readBoolean();
+        }
     }
 
     /** {@hide} */
     PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions,
-            Rect sourceRectHint, boolean autoEnterEnabled) {
+            Rect sourceRectHint, Boolean autoEnterEnabled, Boolean seamlessResizeEnabled) {
         mAspectRatio = aspectRatio;
         mUserActions = actions;
         mSourceRectHint = sourceRectHint;
         mAutoEnterEnabled = autoEnterEnabled;
+        mSeamlessResizeEnabled = seamlessResizeEnabled;
     }
 
     /**
@@ -201,7 +232,7 @@
     public PictureInPictureParams(PictureInPictureParams other) {
         this(other.mAspectRatio, other.mUserActions,
                 other.hasSourceBoundsHint() ? new Rect(other.getSourceRectHint()) : null,
-                other.mAutoEnterEnabled);
+                other.mAutoEnterEnabled, other.mSeamlessResizeEnabled);
     }
 
     /**
@@ -218,7 +249,12 @@
         if (otherArgs.hasSourceBoundsHint()) {
             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
         }
-        mAutoEnterEnabled = otherArgs.mAutoEnterEnabled;
+        if (otherArgs.mAutoEnterEnabled != null) {
+            mAutoEnterEnabled = otherArgs.mAutoEnterEnabled;
+        }
+        if (otherArgs.mSeamlessResizeEnabled != null) {
+            mSeamlessResizeEnabled = otherArgs.mSeamlessResizeEnabled;
+        }
     }
 
     /**
@@ -295,7 +331,16 @@
      * @hide
      */
     public boolean isAutoEnterEnabled() {
-        return mAutoEnterEnabled;
+        return mAutoEnterEnabled == null ? false : mAutoEnterEnabled;
+    }
+
+    /**
+     * @return whether seamless resize is enabled.
+     * @hide
+     */
+    @TestApi
+    public boolean isSeamlessResizeEnabled() {
+        return mSeamlessResizeEnabled == null ? true : mSeamlessResizeEnabled;
     }
 
     /**
@@ -304,7 +349,7 @@
      */
     public boolean empty() {
         return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio()
-                && !mAutoEnterEnabled;
+                && mAutoEnterEnabled != null && mSeamlessResizeEnabled != null;
     }
 
     @Override
@@ -312,7 +357,8 @@
         if (this == o) return true;
         if (!(o instanceof PictureInPictureParams)) return false;
         PictureInPictureParams that = (PictureInPictureParams) o;
-        return mAutoEnterEnabled == that.mAutoEnterEnabled
+        return Objects.equals(mAutoEnterEnabled, that.mAutoEnterEnabled)
+                && Objects.equals(mSeamlessResizeEnabled, that.mSeamlessResizeEnabled)
                 && Objects.equals(mAspectRatio, that.mAspectRatio)
                 && Objects.equals(mUserActions, that.mUserActions)
                 && Objects.equals(mSourceRectHint, that.mSourceRectHint);
@@ -320,7 +366,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mAspectRatio, mUserActions, mSourceRectHint, mAutoEnterEnabled);
+        return Objects.hash(mAspectRatio, mUserActions, mSourceRectHint,
+                mAutoEnterEnabled, mSeamlessResizeEnabled);
     }
 
     @Override
@@ -349,8 +396,18 @@
         } else {
             out.writeInt(0);
         }
-        out.writeInt(1);
-        out.writeBoolean(mAutoEnterEnabled);
+        if (mAutoEnterEnabled != null) {
+            out.writeInt(1);
+            out.writeBoolean(mAutoEnterEnabled);
+        } else {
+            out.writeInt(0);
+        }
+        if (mSeamlessResizeEnabled != null) {
+            out.writeInt(1);
+            out.writeBoolean(mSeamlessResizeEnabled);
+        } else {
+            out.writeInt(0);
+        }
     }
 
     @Override
@@ -360,6 +417,7 @@
                 + " sourceRectHint=" + getSourceRectHint()
                 + " hasSetActions=" + hasSetActions()
                 + " isAutoPipEnabled=" + isAutoEnterEnabled()
+                + " isSeamlessResizeEnabled=" + isSeamlessResizeEnabled()
                 + ")";
     }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 392d6fb..4afbfbf 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -32,6 +32,7 @@
 import android.app.prediction.AppPredictionManager;
 import android.app.role.RoleControllerManager;
 import android.app.role.RoleManager;
+import android.app.search.SearchUiManager;
 import android.app.slice.SliceManager;
 import android.app.time.TimeManager;
 import android.app.timedetector.TimeDetector;
@@ -63,7 +64,6 @@
 import android.content.pm.DataLoaderManager;
 import android.content.pm.ICrossProfileApps;
 import android.content.pm.IDataLoaderManager;
-import android.content.pm.IPackageManager;
 import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
@@ -118,7 +118,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;
@@ -176,6 +175,7 @@
 import android.os.incremental.IIncrementalService;
 import android.os.incremental.IncrementalManager;
 import android.os.storage.StorageManager;
+import android.permission.LegacyPermissionManager;
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.print.IPrintManager;
@@ -781,8 +781,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,
@@ -1174,6 +1173,16 @@
                 return null;
             }});
 
+        registerService(Context.SEARCH_UI_SERVICE, SearchUiManager.class,
+            new CachedServiceFetcher<SearchUiManager>() {
+                @Override
+                public SearchUiManager createService(ContextImpl ctx)
+                    throws ServiceNotFoundException {
+                    IBinder b = ServiceManager.getService(Context.SEARCH_UI_SERVICE);
+                    return b == null ? null : new SearchUiManager(ctx);
+                }
+            });
+
         registerService(Context.APP_PREDICTION_SERVICE, AppPredictionManager.class,
                 new CachedServiceFetcher<AppPredictionManager>() {
             @Override
@@ -1264,8 +1273,15 @@
                     @Override
                     public PermissionManager createService(ContextImpl ctx)
                             throws ServiceNotFoundException {
-                        IPackageManager packageManager = AppGlobals.getPackageManager();
-                        return new PermissionManager(ctx.getOuterContext(), packageManager);
+                        return new PermissionManager(ctx.getOuterContext());
+                    }});
+
+        registerService(Context.LEGACY_PERMISSION_SERVICE, LegacyPermissionManager.class,
+                new CachedServiceFetcher<LegacyPermissionManager>() {
+                    @Override
+                    public LegacyPermissionManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        return new LegacyPermissionManager();
                     }});
 
         registerService(Context.PERMISSION_CONTROLLER_SERVICE, PermissionControllerManager.class,
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 8367bde..61c4d39 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -27,12 +27,12 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
-import android.graphics.Rect;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.util.Log;
+import android.window.TaskSnapshot;
 import android.window.WindowContainerToken;
 
 import java.util.ArrayList;
@@ -187,14 +187,6 @@
     public boolean isResizeable;
 
     /**
-     * Activity bounds if this task or its top activity is presented in letterbox mode and
-     * {@code null} otherwise.
-     * @hide
-     */
-    @Nullable
-    public Rect letterboxActivityBounds;
-
-    /**
      * Relative position of the task's top left corner in the parent container.
      * @hide
      */
@@ -215,12 +207,6 @@
     public int parentTaskId;
 
     /**
-     * Parent bounds.
-     * @hide
-     */
-    public Rect parentBounds;
-
-    /**
      * Whether this task is focused.
      * @hide
      */
@@ -245,9 +231,9 @@
      * @return
      * @hide
      */
-    public ActivityManager.TaskSnapshot getTaskSnapshot(boolean isLowResolution) {
+    public TaskSnapshot getTaskSnapshot(boolean isLowResolution) {
         try {
-            return ActivityManager.getService().getTaskSnapshot(taskId, isLowResolution);
+            return ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e);
             return null;
@@ -312,7 +298,6 @@
         return topActivityType == that.topActivityType
                 && isResizeable == that.isResizeable
                 && Objects.equals(positionInParent, that.positionInParent)
-                && equalsLetterboxParams(that)
                 && Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
                 && getWindowingMode() == that.getWindowingMode()
                 && Objects.equals(taskDescription, that.taskDescription)
@@ -320,17 +305,6 @@
                 && isVisible == that.isVisible;
     }
 
-    private boolean equalsLetterboxParams(TaskInfo that) {
-        return Objects.equals(letterboxActivityBounds, that.letterboxActivityBounds)
-                && Objects.equals(
-                        getConfiguration().windowConfiguration.getBounds(),
-                        that.getConfiguration().windowConfiguration.getBounds())
-                && Objects.equals(
-                        getConfiguration().windowConfiguration.getMaxBounds(),
-                        that.getConfiguration().windowConfiguration.getMaxBounds())
-                && Objects.equals(parentBounds, that.parentBounds);
-    }
-
     /**
      * Reads the TaskInfo from a parcel.
      */
@@ -359,10 +333,8 @@
         topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
         isResizeable = source.readBoolean();
         source.readBinderList(launchCookies);
-        letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
         positionInParent = source.readTypedObject(Point.CREATOR);
         parentTaskId = source.readInt();
-        parentBounds = source.readTypedObject(Rect.CREATOR);
         isFocused = source.readBoolean();
         isVisible = source.readBoolean();
     }
@@ -396,10 +368,8 @@
         dest.writeTypedObject(topActivityInfo, flags);
         dest.writeBoolean(isResizeable);
         dest.writeBinderList(launchCookies);
-        dest.writeTypedObject(letterboxActivityBounds, flags);
         dest.writeTypedObject(positionInParent, flags);
         dest.writeInt(parentTaskId);
-        dest.writeTypedObject(parentBounds, flags);
         dest.writeBoolean(isFocused);
         dest.writeBoolean(isVisible);
     }
@@ -422,10 +392,8 @@
                 + " pictureInPictureParams=" + pictureInPictureParams
                 + " topActivityInfo=" + topActivityInfo
                 + " launchCookies=" + launchCookies
-                + " letterboxActivityBounds=" + letterboxActivityBounds
                 + " positionInParent=" + positionInParent
                 + " parentTaskId=" + parentTaskId
-                + " parentBounds=" + parentBounds
                 + " isFocused=" + isFocused
                 + " isVisible=" + isVisible
                 + "}";
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 70ad9af..c311d718 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -17,7 +17,7 @@
 package android.app;
 
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.os.Binder;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4095acc..02c12b9 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
      */
@@ -2610,6 +2612,18 @@
     /** @hide */
     @TestApi
     public static final int OPERATION_REMOVE_USER = 6;
+    /** @hide */
+    @TestApi
+    public static final int OPERATION_REBOOT = 7;
+    /** @hide */
+    @TestApi
+    public static final int OPERATION_WIPE_DATA = 8;
+    /** @hide */
+    @TestApi
+    public static final int OPERATION_LOGOUT_USER = 9;
+    /** @hide */
+    @TestApi
+    public static final int OPERATION_SET_USER_RESTRICTION = 10;
 
     private static final String PREFIX_OPERATION = "OPERATION_";
 
@@ -2620,7 +2634,11 @@
             OPERATION_START_USER_IN_BACKGROUND,
             OPERATION_STOP_USER,
             OPERATION_CREATE_AND_MANAGE_USER,
-            OPERATION_REMOVE_USER
+            OPERATION_REMOVE_USER,
+            OPERATION_REBOOT,
+            OPERATION_WIPE_DATA,
+            OPERATION_LOGOUT_USER,
+            OPERATION_SET_USER_RESTRICTION
     })
     @Retention(RetentionPolicy.SOURCE)
     public static @interface DevicePolicyOperation {
@@ -2915,22 +2933,36 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
-     * profile.
+     * profile. Apps targeting {@link android.os.Build.VERSION_CODES#S} and above will get a
+     * {@code IllegalArgumentException} when calling this method on the parent
+     * {@link DevicePolicyManager} instance.
      *
      * <p><strong>Note:</strong> Specifying password requirements using this method clears the
      * password complexity requirements set using {@link #setRequiredPasswordComplexity(int)}.
      *
+     * @deprecated Prefer using {@link #setRequiredPasswordComplexity(int)}, to require a password
+     * that satisfies a complexity level defined by the platform, rather than specifying custom
+     * password requirement.
+     * Setting custom, overly-complicated password requirements leads to passwords that are hard
+     * for users to remember and may not provide any security benefits given as Android uses
+     * hardware-backed throttling to thwart online and offline brute-forcing of the device's
+     * screen lock.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED},
      *            {@link #PASSWORD_QUALITY_BIOMETRIC_WEAK},
      *            {@link #PASSWORD_QUALITY_SOMETHING}, {@link #PASSWORD_QUALITY_NUMERIC},
      *            {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC},
      *            {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}.
-     * @throws SecurityException if {@code admin} is not an active administrator or if {@code admin}
-     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
+     * @throws SecurityException if {@code admin} is not an active administrator, if {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} or if the
+     *             calling app is targeting {@link android.os.Build.VERSION_CODES#S} and above,
+     *             and is calling the method the {@link DevicePolicyManager} instance returned by
+     *             {@link #getParentProfileInstance(ComponentName)}.
      */
+    @Deprecated
     public void setPasswordQuality(@NonNull ComponentName admin, int quality) {
         if (mService != null) {
             try {
@@ -2953,9 +2985,12 @@
      * <p>Note: on devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
      * the password is always treated as empty.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      * all admins.
      */
+    @Deprecated
     public int getPasswordQuality(@Nullable ComponentName admin) {
         return getPasswordQuality(admin, myUserId());
     }
@@ -2995,10 +3030,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum password length. A value of 0 means there is no
      *     restriction.
@@ -3008,6 +3047,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3030,9 +3070,12 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      * all admins.
      */
+    @Deprecated
     public int getPasswordMinimumLength(@Nullable ComponentName admin) {
         return getPasswordMinimumLength(admin, myUserId());
     }
@@ -3070,10 +3113,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of upper case letters required in the password.
      *            A value of 0 means there is no restriction.
@@ -3083,6 +3130,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3110,11 +3158,14 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of upper case letters required in the
      *         password.
      */
+    @Deprecated
     public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
         return getPasswordMinimumUpperCase(admin, myUserId());
     }
@@ -3152,10 +3203,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of lower case letters required in the password.
      *            A value of 0 means there is no restriction.
@@ -3165,6 +3220,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3192,11 +3248,14 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of lower case letters required in the
      *         password.
      */
+    @Deprecated
     public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
         return getPasswordMinimumLowerCase(admin, myUserId());
     }
@@ -3234,10 +3293,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of letters required in the password. A value of
      *            0 means there is no restriction.
@@ -3247,6 +3310,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3274,10 +3338,13 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of letters required in the password.
      */
+    @Deprecated
     public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
         return getPasswordMinimumLetters(admin, myUserId());
     }
@@ -3315,10 +3382,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of numerical digits required in the password. A
      *            value of 0 means there is no restriction.
@@ -3328,6 +3399,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3355,10 +3427,13 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of numerical digits required in the password.
      */
+    @Deprecated
     public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
         return getPasswordMinimumNumeric(admin, myUserId());
     }
@@ -3396,10 +3471,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of symbols required in the password. A value of
      *            0 means there is no restriction.
@@ -3409,6 +3488,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3435,10 +3515,13 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of symbols required in the password.
      */
+    @Deprecated
     public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
         return getPasswordMinimumSymbols(admin, myUserId());
     }
@@ -3476,10 +3559,14 @@
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
      * <p>
-     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     *
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
+     * {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param length The new desired minimum number of letters required in the password. A value of
      *            0 means there is no restriction.
@@ -3489,6 +3576,7 @@
      *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
      *     quality requirement prior to calling this method.
      */
+    @Deprecated
     public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -3516,10 +3604,13 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details.
+     *
      * @param admin The name of the admin component to check, or {@code null} to
      *            aggregate all admins.
      * @return The minimum number of letters required in the password.
      */
+    @Deprecated
     public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
         return getPasswordMinimumNonLetter(admin, myUserId());
     }
@@ -5758,7 +5849,6 @@
         return null;
     }
 
-
     /**
      * Called by a device or profile owner, or delegated certificate chooser (an app that has been
      * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to grant an application access
@@ -5796,6 +5886,51 @@
 
     /**
      * Called by a device or profile owner, or delegated certificate chooser (an app that has been
+     * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to query which apps have access
+     * to a given KeyChain key.
+     *
+     * Key are granted on a per-UID basis, so if several apps share the same UID, granting access to
+     * one of them automatically grants it to others. This method returns a set of sets of package
+     * names, where each internal set contains all packages sharing the same UID. Grantee packages
+     * that don't share UID with other packages are represented by singleton sets.
+     *
+     * @param alias The alias of the key to grant access to.
+     * @return package names of apps that have access to a given key, grouped by UIDs
+     *
+     * @throws SecurityException if the caller is not a device owner, a profile owner or
+     *         delegated certificate chooser.
+     * @throws IllegalArgumentException if {@code alias} doesn't correspond to an existing key.
+     *
+     * @see #grantKeyPairToApp(ComponentName, String, String)
+     */
+    public @NonNull Set<Set<String>> getKeyPairGrants(@NonNull String alias) {
+        throwIfParentInstance("getKeyPairGrants");
+        try {
+            // Set of sets is flattened into a null-separated list.
+            final List<String> flattened =
+                    mService.getKeyPairGrants(mContext.getPackageName(), alias);
+            final Set<Set<String>> result = new HashSet<>();
+            Set<String> pkgsForOneUid = new HashSet<>();
+            for (final String pkg : flattened) {
+                if (pkg == null) {
+                    result.add(pkgsForOneUid);
+                    pkgsForOneUid = new HashSet<>();
+                } else {
+                    pkgsForOneUid.add(pkg);
+                }
+            }
+            if (!pkgsForOneUid.isEmpty()) {
+                result.add(pkgsForOneUid);
+            }
+            return result;
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return null;
+    }
+
+    /**
+     * Called by a device or profile owner, or delegated certificate chooser (an app that has been
      * delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to revoke an application's
      * grant to a KeyChain key pair.
      * Calls by the application to {@link android.security.KeyChain#getPrivateKey}
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index c02fcab..ce2fd4f 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -237,4 +237,16 @@
      * Returns whether the given package is a device owner or a profile owner in the calling user.
      */
     public abstract boolean isDeviceOrProfileOwnerInCallingUser(String packageName);
+
+    /**
+     * Returns whether this class supports being deferred the responsibility for resetting the given
+     * op.
+     */
+    public abstract boolean supportsResetOp(int op);
+
+    /**
+     * Resets the given op across the profile group of the given user for the given package. Assumes
+     * {@link #supportsResetOp(int)} is true.
+     */
+    public abstract void resetOp(int op, String packageName, @UserIdInt int userId);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e21fee2..bcc90f7 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -471,6 +471,7 @@
     boolean startViewCalendarEventInManagedProfile(String packageName, long eventId, long start, long end, boolean allDay, int flags);
 
     boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant);
+    List<String> getKeyPairGrants(in String callerPackage, in String alias);
 
     void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages);
 
diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS
new file mode 100644
index 0000000..8462cbe
--- /dev/null
+++ b/core/java/android/app/admin/OWNERS
@@ -0,0 +1,11 @@
+# Bug component: 142675
+
+# Android Enterprise team
+rubinxu@google.com
+sandness@google.com
+eranm@google.com
+alexkershaw@google.com
+pgrafov@google.com
+
+# Emeritus
+yamasani@google.com
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/app/assist/OWNERS
@@ -0,0 +1,7 @@
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
new file mode 100644
index 0000000..482abb2
--- /dev/null
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 643919
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index e870597..95739f3 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -17,6 +17,7 @@
 package android.app.people;
 
 import android.annotation.NonNull;
+import android.app.Person;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutInfo;
@@ -28,7 +29,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
@@ -45,10 +45,14 @@
     private int mUid;
     private Uri mContactUri;
     private String mPackageName;
+    private String mStatusText;
     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
 
@@ -59,10 +63,13 @@
         mContactUri = b.mContactUri;
         mUid = b.mUid;
         mPackageName = b.mPackageName;
+        mStatusText = b.mStatusText;
         mLastInteractionTimestamp = b.mLastInteractionTimestamp;
         mIsImportantConversation = b.mIsImportantConversation;
         mIsHiddenConversation = b.mIsHiddenConversation;
-        mNotification = b.mNotification;
+        mNotificationKey = b.mNotificationKey;
+        mNotificationContent = b.mNotificationContent;
+        mNotificationDataUri = b.mNotificationDataUri;
         mIntent = b.mIntent;
     }
 
@@ -91,6 +98,10 @@
         return mPackageName;
     }
 
+    public String getStatusText() {
+        return mStatusText;
+    }
+
     /** Returns the timestamp of the last interaction. */
     public long getLastInteractionTimestamp() {
         return mLastInteractionTimestamp;
@@ -112,10 +123,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 +148,23 @@
         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.setStatusText(mStatusText);
+        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;
@@ -137,10 +173,13 @@
         private Uri mContactUri;
         private int mUid;
         private String mPackageName;
+        private String mStatusText;
         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. */
@@ -158,6 +197,16 @@
             mUserIcon = convertDrawableToIcon(launcherApps.getShortcutIconDrawable(info, 0));
             mUid = info.getUserId();
             mPackageName = info.getPackage();
+            mContactUri = getContactUri(info);
+        }
+
+        private Uri getContactUri(ShortcutInfo info) {
+            if (info.getPersons() == null || info.getPersons().length != 1) {
+                return null;
+            }
+            // TODO(b/175584929): Update to use the Uri from PeopleService directly
+            Person person = info.getPersons()[0];
+            return person.getUri() == null ? null : Uri.parse(person.getUri());
         }
 
         /** Sets the ID for the tile. */
@@ -196,6 +245,12 @@
             return this;
         }
 
+        /** Sets the status text. */
+        public Builder setStatusText(String statusText) {
+            mStatusText = statusText;
+            return this;
+        }
+
         /** Sets the last interaction timestamp. */
         public Builder setLastInteractionTimestamp(long lastInteractionTimestamp) {
             mLastInteractionTimestamp = lastInteractionTimestamp;
@@ -214,9 +269,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;
         }
 
@@ -237,12 +304,16 @@
         mId = in.readString();
         mUserName = in.readCharSequence();
         mUserIcon = in.readParcelable(Icon.class.getClassLoader());
+        mContactUri = in.readParcelable(Uri.class.getClassLoader());
         mUid = in.readInt();
         mPackageName = in.readString();
+        mStatusText = in.readString();
         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());
     }
 
@@ -256,12 +327,16 @@
         dest.writeString(mId);
         dest.writeCharSequence(mUserName);
         dest.writeParcelable(mUserIcon, flags);
+        dest.writeParcelable(mContactUri, flags);
         dest.writeInt(mUid);
         dest.writeString(mPackageName);
+        dest.writeString(mStatusText);
         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/prediction/OWNERS b/core/java/android/app/prediction/OWNERS
new file mode 100644
index 0000000..fe012da
--- /dev/null
+++ b/core/java/android/app/prediction/OWNERS
@@ -0,0 +1,2 @@
+adamcohen@google.com
+sunnygoyal@google.com
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/OWNERS b/core/java/android/app/role/OWNERS
index b94d988..b8076366 100644
--- a/core/java/android/app/role/OWNERS
+++ b/core/java/android/app/role/OWNERS
@@ -1,6 +1,4 @@
-svetoslavganov@google.com
-moltmann@google.com
+# Bug component: 137825
+
 zhanghai@google.com
-evanseverson@google.com
-eugenesusla@google.com
-ntmyren@google.com
+moltmann@google.com
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/core/java/android/app/role/RolePrivileges.aidl b/core/java/android/app/role/RolePrivileges.aidl
new file mode 100644
index 0000000..1561ad4
--- /dev/null
+++ b/core/java/android/app/role/RolePrivileges.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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;
+
+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/app/search/ISearchCallback.aidl b/core/java/android/app/search/ISearchCallback.aidl
new file mode 100644
index 0000000..a10bffc
--- /dev/null
+++ b/core/java/android/app/search/ISearchCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.search;
+
+import android.content.pm.ParceledListSlice;
+
+/**
+ * @hide
+ */
+oneway interface ISearchCallback {
+
+    void onResult(in ParceledListSlice result);
+}
diff --git a/core/java/android/app/search/ISearchUiManager.aidl b/core/java/android/app/search/ISearchUiManager.aidl
new file mode 100644
index 0000000..a298a2c
--- /dev/null
+++ b/core/java/android/app/search/ISearchUiManager.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.search;
+
+import android.app.search.Query;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.app.search.SearchSessionId;
+import android.app.search.SearchContext;
+import android.app.search.ISearchCallback;
+import android.content.pm.ParceledListSlice;
+
+/**
+ * @hide
+ */
+interface ISearchUiManager {
+
+    void createSearchSession(in SearchContext context, in SearchSessionId sessionId,
+            in IBinder token);
+
+    void query(in SearchSessionId sessionId, in Query input, in ISearchCallback callback);
+
+    void notifyEvent(in SearchSessionId sessionId, in Query input, in SearchTargetEvent event);
+
+    void destroySearchSession(in SearchSessionId sessionId);
+}
diff --git a/core/java/android/app/search/Query.aidl b/core/java/android/app/search/Query.aidl
new file mode 100644
index 0000000..6c13d98
--- /dev/null
+++ b/core/java/android/app/search/Query.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.search;
+
+parcelable Query;
\ No newline at end of file
diff --git a/core/java/android/app/search/Query.java b/core/java/android/app/search/Query.java
new file mode 100644
index 0000000..447ca31
--- /dev/null
+++ b/core/java/android/app/search/Query.java
@@ -0,0 +1,102 @@
+/*
+ * 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.search;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public final class Query implements Parcelable {
+
+    /**
+     * Query string typed from the client.
+     */
+    @NonNull
+    private final String mInput;
+
+    /**
+     * The timestamp that the query string was typed. If this object was created for the
+     * {@link SearchSession#query}, the client expects first consumer to be returned
+     * within mTimestamp + {@link SearchContext#mTimeoutMillis}
+     */
+    private final long mTimestamp;
+
+    @Nullable
+    private final Bundle mExtras;
+
+    public Query(@NonNull String input,
+            long timestamp,
+            @Nullable Bundle extras) {
+        mInput = input;
+        mTimestamp = timestamp;
+        mExtras = extras;
+    }
+
+    private Query(Parcel parcel) {
+        mInput = parcel.readString();
+        mTimestamp = parcel.readLong();
+        mExtras = parcel.readBundle();
+    }
+
+    @NonNull
+    public String getInput() {
+        return mInput;
+    }
+
+    @NonNull
+    public long getTimestamp() {
+        return mTimestamp;
+    }
+
+    @Nullable
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mInput);
+        dest.writeLong(mTimestamp);
+        dest.writeBundle(mExtras);
+    }
+
+    /**
+     * @see Creator
+     */
+    @NonNull
+    public static final Creator<Query> CREATOR =
+            new Creator<Query>() {
+                public Query createFromParcel(Parcel parcel) {
+                    return new Query(parcel);
+                }
+
+                public Query[] newArray(int size) {
+                    return new Query[size];
+                }
+            };
+}
diff --git a/core/java/android/app/search/SearchAction.java b/core/java/android/app/search/SearchAction.java
new file mode 100644
index 0000000..158f9f3
--- /dev/null
+++ b/core/java/android/app/search/SearchAction.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.search;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * Represents a searchable action info that can be called from another process
+ * or within the client process.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchAction implements Parcelable {
+
+    private static final String TAG = "SearchAction";
+
+    @NonNull
+    private String mId;
+
+    @Nullable
+    private final Icon mIcon;
+
+    @NonNull
+    private final CharSequence mTitle;
+
+    @Nullable
+    private final CharSequence mSubtitle;
+
+    @Nullable
+    private final CharSequence mContentDescription;
+
+    @Nullable
+    private final PendingIntent mPendingIntent;
+
+    @Nullable
+    private final Intent mIntent;
+
+    @Nullable
+    private final UserHandle mUserHandle;
+
+    @Nullable
+    private Bundle mExtras;
+
+    SearchAction(Parcel in) {
+        mId = in.readString();
+        mIcon = Icon.CREATOR.createFromParcel(in);
+        mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mPendingIntent = PendingIntent.CREATOR.createFromParcel(in);
+        mIntent = Intent.CREATOR.createFromParcel(in);
+        mUserHandle = in.readTypedObject(UserHandle.CREATOR);
+        mExtras = in.readBundle();
+    }
+
+    private SearchAction(
+            @NonNull String id,
+            @Nullable Icon icon,
+            @NonNull CharSequence title,
+            @Nullable CharSequence subtitle,
+            @Nullable CharSequence contentDescription,
+            @Nullable PendingIntent pendingIntent,
+            @Nullable Intent intent,
+            @Nullable UserHandle userHandle,
+            @Nullable Bundle extras) {
+        mId = Objects.requireNonNull(id);
+        mIcon = icon;
+        mTitle = Objects.requireNonNull(title);
+        mSubtitle = subtitle;
+        mContentDescription = contentDescription;
+        mPendingIntent = pendingIntent;
+        mIntent = intent;
+        mUserHandle = userHandle;
+        mExtras = extras;
+
+        if (mPendingIntent == null && mIntent == null) {
+            throw new IllegalStateException("At least one type of intent should be available.");
+        }
+        if (mPendingIntent != null && mIntent != null) {
+            throw new IllegalStateException("Only one type of intent should be available.");
+        }
+    }
+
+    /**
+     * Returns the unique id of this object.
+     */
+    public @NonNull String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns an icon representing the action.
+     */
+    public @Nullable Icon getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * Returns a title representing the action.
+     */
+    public @NonNull CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns a subtitle representing the action.
+     */
+    public @Nullable CharSequence getSubtitle() {
+        return mSubtitle;
+    }
+
+    /**
+     * Returns a content description representing the action.
+     */
+    public @Nullable CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
+     * Returns the action intent.
+     */
+    public @Nullable PendingIntent getPendingIntent() {
+        return mPendingIntent;
+    }
+
+    /**
+     * Returns the intent.
+     */
+    public @Nullable Intent getIntent() {
+        return mIntent;
+    }
+
+    /**
+     * Returns the user handle.
+     */
+    public @Nullable UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
+    /**
+     * Returns the extra bundle for this object.
+     */
+    public @Nullable Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SearchAction)) return false;
+        SearchAction that = (SearchAction) o;
+        return mId.equals(that.mId) && mTitle.equals(that.mTitle);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mTitle);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeString(mId);
+        out.writeTypedObject(mIcon, flags);
+        TextUtils.writeToParcel(mTitle, out, flags);
+        TextUtils.writeToParcel(mSubtitle, out, flags);
+        TextUtils.writeToParcel(mContentDescription, out, flags);
+        out.writeTypedObject(mPendingIntent, flags);
+        out.writeTypedObject(mIntent, flags);
+        out.writeTypedObject(mUserHandle, flags);
+        out.writeBundle(mExtras);
+    }
+
+    @Override
+    public String toString() {
+        String str = "id=" + mId
+                + " title=" + mTitle
+                + " contentDescription=" + mContentDescription
+                + " subtitle=" + mSubtitle
+                + " icon=" + mIcon
+                + " pendingIntent=" + (mPendingIntent == null ? "" : mPendingIntent.getIntent())
+                + " intent=" + mIntent
+                + " userHandle=" + mUserHandle;
+        return str;
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<SearchAction> CREATOR =
+            new Parcelable.Creator<SearchAction>() {
+                public SearchAction createFromParcel(Parcel in) {
+                    return new SearchAction(in);
+                }
+                public SearchAction[] newArray(int size) {
+                    return new SearchAction[size];
+                }
+            };
+
+    /**
+     * A builder for search action object.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class Builder {
+        @NonNull
+        private String mId;
+
+        @Nullable
+        private Icon mIcon;
+
+        @NonNull
+        private CharSequence mTitle;
+
+        @Nullable
+        private CharSequence mSubtitle;
+
+        @Nullable
+        private CharSequence mContentDescription;
+
+        @Nullable
+        private PendingIntent mPendingIntent;
+
+        @Nullable
+        private Intent mIntent;
+
+        @Nullable
+        private UserHandle mUserHandle;
+
+        @Nullable
+        private Bundle mExtras;
+
+        public Builder(@NonNull String id, @NonNull String title) {
+            mId = Objects.requireNonNull(id);
+            mTitle = Objects.requireNonNull(title);
+        }
+
+        /**
+         * Sets the subtitle.
+         */
+        @NonNull
+        public SearchAction.Builder setIcon(
+                @Nullable Icon icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /**
+         * Sets the subtitle.
+         */
+        @NonNull
+        public SearchAction.Builder setSubtitle(
+                @Nullable CharSequence subtitle) {
+            mSubtitle = subtitle;
+            return this;
+        }
+
+        /**
+         * Sets the content description.
+         */
+        @NonNull
+        public SearchAction.Builder setContentDescription(
+                @Nullable CharSequence contentDescription) {
+            mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the pending intent.
+         */
+        @NonNull
+        public SearchAction.Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
+            mPendingIntent = pendingIntent;
+            return this;
+        }
+
+        /**
+         * Sets the user handle.
+         */
+        @NonNull
+        public SearchAction.Builder setUserHandle(@Nullable UserHandle userHandle) {
+            mUserHandle = userHandle;
+            return this;
+        }
+
+        /**
+         * Sets the intent.
+         */
+        @NonNull
+        public SearchAction.Builder setIntent(@Nullable Intent intent) {
+            mIntent = intent;
+            return this;
+        }
+
+        /**
+         * Sets the extra.
+         */
+        @NonNull
+        public SearchAction.Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Builds a new SearchAction instance.
+         *
+         * @throws IllegalStateException if no target is set
+         */
+        @NonNull
+        public SearchAction build() {
+            return new SearchAction(mId, mIcon, mTitle, mSubtitle, mContentDescription,
+                    mPendingIntent, mIntent, mUserHandle, mExtras);
+        }
+    }
+}
diff --git a/core/java/android/app/search/SearchContext.aidl b/core/java/android/app/search/SearchContext.aidl
new file mode 100644
index 0000000..c9442b8
--- /dev/null
+++ b/core/java/android/app/search/SearchContext.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.search;
+
+parcelable SearchContext;
\ No newline at end of file
diff --git a/core/java/android/app/search/SearchContext.java b/core/java/android/app/search/SearchContext.java
new file mode 100644
index 0000000..9bf766d
--- /dev/null
+++ b/core/java/android/app/search/SearchContext.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.search;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public final class SearchContext implements Parcelable {
+
+    /**
+     * Result types the client UI is expecting the service to return.
+     */
+    private final int mResultTypes;
+
+    /**
+     * Timeout constraint imposed from the client UI for the first search result.
+     */
+    private final int mTimeoutMillis;
+
+    /**
+     * Send other client UI configurations in extras.
+     */
+    @Nullable
+    private final Bundle mExtras;
+
+    /**
+     * Package name of the client.
+     */
+    @Nullable
+    private String mPackageName;
+
+    public SearchContext(int resultTypes,
+            int queryTimeoutMillis,
+            @Nullable Bundle extras) {
+        mResultTypes = resultTypes;
+        mTimeoutMillis = queryTimeoutMillis;
+        mExtras = extras;
+    }
+
+    private SearchContext(Parcel parcel) {
+        mResultTypes = parcel.readInt();
+        mTimeoutMillis = parcel.readInt();
+        mPackageName = parcel.readString();
+        mExtras = parcel.readBundle();
+    }
+
+    @Nullable
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * @hide
+     */
+    public void setPackageName(@Nullable String packageName) {
+        mPackageName = packageName;
+    }
+
+    @NonNull
+    public int getTimeoutMillis() {
+        return mTimeoutMillis;
+    }
+
+    @Nullable
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @NonNull
+    public int getResultTypes() {
+        return mResultTypes;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mResultTypes);
+        dest.writeInt(mTimeoutMillis);
+        dest.writeString(mPackageName);
+        dest.writeBundle(mExtras);
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    @NonNull
+    public static final Parcelable.Creator<SearchContext> CREATOR =
+            new Parcelable.Creator<SearchContext>() {
+                public SearchContext createFromParcel(Parcel parcel) {
+                    return new SearchContext(parcel);
+                }
+
+                public SearchContext[] newArray(int size) {
+                    return new SearchContext[size];
+                }
+            };
+}
diff --git a/core/java/android/app/search/SearchSession.java b/core/java/android/app/search/SearchSession.java
new file mode 100644
index 0000000..7bd88d9
--- /dev/null
+++ b/core/java/android/app/search/SearchSession.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 android.app.search;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.search.ISearchCallback.Stub;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import dalvik.system.CloseGuard;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
+/**
+ * Client API to share information about the search UI state and execute query.
+ *
+ * <p>
+ * Usage: <pre> {@code
+ *
+ * class MyActivity {
+ *
+ *    void onCreate() {
+ *         mSearchSession.createSearchSession(searchContext)
+ *    }
+ *
+ *    void afterTextChanged(...) {
+ *        mSearchSession.query(...);
+ *    }
+ *
+ *    void onTouch(...) OR
+ *    void onStateTransitionStarted(...) OR
+ *    void onResume(...) OR
+ *    void onStop(...) {
+ *        mSearchSession.notifyEvent(event);
+ *    }
+ *
+ *    void onDestroy() {
+ *        mSearchSession.destroy();
+ *    }
+ *
+ * }</pre>
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchSession implements AutoCloseable{
+
+    private static final String TAG = SearchSession.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private final android.app.search.ISearchUiManager mInterface;
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
+
+    private final SearchSessionId mSessionId;
+    private final IBinder mToken = new Binder();
+
+    /**
+     * Creates a new search ui client.
+     * <p>
+     * The caller should call {@link SearchSession#destroy()} to dispose the client once it
+     * no longer used.
+     *
+     * @param context       the {@link Context} of the user of this {@link SearchSession}.
+     * @param searchContext the search context.
+     */
+    // b/175668315 Create weak reference child objects to not leak context.
+    SearchSession(@NonNull Context context, @NonNull SearchContext searchContext) {
+        IBinder b = ServiceManager.getService(Context.SEARCH_UI_SERVICE);
+        mInterface = android.app.search.ISearchUiManager.Stub.asInterface(b);
+        mSessionId = new SearchSessionId(
+                context.getPackageName() + ":" + UUID.randomUUID().toString(), context.getUserId());
+        // b/175527717 whitelist possible clients of this API
+        searchContext.setPackageName(context.getPackageName());
+        try {
+            mInterface.createSearchSession(searchContext, mSessionId, mToken);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to search session", e);
+            e.rethrowFromSystemServer();
+        }
+
+        mCloseGuard.open("close");
+    }
+
+    /**
+     * Notifies the search service of an search target event.
+     *
+     * @param query input object associated with the event.
+     * @param event The {@link SearchTargetEvent} that represents the search target event.
+     */
+    public void notifyEvent(@NonNull Query query, @NonNull SearchTargetEvent event) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mInterface.notifyEvent(mSessionId, query, event);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to notify event", e);
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls consumer with list of {@link SearchTarget}s based on the input query.
+     *
+     * @param input query object to be used for the request.
+     * @param callbackExecutor The callback executor to use when calling the callback.
+     * @param callback The callback to return the list of search targets.
+     */
+    @Nullable
+    public void query(@NonNull Query input,
+            @NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull Consumer<List<SearchTarget>> callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+
+            mInterface.query(mSessionId, input, new CallbackWrapper(callbackExecutor, callback));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to sort targets", e);
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Destroys the client and unregisters the callback. Any method on this class after this call
+     * will throw {@link IllegalStateException}.
+     */
+    public void destroy() {
+        if (!mIsClosed.getAndSet(true)) {
+            mCloseGuard.close();
+
+            // Do destroy;
+            try {
+                mInterface.destroySearchSession(mSessionId);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to notify search target event", e);
+                e.rethrowFromSystemServer();
+            }
+        } else {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+    }
+
+    @Override
+    protected void finalize() {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            if (!mIsClosed.get()) {
+                destroy();
+            }
+        } finally {
+            try {
+                super.finalize();
+            } catch (Throwable throwable) {
+                throwable.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public void close() {
+        try {
+            finalize();
+        } catch (Throwable throwable) {
+            throwable.printStackTrace();
+        }
+    }
+
+    static class CallbackWrapper extends Stub {
+
+        private final Consumer<List<SearchTarget>> mCallback;
+        private final Executor mExecutor;
+
+        CallbackWrapper(@NonNull Executor callbackExecutor,
+                @NonNull Consumer<List<SearchTarget>> callback) {
+            mCallback = callback;
+            mExecutor = callbackExecutor;
+        }
+
+        @Override
+        public void onResult(ParceledListSlice result) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "CallbackWrapper.onResult result=" + result.getList());
+                }
+                mExecutor.execute(() -> mCallback.accept(result.getList()));
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+}
diff --git a/core/java/android/app/search/SearchSessionId.aidl b/core/java/android/app/search/SearchSessionId.aidl
new file mode 100644
index 0000000..d390136
--- /dev/null
+++ b/core/java/android/app/search/SearchSessionId.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.search;
+
+parcelable SearchSessionId;
\ No newline at end of file
diff --git a/core/java/android/app/search/SearchSessionId.java b/core/java/android/app/search/SearchSessionId.java
new file mode 100644
index 0000000..03bf1a1
--- /dev/null
+++ b/core/java/android/app/search/SearchSessionId.java
@@ -0,0 +1,99 @@
+/*
+ * 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.search;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The id for an search session. See {@link SearchSession}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchSessionId implements Parcelable {
+
+    private final String mId;
+    private final int mUserId;
+
+    /**
+     * Creates a new id for a search session.
+     *
+     * @hide
+     */
+    public SearchSessionId(@NonNull final String id, final int userId) {
+        mId = id;
+        mUserId = userId;
+    }
+
+    private SearchSessionId(Parcel p) {
+        mId = p.readString();
+        mUserId = p.readInt();
+    }
+
+    /**
+     * @hide
+     */
+    public int getUserId() {
+        return mUserId;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        SearchSessionId other = (SearchSessionId) o;
+        return mId.equals(other.mId) && mUserId == other.mUserId;
+    }
+
+    @Override
+    public @NonNull String toString() {
+        return mId + "," + mUserId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mUserId);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mId);
+        dest.writeInt(mUserId);
+    }
+
+    public static final @NonNull Creator<SearchSessionId> CREATOR =
+            new Creator<SearchSessionId>() {
+                public SearchSessionId createFromParcel(Parcel parcel) {
+                    return new SearchSessionId(parcel);
+                }
+
+                public SearchSessionId[] newArray(int size) {
+                    return new SearchSessionId[size];
+                }
+            };
+}
diff --git a/core/java/android/app/search/SearchTarget.aidl b/core/java/android/app/search/SearchTarget.aidl
new file mode 100644
index 0000000..0d3d5d33
--- /dev/null
+++ b/core/java/android/app/search/SearchTarget.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.search;
+
+parcelable SearchTarget;
\ No newline at end of file
diff --git a/core/java/android/app/search/SearchTarget.java b/core/java/android/app/search/SearchTarget.java
new file mode 100644
index 0000000..cac22d81
--- /dev/null
+++ b/core/java/android/app/search/SearchTarget.java
@@ -0,0 +1,425 @@
+/*
+ * 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.search;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+import java.util.Objects;
+
+/**
+ * A representation of a searchable item info.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchTarget implements Parcelable {
+
+
+    @NonNull
+    private final int mResultType;
+
+    /**
+     * Constant to express how the group of {@link SearchTarget} should be laid out.
+     */
+    @NonNull
+    private final String mLayoutType;
+
+    @NonNull
+    private final String mId;
+
+    @Nullable
+    private String mParentId;
+
+    private final float mScore;
+
+    private final boolean mShouldHide;
+
+    @NonNull
+    private final String mPackageName;
+    @NonNull
+    private final UserHandle mUserHandle;
+    @Nullable
+    private final SearchAction mSearchAction;
+    @Nullable
+    private final ShortcutInfo mShortcutInfo;
+    @Nullable
+    private final AppWidgetProviderInfo mAppWidgetProviderInfo;
+    @Nullable
+    private final Uri mSliceUri;
+    @Nullable
+    private final Bundle mExtras;
+
+    private SearchTarget(Parcel parcel) {
+        mResultType = parcel.readInt();
+        mLayoutType = parcel.readString();
+
+        mId = parcel.readString();
+        mParentId = parcel.readString();
+        mScore = parcel.readFloat();
+        mShouldHide = parcel.readBoolean();
+
+        mPackageName = parcel.readString();
+        mUserHandle = UserHandle.of(parcel.readInt());
+        mSearchAction = parcel.readTypedObject(SearchAction.CREATOR);
+        mShortcutInfo = parcel.readTypedObject(ShortcutInfo.CREATOR);
+        mAppWidgetProviderInfo = parcel.readTypedObject(AppWidgetProviderInfo.CREATOR);
+        mSliceUri = parcel.readTypedObject(Uri.CREATOR);
+        mExtras = parcel.readBundle(getClass().getClassLoader());
+    }
+
+    private SearchTarget(
+            int resultType,
+            @NonNull String layoutType,
+            @NonNull String id,
+            @Nullable String parentId,
+            float score, boolean shouldHide,
+            @NonNull String packageName,
+            @NonNull UserHandle userHandle,
+            @Nullable SearchAction action,
+            @Nullable ShortcutInfo shortcutInfo,
+            @Nullable Uri sliceUri,
+            @Nullable AppWidgetProviderInfo appWidgetProviderInfo,
+            @Nullable Bundle extras) {
+        mResultType = resultType;
+        mLayoutType = Objects.requireNonNull(layoutType);
+        mId = Objects.requireNonNull(id);
+        mParentId = parentId;
+        mScore = score;
+        mShouldHide = shouldHide;
+        mPackageName = Objects.requireNonNull(packageName);
+        mUserHandle = Objects.requireNonNull(userHandle);
+        mSearchAction = action;
+        mShortcutInfo = shortcutInfo;
+        mAppWidgetProviderInfo = appWidgetProviderInfo;
+        mSliceUri = sliceUri;
+        mExtras = extras;
+
+        int published = 0;
+        if (mSearchAction != null) published++;
+        if (mShortcutInfo != null) published++;
+        if (mAppWidgetProviderInfo != null) published++;
+        if (mSliceUri != null) published++;
+        if (published > 1) {
+            throw new IllegalStateException("Only one of SearchAction, ShortcutInfo,"
+                    + " AppWidgetProviderInfo, SliceUri can be assigned in a SearchTarget.");
+        }
+    }
+
+    /**
+     * Retrieves the result type.
+     */
+    public int getResultType() {
+        return mResultType;
+    }
+
+    /**
+     * Retrieves the layout type.
+     */
+    @NonNull
+    public String getLayoutType() {
+        return mLayoutType;
+    }
+
+    /**
+     * Retrieves the id of the target.
+     */
+    @NonNull
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Retrieves the parent id of the target.
+     */
+    @NonNull
+    public String getParentId() {
+        return mParentId;
+    }
+
+    /**
+     * Retrieves the score of the target.
+     */
+    public float getScore() {
+        return mScore;
+    }
+
+    /**
+     * TODO: add comment
+     */
+    public boolean shouldHide() {
+        return mShouldHide;
+    }
+
+    /**
+     * Retrieves the package name of the target.
+     */
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Retrieves the user handle of the target.
+     */
+    @NonNull
+    public UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
+    /**
+     * Retrieves the shortcut info of the target.
+     */
+    @Nullable
+    public ShortcutInfo getShortcutInfo() {
+        return mShortcutInfo;
+    }
+
+    /**
+     * Return widget provider info.
+     */
+    @Nullable
+    public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+        return mAppWidgetProviderInfo;
+    }
+
+    /**
+     * Return slice uri.
+     */
+    @Nullable
+    public Uri getSliceUri() {
+        return mSliceUri;
+    }
+
+    /**
+     * Return search action.
+     */
+    @Nullable
+    public SearchAction getSearchAction() {
+        return mSearchAction;
+    }
+
+    /**
+     * Return extra bundle.
+     */
+    @Nullable
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
+        parcel.writeInt(mResultType);
+        parcel.writeString(mLayoutType);
+        parcel.writeString(mId);
+        parcel.writeString(mParentId);
+        parcel.writeFloat(mScore);
+        parcel.writeBoolean(mShouldHide);
+        parcel.writeString(mPackageName);
+        parcel.writeInt(mUserHandle.getIdentifier());
+        parcel.writeTypedObject(mSearchAction, flags);
+        parcel.writeTypedObject(mShortcutInfo, flags);
+        parcel.writeTypedObject(mAppWidgetProviderInfo, flags);
+        parcel.writeTypedObject(mSliceUri, flags);
+        parcel.writeBundle(mExtras);
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    @NonNull
+    public static final Parcelable.Creator<SearchTarget> CREATOR =
+            new Parcelable.Creator<SearchTarget>() {
+                public SearchTarget createFromParcel(Parcel parcel) {
+                    return new SearchTarget(parcel);
+                }
+
+                public SearchTarget[] newArray(int size) {
+                    return new SearchTarget[size];
+                }
+            };
+
+    /**
+     * A builder for search target object.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class Builder {
+        private int mResultType;
+        @NonNull
+        private String mLayoutType;
+        @NonNull
+        private String mId;
+        @Nullable
+        private String mParentId;
+        private float mScore;
+        private boolean mShouldHide;
+        @NonNull
+        private String mPackageName;
+        @NonNull
+        private UserHandle mUserHandle;
+        @Nullable
+        private SearchAction mSearchAction;
+        @Nullable
+        private ShortcutInfo mShortcutInfo;
+        @Nullable
+        private Uri mSliceUri;
+        @Nullable
+        private AppWidgetProviderInfo mAppWidgetProviderInfo;
+        @Nullable
+        private Bundle mExtras;
+
+        public Builder(int resultType,
+                @NonNull String layoutType,
+                @NonNull String id) {
+            mId = id;
+            mLayoutType = Objects.requireNonNull(layoutType);
+            mResultType = resultType;
+            mScore = 1f;
+            mShouldHide = false;
+        }
+
+        /**
+         * Sets the parent id.
+         */
+        @NonNull
+        public Builder setParentId(@NonNull String parentId) {
+            mParentId = Objects.requireNonNull(parentId);
+            return this;
+        }
+
+        /**
+         * Sets the package name.
+         */
+        @NonNull
+        public Builder setPackageName(@NonNull String packageName) {
+            mPackageName = Objects.requireNonNull(packageName);
+            return this;
+        }
+
+        /**
+         * Sets the user handle.
+         */
+        @NonNull
+        public Builder setUserHandle(@NonNull UserHandle userHandle) {
+            mUserHandle = Objects.requireNonNull(userHandle);
+            return this;
+        }
+
+        /**
+         * Sets the shortcut info.
+         */
+        @NonNull
+        public Builder setShortcutInfo(@NonNull ShortcutInfo shortcutInfo) {
+            mShortcutInfo = Objects.requireNonNull(shortcutInfo);
+            if (mPackageName != null && !mPackageName.equals(shortcutInfo.getPackage())) {
+                throw new IllegalStateException("SearchTarget packageName is different from "
+                        + "shortcut's packageName");
+            }
+            mPackageName = shortcutInfo.getPackage();
+            return this;
+        }
+
+        /**
+         * Sets the app widget provider info.
+         */
+        @NonNull
+        public Builder setAppWidgetProviderInfo(
+                @NonNull AppWidgetProviderInfo appWidgetProviderInfo) {
+            mAppWidgetProviderInfo = Objects.requireNonNull(appWidgetProviderInfo);
+            if (mPackageName != null
+                    && !mPackageName.equals(appWidgetProviderInfo.provider.getPackageName())) {
+                throw new IllegalStateException("SearchTarget packageName is different from "
+                        + "appWidgetProviderInfo's packageName");
+            }
+            return this;
+        }
+
+        /**
+         * Sets the slice URI.
+         */
+        @NonNull
+        public Builder setSliceUri(@NonNull Uri sliceUri) {
+            // TODO: add packageName check
+            mSliceUri = sliceUri;
+            return this;
+        }
+
+        /**
+         * TODO: add comment
+         */
+        @NonNull
+        public Builder setSearchAction(@Nullable SearchAction remoteAction) {
+            // TODO: add packageName check
+            mSearchAction = remoteAction;
+            return this;
+        }
+
+        /**
+         * TODO: add comment
+         */
+        @NonNull
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * TODO: add comment
+         */
+        @NonNull
+        public Builder setScore(float score) {
+            mScore = score;
+            return this;
+        }
+
+        /**
+         * TODO: add comment
+         */
+        @NonNull
+        public Builder setShouldHide(boolean shouldHide) {
+            mShouldHide = shouldHide;
+            return this;
+        }
+
+        /**
+         * Builds a new SearchTarget instance.
+         *
+         * @throws IllegalStateException if no target is set
+         */
+        @NonNull
+        public SearchTarget build() {
+            return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mShouldHide,
+                    mPackageName, mUserHandle,
+                    mSearchAction, mShortcutInfo, mSliceUri, mAppWidgetProviderInfo,
+                    mExtras);
+        }
+    }
+}
diff --git a/core/java/android/app/search/SearchTargetEvent.aidl b/core/java/android/app/search/SearchTargetEvent.aidl
new file mode 100644
index 0000000..a7a8ea2
--- /dev/null
+++ b/core/java/android/app/search/SearchTargetEvent.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.search;
+
+parcelable SearchTargetEvent;
diff --git a/core/java/android/app/search/SearchTargetEvent.java b/core/java/android/app/search/SearchTargetEvent.java
new file mode 100644
index 0000000..f478dc3
--- /dev/null
+++ b/core/java/android/app/search/SearchTargetEvent.java
@@ -0,0 +1,267 @@
+/*
+ * 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.search;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A representation of an app target event.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchTargetEvent implements Parcelable {
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = {"ACTION_"}, value = {
+            ACTION_SURFACE_VISIBLE,
+            ACTION_TAP,
+            ACTION_LONGPRESS,
+            ACTION_LAUNCH_TOUCH,
+            ACTION_LAUNCH_KEYBOARD_FOCUS,
+            ACTION_DRAGNDROP,
+            ACTION_SURFACE_INVISIBLE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ActionType {}
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = {"FLAG_"}, value = {
+            FLAG_IME_SHOWN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FlagType {}
+
+    @NonNull
+    private final List<String> mTargetIds;
+    @Nullable
+    private final String mLocation;
+    @ActionType
+    private final int mAction;
+    @FlagType
+    private int mFlags;
+
+    /**
+     * IME was shown when event happened.
+     */
+    public static final int FLAG_IME_SHOWN = 1 << 0;
+
+
+    /**
+     * Search container was opened.
+     */
+    public static final int ACTION_SURFACE_VISIBLE = 1;
+
+    /**
+     * Constants that define tapping without closing the search surface.
+     */
+    public static final int ACTION_TAP = 3;
+
+    /**
+     * Constants that define long pressing without closing the search surface.
+     */
+    public static final int ACTION_LONGPRESS = 4;
+
+    /**
+     * Constants that define tapping on the touch target to launch.
+     */
+    public static final int ACTION_LAUNCH_TOUCH = 5;
+
+    /**
+     * Constants that define tapping on the soft keyboard confirm or search to launch.
+     */
+    public static final int ACTION_LAUNCH_KEYBOARD_FOCUS = 6;
+
+    /**
+     * Searcheable item was draged and dropped to another surface.
+     */
+    public static final int ACTION_DRAGNDROP = 7;
+
+    /**
+     * Search container was closed.
+     */
+    public static final int ACTION_SURFACE_INVISIBLE = 8;
+
+    private SearchTargetEvent(@NonNull List<String> targetIds,
+            @Nullable String location,
+            @ActionType int actionType,
+            @FlagType int flags) {
+        mTargetIds = Objects.requireNonNull(targetIds);
+        mLocation = location;
+        mAction = actionType;
+        mFlags = flags;
+    }
+
+    private SearchTargetEvent(Parcel parcel) {
+        mTargetIds = new ArrayList<>();
+        parcel.readStringList(mTargetIds);
+        mLocation = parcel.readString();
+        mAction = parcel.readInt();
+        mFlags = parcel.readInt();
+    }
+
+    /**
+     * Returns the primary search target with interaction.
+     */
+    @NonNull
+    public String getTargetId() {
+        return mTargetIds.get(0);
+    }
+
+    /**
+     * Returns the list of search targets with visualization change.
+     */
+    @NonNull
+    public List<String> getTargetIds() {
+        return mTargetIds;
+    }
+
+    /**
+     * Returns the launch location.
+     */
+    @Nullable
+    public String getLaunchLocation() {
+        return mLocation;
+    }
+
+    /**
+     * Returns the action type.
+     */
+    @ActionType
+    public int getAction() {
+        return mAction;
+    }
+
+    public int getFlags() {
+        return mFlags;
+    }
+
+    @Override
+    public int hashCode() {
+        return mTargetIds.get(0).hashCode() + mAction;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        SearchTargetEvent other = (SearchTargetEvent) o;
+        return mTargetIds.equals(other.mTargetIds)
+                && mAction == other.mAction
+                && mFlags == other.mFlags
+                && mLocation == null ? other.mLocation == null : mLocation.equals(other.mLocation);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeStringList(mTargetIds);
+        dest.writeString(mLocation);
+        dest.writeInt(mAction);
+        dest.writeInt(mFlags);
+    }
+
+    public static final @NonNull Creator<SearchTargetEvent> CREATOR =
+            new Creator<SearchTargetEvent>() {
+                public SearchTargetEvent createFromParcel(Parcel parcel) {
+                    return new SearchTargetEvent(parcel);
+                }
+
+                public SearchTargetEvent[] newArray(int size) {
+                    return new SearchTargetEvent[size];
+                }
+            };
+
+    /**
+     * A builder for search target events.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class Builder {
+        @NonNull
+        private List<String> mTargetIds;
+        @Nullable
+        private String mLocation;
+        @ActionType
+        private int mAction;
+        private int mFlags;
+
+        /**
+         * @param id The target id that is associated with this event.
+         * @param actionType The event type
+         */
+        public Builder(@NonNull String id, @ActionType int actionType) {
+            mTargetIds = new ArrayList<>();
+            mTargetIds.add(id);
+            mAction = actionType;
+        }
+
+        /**
+         * @param ids The target ids that is associated with this event.
+         * @param actionType The event type
+         */
+        public Builder(@NonNull List<String> ids, @ActionType int actionType) {
+            mTargetIds = ids;
+            mAction = actionType;
+        }
+
+        /**
+         * Sets the launch location.
+         */
+        @NonNull
+        public Builder setLaunchLocation(@Nullable String location) {
+            mLocation = location;
+            return this;
+        }
+
+        /**
+         * Sets the launch location.
+         */
+        @NonNull
+        public Builder setFlags(int flags) {
+            mFlags = flags;
+            return this;
+        }
+
+        /**
+         * Builds a new event instance.
+         */
+        @NonNull
+        public SearchTargetEvent build() {
+            return new SearchTargetEvent(mTargetIds, mLocation, mAction, mFlags);
+        }
+    }
+}
diff --git a/core/java/android/app/search/SearchUiManager.java b/core/java/android/app/search/SearchUiManager.java
new file mode 100644
index 0000000..636bfe1
--- /dev/null
+++ b/core/java/android/app/search/SearchUiManager.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.search;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.Context;
+
+import java.util.Objects;
+
+/**
+ * Class that provides methods to create search ui session clients.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SearchUiManager {
+
+    private final Context mContext;
+
+    /**
+     * @hide
+     */
+    public SearchUiManager(Context context) {
+        mContext = Objects.requireNonNull(context);
+    }
+
+    /**
+     * Creates a new search session.
+     */
+    @NonNull
+    public SearchSession createSearchSession(
+            @NonNull SearchContext searchContext) {
+        return new SearchSession(mContext, searchContext);
+    }
+}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 7f08bfb..3758cb4 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -20,8 +20,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityClient;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
+import android.app.IActivityClientController;
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -67,6 +69,11 @@
     private boolean mIsForward;
     private ProfilerInfo mProfilerInfo;
     private IBinder mAssistToken;
+    /**
+     * It is only non-null if the process is the first time to launch activity. It is only an
+     * optimization for quick look up of the interface so the field is ignored for comparison.
+     */
+    private IActivityClientController mActivityClientController;
     private FixedRotationAdjustments mFixedRotationAdjustments;
 
     @Override
@@ -74,6 +81,9 @@
         client.countLaunchingActivities(1);
         client.updateProcessState(mProcState, false);
         client.updatePendingConfiguration(mCurConfig);
+        if (mActivityClientController != null) {
+            ActivityClient.setActivityClientController(mActivityClientController);
+        }
     }
 
     @Override
@@ -105,14 +115,16 @@
             String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
             PersistableBundle persistentState, List<ResultInfo> pendingResults,
             List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo,
-            IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
+            IBinder assistToken, IActivityClientController activityClientController,
+            FixedRotationAdjustments fixedRotationAdjustments) {
         LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
         if (instance == null) {
             instance = new LaunchActivityItem();
         }
         setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
                 voiceInteractor, procState, state, persistentState, pendingResults,
-                pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments);
+                pendingNewIntents, isForward, profilerInfo, assistToken, activityClientController,
+                fixedRotationAdjustments);
 
         return instance;
     }
@@ -120,7 +132,7 @@
     @Override
     public void recycle() {
         setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
-                false, null, null, null);
+                false, null, null, null, null);
         ObjectPool.recycle(this);
     }
 
@@ -146,6 +158,7 @@
         dest.writeBoolean(mIsForward);
         dest.writeTypedObject(mProfilerInfo, flags);
         dest.writeStrongBinder(mAssistToken);
+        dest.writeStrongInterface(mActivityClientController);
         dest.writeTypedObject(mFixedRotationAdjustments, flags);
     }
 
@@ -162,6 +175,7 @@
                 in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(),
                 in.readTypedObject(ProfilerInfo.CREATOR),
                 in.readStrongBinder(),
+                IActivityClientController.Stub.asInterface(in.readStrongBinder()),
                 in.readTypedObject(FixedRotationAdjustments.CREATOR));
     }
 
@@ -266,6 +280,7 @@
             int procState, Bundle state, PersistableBundle persistentState,
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
             boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
+            IActivityClientController activityClientController,
             FixedRotationAdjustments fixedRotationAdjustments) {
         instance.mIntent = intent;
         instance.mIdent = ident;
@@ -283,6 +298,7 @@
         instance.mIsForward = isForward;
         instance.mProfilerInfo = profilerInfo;
         instance.mAssistToken = assistToken;
+        instance.mActivityClientController = activityClientController;
         instance.mFixedRotationAdjustments = fixedRotationAdjustments;
     }
 }
diff --git a/core/java/android/app/servertransaction/OWNERS b/core/java/android/app/servertransaction/OWNERS
new file mode 100644
index 0000000..aa6248e
--- /dev/null
+++ b/core/java/android/app/servertransaction/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 316125
+
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/app/slice/OWNERS b/core/java/android/app/slice/OWNERS
new file mode 100644
index 0000000..b0a44fb
--- /dev/null
+++ b/core/java/android/app/slice/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 342804
+
+sunnygoyal@google.com
+dsandler@android.com
+dsandler@google.com
+adamcohen@google.com
diff --git a/core/java/android/app/time/OWNERS b/core/java/android/app/time/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/app/time/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.aidl b/core/java/android/app/timedetector/GnssTimeSuggestion.aidl
new file mode 100644
index 0000000..81475ec
--- /dev/null
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.timedetector;
+
+parcelable GnssTimeSuggestion;
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java
new file mode 100644
index 0000000..6478a2d
--- /dev/null
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a GNSS source.
+ *
+ * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
+ * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
+ * elapsed realtime clock when the {@code utcTime.value} was established.
+ * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
+ * suggestions cannot be persisted across device resets.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was entered. This information exists only to aid in
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
+ * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ *
+ * @hide
+ */
+public final class GnssTimeSuggestion implements Parcelable {
+
+    public static final @NonNull Creator<GnssTimeSuggestion> CREATOR =
+            new Creator<GnssTimeSuggestion>() {
+                public GnssTimeSuggestion createFromParcel(Parcel in) {
+                    return GnssTimeSuggestion.createFromParcel(in);
+                }
+
+                public GnssTimeSuggestion[] newArray(int size) {
+                    return new GnssTimeSuggestion[size];
+                }
+            };
+
+    @NonNull private final TimestampedValue<Long> mUtcTime;
+    @Nullable private ArrayList<String> mDebugInfo;
+
+    public GnssTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
+        mUtcTime = Objects.requireNonNull(utcTime);
+        Objects.requireNonNull(utcTime.getValue());
+    }
+
+    private static GnssTimeSuggestion createFromParcel(Parcel in) {
+        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+        GnssTimeSuggestion suggestion = new GnssTimeSuggestion(utcTime);
+        @SuppressWarnings("unchecked")
+        ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+        suggestion.mDebugInfo = debugInfo;
+        return suggestion;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelable(mUtcTime, 0);
+        dest.writeList(mDebugInfo);
+    }
+
+    @NonNull
+    public TimestampedValue<Long> getUtcTime() {
+        return mUtcTime;
+    }
+
+    @NonNull
+    public List<String> getDebugInfo() {
+        return mDebugInfo == null
+                ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+    }
+
+    /**
+     * Associates information with the instance that can be useful for debugging / logging. The
+     * information is present in {@link #toString()} but is not considered for
+     * {@link #equals(Object)} and {@link #hashCode()}.
+     */
+    public void addDebugInfo(String... debugInfos) {
+        if (mDebugInfo == null) {
+            mDebugInfo = new ArrayList<>();
+        }
+        mDebugInfo.addAll(Arrays.asList(debugInfos));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        GnssTimeSuggestion that = (GnssTimeSuggestion) o;
+        return Objects.equals(mUtcTime, that.mUtcTime);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mUtcTime);
+    }
+
+    @Override
+    public String toString() {
+        return "GnssTimeSuggestion{"
+                + "mUtcTime=" + mUtcTime
+                + ", mDebugInfo=" + mDebugInfo
+                + '}';
+    }
+}
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index 7bea5d7..87e7233 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -16,6 +16,7 @@
 
 package android.app.timedetector;
 
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
@@ -34,6 +35,7 @@
  * {@hide}
  */
 interface ITimeDetectorService {
+  void suggestGnssTime(in GnssTimeSuggestion timeSuggestion);
   boolean suggestManualTime(in ManualTimeSuggestion timeSuggestion);
   void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion);
   void suggestTelephonyTime(in TelephonyTimeSuggestion timeSuggestion);
diff --git a/core/java/android/app/timedetector/OWNERS b/core/java/android/app/timedetector/OWNERS
new file mode 100644
index 0000000..941eed8
--- /dev/null
+++ b/core/java/android/app/timedetector/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 847766
+mingaleev@google.com
+narayan@google.com
+nfuller@google.com
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 162e182..52016b6 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -71,4 +71,12 @@
      */
     @RequiresPermission(android.Manifest.permission.SET_TIME)
     void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion);
+
+    /**
+     * Suggests the time according to a gnss time source.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.SET_TIME)
+    void suggestGnssTime(GnssTimeSuggestion timeSuggestion);
 }
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index ac02c89..b0aa3c8 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -74,4 +74,16 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    @Override
+    public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
+        if (DEBUG) {
+            Log.d(TAG, "suggestGnssTime called: " + timeSuggestion);
+        }
+        try {
+            mITimeDetectorService.suggestGnssTime(timeSuggestion);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/app/timezone/OWNERS b/core/java/android/app/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/app/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/app/timezonedetector/OWNERS b/core/java/android/app/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/app/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/app/usage/OWNERS b/core/java/android/app/usage/OWNERS
new file mode 100644
index 0000000..a33d0ad
--- /dev/null
+++ b/core/java/android/app/usage/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 532296
+
+yamasani@google.com
+mwachens@google.com
+varunshah@google.com
diff --git a/core/java/android/attention/OWNERS b/core/java/android/attention/OWNERS
new file mode 100644
index 0000000..dd579b6
--- /dev/null
+++ b/core/java/android/attention/OWNERS
@@ -0,0 +1 @@
+asalo@google.com
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1713a0c..406fe8d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2967,6 +2967,16 @@
                             }
                         });
                     }
+                    synchronized (mBluetoothConnectionCallbackExecutorMap) {
+                        if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+                            try {
+                                mService.registerBluetoothConnectionCallback(mConnectionCallback);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth"
+                                        + "connection callback", e);
+                            }
+                        }
+                    }
                 }
 
                 public void onBluetoothServiceDown() {
@@ -3616,25 +3626,25 @@
             return false;
         }
 
-        // If the callback map is empty, we register the service-to-app callback
-        if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
-            try {
-                mServiceLock.readLock().lock();
-                if (mService != null) {
-                    if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
-                        return false;
-                    }
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-                mBluetoothConnectionCallbackExecutorMap.remove(callback);
-            } finally {
-                mServiceLock.readLock().unlock();
-            }
-        }
-
-        // Adds the passed in callback to our map of callbacks to executors
         synchronized (mBluetoothConnectionCallbackExecutorMap) {
+            // If the callback map is empty, we register the service-to-app callback
+            if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+                try {
+                    mServiceLock.readLock().lock();
+                    if (mService != null) {
+                        if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+                            return false;
+                        }
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "", e);
+                    mBluetoothConnectionCallbackExecutorMap.remove(callback);
+                } finally {
+                    mServiceLock.readLock().unlock();
+                }
+            }
+
+            // Adds the passed in callback to our map of callbacks to executors
             if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
                 throw new IllegalArgumentException("This callback has already been registered");
             }
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index e274af1..56c4824 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -153,7 +153,12 @@
     @SystemApi
     public static final ParcelUuid HEARING_AID =
             ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb");
-
+   /** Placeholder until specification is released
+     * @hide */
+    @NonNull
+    @SystemApi
+    public static final ParcelUuid LE_AUDIO =
+            ParcelUuid.fromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE");
     /** @hide */
     @NonNull
     @SystemApi
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
new file mode 100644
index 0000000..3523ee0
--- /dev/null
+++ b/core/java/android/bluetooth/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 27441
+
+zachoverflow@google.com
+siyuanh@google.com
diff --git a/core/java/android/bluetooth/le/OWNERS b/core/java/android/bluetooth/le/OWNERS
new file mode 100644
index 0000000..3523ee0
--- /dev/null
+++ b/core/java/android/bluetooth/le/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 27441
+
+zachoverflow@google.com
+siyuanh@google.com
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index c3c270e..59646f10 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -34,6 +34,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
+import android.util.ExceptionUtils;
 import android.util.Log;
 
 import java.util.Collections;
@@ -321,6 +322,77 @@
         }
     }
 
+    /**
+     * Register to receive callbacks whenever the associated device comes in and out of range.
+     *
+     * The provided device must be {@link #associate associated} with the calling app before
+     * calling this method.
+     *
+     * Caller must implement a single {@link CompanionDeviceService} which will be bound to and
+     * receive callbacks to {@link CompanionDeviceService#onDeviceAppeared} and
+     * {@link CompanionDeviceService#onDeviceDisappeared}.
+     * The app doesn't need to remain running in order to receive its callbacks.
+     *
+     * Calling app must declare uses-permission
+     * {@link android.Manifest.permission#REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE}.
+     *
+     * Calling app must check for feature presence of
+     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API.
+     *
+     * @param deviceAddress a previously-associated companion device's address
+     *
+     * @throws DeviceNotAssociatedException if the given device was not previously associated
+     * with this app.
+     */
+    @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
+    public void startObservingDevicePresence(@NonNull String deviceAddress)
+            throws DeviceNotAssociatedException {
+        if (!checkFeaturePresent()) {
+            return;
+        }
+        Objects.requireNonNull(deviceAddress, "address cannot be null");
+        try {
+            mService.registerDevicePresenceListenerService(
+                    mContext.getPackageName(), deviceAddress);
+        } catch (RemoteException e) {
+            ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister for receiving callbacks whenever the associated device comes in and out of range.
+     *
+     * The provided device must be {@link #associate associated} with the calling app before
+     * calling this method.
+     *
+     * Calling app must declare uses-permission
+     * {@link android.Manifest.permission#REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE}.
+     *
+     * Calling app must check for feature presence of
+     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API.
+     *
+     * @param deviceAddress a previously-associated companion device's address
+     *
+     * @throws DeviceNotAssociatedException if the given device was not previously associated
+     * with this app.
+     */
+    @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE)
+    public void stopObservingDevicePresence(@NonNull String deviceAddress)
+            throws DeviceNotAssociatedException {
+        if (!checkFeaturePresent()) {
+            return;
+        }
+        Objects.requireNonNull(deviceAddress, "address cannot be null");
+        try {
+            mService.unregisterDevicePresenceListenerService(
+                    mContext.getPackageName(), deviceAddress);
+        } catch (RemoteException e) {
+            ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private boolean checkFeaturePresent() {
         boolean featurePresent = mService != null;
         if (!featurePresent && DEBUG) {
diff --git a/core/java/android/companion/DeviceNotAssociatedException.java b/core/java/android/companion/DeviceNotAssociatedException.java
new file mode 100644
index 0000000..bebb6c9
--- /dev/null
+++ b/core/java/android/companion/DeviceNotAssociatedException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.companion;
+
+import android.annotation.Nullable;
+
+/**
+ * An exception for a case when a given device was not
+ * {@link CompanionDeviceManager#associate associated} to the calling app.
+ */
+public class DeviceNotAssociatedException extends Exception {
+    /** @hide */
+    public DeviceNotAssociatedException(@Nullable String deviceName) {
+        super("Device not associated with the current app: " + deviceName);
+    }
+}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index bcb9be8..527d8df 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -45,4 +45,8 @@
 
     boolean isDeviceAssociatedForWifiConnection(in String packageName, in String macAddress,
         int userId);
+
+    void registerDevicePresenceListenerService(in String packageName, in String deviceAddress);
+
+    void unregisterDevicePresenceListenerService(in String packageName, in String deviceAddress);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 616194b..abe7fda 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4529,6 +4529,18 @@
     public static final String APP_PREDICTION_SERVICE = "app_prediction";
 
     /**
+     * Official published name of the search ui service.
+     *
+     * <p><b>NOTE: </b> this service is optional; callers of
+     * {@code Context.getSystemServiceName(SEARCH_UI_SERVICE)} should check for {@code null}.
+     *
+     * @hide
+     * @see #getSystemService(String)
+     */
+    @SystemApi
+    public static final String SEARCH_UI_SERVICE = "search_ui";
+
+    /**
      * Use with {@link #getSystemService(String)} to access the
      * {@link com.android.server.voiceinteraction.SoundTriggerService}.
      *
@@ -4552,6 +4564,7 @@
      * @hide
      * @see #getSystemService(String)
      */
+    @SystemApi
     public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
 
     /**
@@ -4564,6 +4577,15 @@
     public static final String PERMISSION_SERVICE = "permission";
 
     /**
+     * Official published name of the legacy (internal) permission service.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public static final String LEGACY_PERMISSION_SERVICE = "legacy_permission";
+
+    /**
      * Official published name of the (internal) permission controller service.
      *
      * @see #getSystemService(String)
@@ -5216,7 +5238,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/OWNERS b/core/java/android/content/OWNERS
new file mode 100644
index 0000000..c1e7e41
--- /dev/null
+++ b/core/java/android/content/OWNERS
@@ -0,0 +1,3 @@
+# Remain no owner because multiple modules may touch this file.
+per-file Context.java = *
+per-file ContextWrapper.java = *
diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS
new file mode 100644
index 0000000..91a0abf
--- /dev/null
+++ b/core/java/android/content/om/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 568631
+
+toddke@android.com
+toddke@google.com
+patb@google.com
+rtmitchell@google.com
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 81d9b11..e32068f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2101,7 +2101,7 @@
     }
 
     /** @hide */
-    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    @SystemApi
     public boolean isOem() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
     }
@@ -2149,13 +2149,13 @@
     }
 
     /** @hide */
-    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    @SystemApi
     public boolean isVendor() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
     }
 
     /** @hide */
-    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    @SystemApi
     public boolean isProduct() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
diff --git a/core/java/android/content/pm/CrossProfileAppsInternal.java b/core/java/android/content/pm/CrossProfileAppsInternal.java
index 16a749f..255aeac 100644
--- a/core/java/android/content/pm/CrossProfileAppsInternal.java
+++ b/core/java/android/content/pm/CrossProfileAppsInternal.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.UserIdInt;
+import android.app.AppOpsManager.Mode;
 import android.os.UserHandle;
 
 import java.util.List;
@@ -62,4 +63,14 @@
      */
     public abstract List<UserHandle> getTargetUserProfiles(
             String packageName, @UserIdInt int userId);
+
+    /**
+     * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is
+     * configurable by users in Settings. This configures it for the profile group of the given
+     * user.
+     *
+     * @see CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)
+     */
+    public abstract void setInteractAcrossProfilesAppOp(
+            String packageName, @Mode int newMode, @UserIdInt int userId);
 }
diff --git a/core/java/android/content/pm/LimitedLengthInputStream.java b/core/java/android/content/pm/LimitedLengthInputStream.java
index 19b681e..05089f6 100644
--- a/core/java/android/content/pm/LimitedLengthInputStream.java
+++ b/core/java/android/content/pm/LimitedLengthInputStream.java
@@ -1,6 +1,6 @@
 package android.content.pm;
 
-import libcore.util.ArrayUtils;
+import com.android.internal.util.ArrayUtils;
 
 import java.io.FilterInputStream;
 import java.io.IOException;
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index a16bb4f..24872e8 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -1 +1,8 @@
+# Bug component: 36137
+
+toddke@android.com
+toddke@google.com
+patb@google.com
+
 per-file PackageParser.java = chiuwinson@google.com
+per-file *Shortcut* = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
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/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cf3f706..bd27099 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2682,6 +2682,23 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature(String, int)}: If this feature is supported, the feature version
+     * specifies a date such that the device is known to pass the OpenGLES dEQP test suite
+     * associated with that date.  The date is encoded as follows:
+     * <ul>
+     * <li>Year in bits 31-16</li>
+     * <li>Month in bits 15-8</li>
+     * <li>Day in bits 7-0</li>
+     * </ul>
+     * <p>
+     * Example: 2021-03-01 is encoded as 0x07E50301, and would indicate that the device passes the
+     * OpenGL ES dEQP test suite version that was current on 2021-03-01.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device includes broadcast radio tuner.
      * @hide
      */
@@ -4438,6 +4455,7 @@
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
+    //@Deprecated
     public abstract PermissionInfo getPermissionInfo(@NonNull String permName,
             @PermissionInfoFlags int flags) throws NameNotFoundException;
 
@@ -4450,9 +4468,10 @@
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a list of {@link PermissionInfo} containing information
      *         about all of the permissions in the given group.
-     * @throws NameNotFoundException if a package with the given name cannot be
+     * @throws NameNotFoundException if a group with the given name cannot be
      *             found on the system.
      */
+    //@Deprecated
     @NonNull
     public abstract List<PermissionInfo> queryPermissionsByGroup(@NonNull String permissionGroup,
             @PermissionInfoFlags int flags) throws NameNotFoundException;
@@ -4481,7 +4500,7 @@
      * Retrieve all of the information we know about a particular group of
      * permissions.
      *
-     * @param permName The fully qualified name (i.e.
+     * @param groupName The fully qualified name (i.e.
      *            com.google.permission_group.APPS) of the permission you are
      *            interested in.
      * @param flags Additional option flags to modify the data returned.
@@ -4490,8 +4509,9 @@
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
+    //@Deprecated
     @NonNull
-    public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permName,
+    public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
             @PermissionGroupInfoFlags int flags) throws NameNotFoundException;
 
     /**
@@ -4501,6 +4521,7 @@
      * @return Returns a list of {@link PermissionGroupInfo} containing
      *         information about all of the known permission groups.
      */
+    //@Deprecated
     @NonNull
     public abstract List<PermissionGroupInfo> getAllPermissionGroups(
             @PermissionGroupInfoFlags int flags);
@@ -4757,6 +4778,7 @@
      * @return Whether the permission is restricted by policy.
      */
     @CheckResult
+    //@Deprecated
     public abstract boolean isPermissionRevokedByPolicy(@NonNull String permName,
             @NonNull String packageName);
 
@@ -4805,6 +4827,7 @@
      *
      * @see #removePermission(String)
      */
+    //@Deprecated
     public abstract boolean addPermission(@NonNull PermissionInfo info);
 
     /**
@@ -4814,6 +4837,7 @@
      * expense of no guarantee the added permission will be retained if
      * the device is rebooted before it is written.
      */
+    //@Deprecated
     public abstract boolean addPermissionAsync(@NonNull PermissionInfo info);
 
     /**
@@ -4829,6 +4853,7 @@
      *
      * @see #addPermission(PermissionInfo)
      */
+    //@Deprecated
     public abstract void removePermission(@NonNull String permName);
 
     /**
@@ -4881,6 +4906,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
@@ -4908,6 +4934,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
@@ -4936,6 +4963,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public void revokeRuntimePermission(@NonNull String packageName,
@@ -4953,6 +4981,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(anyOf = {
@@ -4976,6 +5005,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(anyOf = {
@@ -5040,6 +5070,7 @@
      *
      * @throws SecurityException if you try to access a whitelist that you have no access to.
      */
+    //@Deprecated
     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
             conditional = true)
     public @NonNull Set<String> getWhitelistedRestrictedPermissions(
@@ -5106,6 +5137,7 @@
      *
      * @throws SecurityException if you try to modify a whitelist that you have no access to.
      */
+    //@Deprecated
     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
             conditional = true)
     public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
@@ -5175,6 +5207,7 @@
      *
      * @throws SecurityException if you try to modify a whitelist that you have no access to.
      */
+    //@Deprecated
     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
         conditional = true)
     public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
@@ -5207,6 +5240,7 @@
      *
      * @throws SecurityException if you you have no access to modify this.
      */
+    //@Deprecated
     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
             conditional = true)
     public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) {
@@ -5234,6 +5268,7 @@
      *
      * @throws SecurityException if you you have no access to this.
      */
+    //@Deprecated
     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
             conditional = true)
     public boolean isAutoRevokeWhitelisted(@NonNull String packageName) {
@@ -5252,6 +5287,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @UnsupportedAppUsage
     public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permName);
@@ -7554,6 +7590,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
@@ -7567,6 +7604,7 @@
      *
      * @hide
      */
+    //@Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @SystemApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4dfbd75..45f072a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -53,7 +53,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
 import android.content.pm.split.SplitAssetLoader;
@@ -74,6 +73,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -2394,17 +2394,13 @@
             Slog.i(TAG, newPermsMsg.toString());
         }
 
-        List<SplitPermissionInfoParcelable> splitPermissions;
-
-        try {
-            splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        final List<PermissionManager.SplitPermissionInfo> splitPermissions =
+                ActivityThread.currentApplication().getSystemService(PermissionManager.class)
+                        .getSplitPermissions();
 
         final int listSize = splitPermissions.size();
         for (int is = 0; is < listSize; is++) {
-            final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
+            final PermissionManager.SplitPermissionInfo spi = splitPermissions.get(is);
             if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
                     || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
                 continue;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index cd9ba6a..35f02a8 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -65,12 +65,20 @@
     @Deprecated
     public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;
 
+    /**
+     * System-level value for {@link #protectionLevel}, corresponding
+     * to the <code>internal</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     */
+    public static final int PROTECTION_INTERNAL = 4;
+
     /** @hide */
     @IntDef(flag = false, prefix = { "PROTECTION_" }, value = {
             PROTECTION_NORMAL,
             PROTECTION_DANGEROUS,
             PROTECTION_SIGNATURE,
             PROTECTION_SIGNATURE_OR_SYSTEM,
+            PROTECTION_INTERNAL,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Protection {}
@@ -261,6 +269,15 @@
     @SystemApi
     public static final int PROTECTION_FLAG_RECENTS = 0x2000000;
 
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding to the <code>role</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int PROTECTION_FLAG_ROLE = 0x4000000;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
             PROTECTION_FLAG_PRIVILEGED,
@@ -285,6 +302,7 @@
             PROTECTION_FLAG_COMPANION,
             PROTECTION_FLAG_RETAIL_DEMO,
             PROTECTION_FLAG_RECENTS,
+            PROTECTION_FLAG_ROLE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionFlags {}
@@ -317,7 +335,7 @@
      * </pre>
      *
      * <p></p>Base permission types are {@link #PROTECTION_NORMAL},
-     * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE}
+     * {@link #PROTECTION_DANGEROUS}, {@link #PROTECTION_SIGNATURE}, {@link #PROTECTION_INTERNAL}
      * and the deprecated {@link #PROTECTION_SIGNATURE_OR_SYSTEM}.
      * Flags are listed under {@link android.R.attr#protectionLevel}.
      *
@@ -479,6 +497,9 @@
             case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
                 protLevel.append("signatureOrSystem");
                 break;
+            case PermissionInfo.PROTECTION_INTERNAL:
+                protLevel.append("internal");
+                break;
             default:
                 protLevel.append("????");
                 break;
@@ -546,6 +567,9 @@
         if ((level & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0) {
             protLevel.append("|recents");
         }
+        if ((level & PermissionInfo.PROTECTION_FLAG_ROLE) != 0) {
+            protLevel.append("|role");
+        }
         return protLevel.toString();
     }
 
diff --git a/core/java/android/content/pm/dex/OWNERS b/core/java/android/content/pm/dex/OWNERS
new file mode 100644
index 0000000..267e5d58
--- /dev/null
+++ b/core/java/android/content/pm/dex/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 86431
+
+toddke@android.com
+toddke@google.com
+patb@google.com
+calin@google.com
+ngeoffray@google.com
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index eae7d45..561a9e3 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -71,7 +71,6 @@
 import android.content.pm.parsing.result.ParseInput.DeferredError;
 import android.content.pm.parsing.result.ParseResult;
 import android.content.pm.parsing.result.ParseTypeImpl;
-import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
 import android.content.pm.split.SplitAssetLoader;
@@ -85,9 +84,9 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.FileUtils;
-import android.os.RemoteException;
 import android.os.Trace;
 import android.os.ext.SdkExtensions;
+import android.permission.PermissionManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -2664,17 +2663,13 @@
     }
 
     private static void convertSplitPermissions(ParsingPackage pkg) {
-        List<SplitPermissionInfoParcelable> splitPermissions;
-
-        try {
-            splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        final List<PermissionManager.SplitPermissionInfo> splitPermissions =
+                ActivityThread.currentApplication().getSystemService(PermissionManager.class)
+                        .getSplitPermissions();
 
         final int listSize = splitPermissions.size();
         for (int is = 0; is < listSize; is++) {
-            final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
+            final PermissionManager.SplitPermissionInfo spi = splitPermissions.get(is);
             List<String> requestedPermissions = pkg.getRequestedPermissions();
             if (pkg.getTargetSdkVersion() >= spi.getTargetSdk()
                     || !requestedPermissions.contains(spi.getSplitPermission())) {
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
index 894849a..cbd2c55 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
@@ -112,10 +112,12 @@
             if ((permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
                     && (permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY)
                     == 0
-                    && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) !=
-                    PermissionInfo.PROTECTION_SIGNATURE) {
+                    && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                    != PermissionInfo.PROTECTION_SIGNATURE
+                    && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                    != PermissionInfo.PROTECTION_INTERNAL) {
                 return input.error("<permission>  protectionLevel specifies a non-instant flag "
-                        + "but is not based on signature type");
+                        + "but is not based on signature or internal type");
             }
         }
 
diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS
new file mode 100644
index 0000000..cde7b2a
--- /dev/null
+++ b/core/java/android/content/pm/permission/OWNERS
@@ -0,0 +1,11 @@
+# Bug component: 137825
+
+toddke@android.com
+toddke@google.com
+patb@google.com
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+zhanghai@google.com
+evanseverson@google.com
+ntmyren@google.com
diff --git a/core/java/android/content/pm/split/OWNERS b/core/java/android/content/pm/split/OWNERS
new file mode 100644
index 0000000..3d126d2
--- /dev/null
+++ b/core/java/android/content/pm/split/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+
+toddke@android.com
+toddke@google.com
+patb@google.com
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index f5e1719..2d381eb 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -25,6 +25,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -101,11 +103,11 @@
     public @interface FormatType {}
 
     @GuardedBy("this")
-    private long mNativePtr;  // final, except cleared in finalizer.
+    private final long mNativePtr;
 
     @Nullable
     @GuardedBy("this")
-    private final StringBlock mStringBlock;  // null or closed if mNativePtr = 0.
+    private final StringBlock mStringBlock;
 
     @PropertyFlags
     private final int mFlags;
@@ -113,6 +115,19 @@
     @Nullable
     private final AssetsProvider mAssets;
 
+    @GuardedBy("this")
+    @Nullable
+    private final Runnable mRunNativeCleanup;
+
+    // Use a Holder to allow static initialization of ApkAssets in the boot image, and
+    // possibly to avoid some initialization ordering issues.
+    private static class NoImagePreloadHolder {
+        // TODO(175425996): Make size estimate more accurate
+        public static final NativeAllocationRegistry REGISTRY =
+                NativeAllocationRegistry.createMalloced(ApkAssets.class.getClassLoader(),
+                                                        nativeGetFinalizer());
+    }
+
     /**
      * Creates a new ApkAssets instance from the given path on disk.
      *
@@ -287,6 +302,8 @@
         mFlags = flags;
         mNativePtr = nativeLoad(format, path, flags, assets);
         mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+        mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+                this, mNativePtr);
         mAssets = assets;
     }
 
@@ -298,6 +315,8 @@
         mFlags = flags;
         mNativePtr = nativeLoadFd(format, fd, friendlyName, flags, assets);
         mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+        mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+                this, mNativePtr);
         mAssets = assets;
     }
 
@@ -309,6 +328,8 @@
         mFlags = flags;
         mNativePtr = nativeLoadFdOffsets(format, fd, friendlyName, offset, length, flags, assets);
         mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+        mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+                this, mNativePtr);
         mAssets = assets;
     }
 
@@ -316,6 +337,7 @@
         mFlags = flags;
         mNativePtr = nativeLoadEmpty(flags, assets);
         mStringBlock = null;
+        mRunNativeCleanup = null;
         mAssets = assets;
     }
 
@@ -403,22 +425,16 @@
         return "ApkAssets{path=" + getAssetPath() + "}";
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        close();
-    }
-
     /**
      * Closes this class and the contained {@link #mStringBlock}.
      */
     public void close() {
         synchronized (this) {
-            if (mNativePtr != 0) {
-                if (mStringBlock != null) {
-                    mStringBlock.close();
-                }
-                nativeDestroy(mNativePtr);
-                mNativePtr = 0;
+            if (mStringBlock != null) {
+                mStringBlock.close();
+            }
+            if (mRunNativeCleanup != null) {
+                mRunNativeCleanup.run();
             }
         }
     }
@@ -433,7 +449,6 @@
     private static native long nativeLoadFdOffsets(@FormatType int format,
             @NonNull FileDescriptor fd, @NonNull String friendlyName, long offset, long length,
             @PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException;
-    private static native void nativeDestroy(long ptr);
     private static native @NonNull String nativeGetAssetPath(long ptr);
     private static native long nativeGetStringBlock(long ptr);
     private static native boolean nativeIsUpToDate(long ptr);
@@ -441,4 +456,5 @@
     private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr,
             String overlayableName) throws IOException;
     private static native boolean nativeDefinesOverlayable(long ptr) throws IOException;
+    private static native final long nativeGetFinalizer();
 }
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
new file mode 100644
index 0000000..bc2355c
--- /dev/null
+++ b/core/java/android/content/res/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 568761
+
+toddke@android.com
+toddke@google.com
+patb@google.com
+rtmitchell@google.com
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 78cea15..cbcdb37 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -534,7 +534,24 @@
             remainder = languageTag.substring(separator);
         }
 
-        return Locale.adjustLanguageCode(language) + remainder;
+        // No need to convert to lower cases because the language in the return value of
+        // Locale.toLanguageTag has been lower-cased.
+        final String adjustedLanguage;
+        switch(language) {
+            case "id":
+                adjustedLanguage = "in";
+                break;
+            case "yi":
+                adjustedLanguage = "ji";
+                break;
+            case "he":
+                adjustedLanguage = "iw";
+                break;
+            default:
+                adjustedLanguage = language;
+                break;
+        }
+        return adjustedLanguage + remainder;
     }
 
     /**
diff --git a/core/java/android/content/rollback/OWNERS b/core/java/android/content/rollback/OWNERS
new file mode 100644
index 0000000..3093fd6
--- /dev/null
+++ b/core/java/android/content/rollback/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 557916
+
+narayan@google.com
+nandana@google.com
+olilan@google.com
diff --git a/core/java/android/gesture/OWNERS b/core/java/android/gesture/OWNERS
new file mode 100644
index 0000000..b3b8775
--- /dev/null
+++ b/core/java/android/gesture/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 25700
+
+romainguy@google.com
+alanv@google.com
+adamp@google.com
+aurimas@google.com
+nduca@google.com
+sumir@google.com
diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl
index 1ba7b98..4e368d0 100644
--- a/core/java/android/hardware/ISensorPrivacyManager.aidl
+++ b/core/java/android/hardware/ISensorPrivacyManager.aidl
@@ -32,4 +32,12 @@
 
     void setSensorPrivacy(boolean enable);
     // =============== End of transactions used on native side as well ============================
+
+    // TODO(evanseverson) add to native interface
+    boolean isIndividualSensorPrivacyEnabled(int sensor);
+
+    // TODO(evanseverson) add to native interface
+    void setIndividualSensorPrivacy(int sensor, boolean enable);
+
+    // TODO(evanseverson) listeners
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 47dbf2d..3295042 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,2 +1,5 @@
 # Camera
 per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com,jchowdhary@google.com
+
+# Sensor Privacy
+per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e913986..f7c4c2c 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -19,6 +19,7 @@
 
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.hardware.input.InputSensorInfo;
 import android.os.Build;
 
 /**
@@ -923,6 +924,30 @@
     }
 
     /**
+     * Construct a sensor object from SensorInfo of an input device.
+     * This is only used for constructing an input device sensor object.
+     * @hide
+     */
+    public Sensor(InputSensorInfo sensorInfo) {
+        this.mName = sensorInfo.getName();
+        this.mVendor = sensorInfo.getVendor();
+        this.mVersion = sensorInfo.getVersion();
+        this.mHandle = sensorInfo.getHandle();
+        this.mType = sensorInfo.getType();
+        this.mMaxRange = sensorInfo.getMaxRange();
+        this.mResolution = sensorInfo.getResolution();
+        this.mPower = sensorInfo.getPower();
+        this.mMinDelay = sensorInfo.getMinDelay();
+        this.mFifoReservedEventCount = sensorInfo.getFifoReservedEventCount();
+        this.mFifoMaxEventCount = sensorInfo.getFifoMaxEventCount();
+        this.mStringType = sensorInfo.getStringType();
+        this.mRequiredPermission = sensorInfo.getRequiredPermission();
+        this.mMaxDelay = sensorInfo.getMaxDelay();
+        this.mFlags = sensorInfo.getFlags();
+        this.mId = sensorInfo.getId();
+    }
+
+    /**
      * @return name string of the sensor.
      */
     public String getName() {
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 236fab0..232f234 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 
 /**
@@ -667,4 +668,16 @@
     SensorEvent(int valueSize) {
         values = new float[valueSize];
     }
+
+    /**
+     * Construct a sensor event object by sensor object, accuracy, timestamp and values.
+     * This is only used for constructing an input device sensor event object.
+     * @hide
+     */
+    public SensorEvent(@NonNull Sensor sensor, int accuracy, long timestamp, float[] values) {
+        this.sensor = sensor;
+        this.accuracy = accuracy;
+        this.timestamp = timestamp;
+        this.values = values;
+    }
 }
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 274202f..c647239 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
@@ -23,10 +24,14 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.service.SensorPrivacyIndividualEnabledSensorProto;
 import android.util.ArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * This class provides access to the sensor privacy services; sensor privacy allows the
  * user to disable access to all sensors on the device. This class provides methods to query the
@@ -38,6 +43,25 @@
 @SystemService(Context.SENSOR_PRIVACY_SERVICE)
 public final class SensorPrivacyManager {
 
+    /** Microphone */
+    public static final int INDIVIDUAL_SENSOR_MICROPHONE =
+            SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+
+    /** Camera */
+    public static final int INDIVIDUAL_SENSOR_CAMERA =
+            SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
+    /**
+     * Individual sensors not listed in {@link Sensor}
+     * @hide
+     */
+    @IntDef(prefix = "INDIVIDUAL_SENSOR_", value = {
+            INDIVIDUAL_SENSOR_MICROPHONE,
+            INDIVIDUAL_SENSOR_CAMERA
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IndividualSensor {}
+
     /**
      * A class implementing this interface can register with the {@link
      * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
@@ -168,4 +192,31 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Returns whether sensor privacy is currently enabled for a specific sensor.
+     *
+     * @return true if sensor privacy is currently enabled, false otherwise.
+     */
+    public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) {
+        try {
+            return mService.isIndividualSensorPrivacyEnabled(sensor);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets sensor privacy to the specified state for an individual sensor.
+     *
+     * @param enable the state to which sensor privacy should be set.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+    public void setIndividualSensorPrivacy(@IndividualSensor int sensor, boolean enable) {
+        try {
+            mService.setIndividualSensorPrivacy(sensor, enable);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/hardware/biometrics/OWNERS b/core/java/android/hardware/biometrics/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/biometrics/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
+jaggies@google.com
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index e858159..bd47463 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -964,12 +964,20 @@
      * <p>Closing a session frees up the target output Surfaces of the session for reuse with either
      * a new session, or to other APIs that can draw to Surfaces.</p>
      *
-     * <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession}
+     * <p>Note that for common usage scenarios like creating a new session or closing the camera
+     * device, it is faster to call respective APIs directly (see below for more details) without
+     * calling into this method. This API is only useful when application wants to uncofigure the
+     * camera but keep the device open for later use.</p>
+     *
+     * <p>Creating a new capture session with {@link CameraDevice#createCaptureSession}
      * will close any existing capture session automatically, and call the older session listener's
      * {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
      * directly without closing is the recommended approach for quickly switching to a new session,
      * since unchanged target outputs can be reused more efficiently.</p>
      *
+     * <p>Closing the device with {@link CameraDevice#close} directly without calling this API is
+     * also recommended for quickly closing the camera.</p>
+     *
      * <p>Once a session is closed, all methods on it will throw an IllegalStateException, and any
      * repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
      * However, any in-progress capture requests submitted to the session will be completed as
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8469f5f..cdfdc1f 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
@@ -850,13 +851,17 @@
          * A camera device has been opened by an application.
          *
          * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param cameraId The unique identifier of the new camera.
+         *    android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this
+         *    callback
+         * @param cameraId The unique identifier of the camera opened.
          * @param packageId The package Id of the application opening the camera.
          *
          * @see #onCameraClosed
+         * @hide
          */
-        /** @hide */
+        @SystemApi
+        @TestApi
+        @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER)
         public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) {
             // default empty implementation
         }
@@ -865,10 +870,14 @@
          * A previously-opened camera has been closed.
          *
          * <p>The default implementation of this method does nothing.</p>
-         *
+         *    android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this
+         *    callback.
          * @param cameraId The unique identifier of the closed camera.
+         * @hide
          */
-        /** @hide */
+        @SystemApi
+        @TestApi
+        @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER)
         public void onCameraClosed(@NonNull String cameraId) {
             // default empty implementation
         }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 7afba1a..41cc12f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2856,10 +2856,10 @@
      * respective color channel provided in
      * {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}.</p>
      * <p>For example:</p>
-     * <pre><code>android.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
+     * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
      * </code></pre>
      * <p>All green pixels are 100% green. All red/blue pixels are black.</p>
-     * <pre><code>android.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
+     * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
      * </code></pre>
      * <p>All red pixels are 100% red. Only the odd green pixels
      * are 100% green. All blue pixels are 100% black.</p>
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 19f4cd6..5cc7bf8 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1719,37 +1719,25 @@
     private static native long nativeAllocateCopy(long ptr)
             throws NullPointerException;
 
-    @FastNative
     private static synchronized native void nativeWriteToParcel(Parcel dest, long ptr);
-    @FastNative
     private static synchronized native void nativeReadFromParcel(Parcel source, long ptr);
-    @FastNative
     private static synchronized native void nativeSwap(long ptr, long otherPtr)
             throws NullPointerException;
-    @FastNative
     private static synchronized native void nativeClose(long ptr);
-    @FastNative
     private static synchronized native boolean nativeIsEmpty(long ptr);
-    @FastNative
     private static synchronized native int nativeGetEntryCount(long ptr);
-    @FastNative
     private static synchronized native long nativeGetBufferSize(long ptr);
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @FastNative
     private static synchronized native byte[] nativeReadValues(int tag, long ptr);
-    @FastNative
     private static synchronized native void nativeWriteValues(int tag, byte[] src, long ptr);
     private static synchronized native void nativeDump(long ptr) throws IOException; // dump to LOGD
 
-    @FastNative
     private static synchronized native ArrayList nativeGetAllVendorKeys(long ptr, Class keyClass);
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @FastNative
     private static synchronized native int nativeGetTagFromKeyLocal(long ptr, String keyName)
             throws IllegalArgumentException;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @FastNative
     private static synchronized native int nativeGetTypeFromTagLocal(long ptr, int tag)
             throws IllegalArgumentException;
     @FastNative
diff --git a/core/java/android/hardware/display/OWNERS b/core/java/android/hardware/display/OWNERS
index 9ca3910..5bcd9bb8 100644
--- a/core/java/android/hardware/display/OWNERS
+++ b/core/java/android/hardware/display/OWNERS
@@ -1,2 +1,6 @@
+# Bug component: 345010
+
+include /services/core/java/com/android/server/display/OWNERS
+
 michaelwr@google.com
 santoscordon@google.com
diff --git a/core/java/android/hardware/face/OWNERS b/core/java/android/hardware/face/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/face/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
+jaggies@google.com
diff --git a/core/java/android/hardware/fingerprint/OWNERS b/core/java/android/hardware/fingerprint/OWNERS
new file mode 100644
index 0000000..dcead40
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 114777
+
+jaggies@google.com
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ae10f40..43f04cd 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)
@@ -848,6 +848,20 @@
     }
 
     /**
+     * Determines whether the HDMI CEC stack should handle KEYCODE_TV_POWER.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+    public boolean shouldHandleTvPowerKey() {
+        try {
+            return mService.shouldHandleTvPowerKey();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Controls whether volume control commands via HDMI CEC are enabled.
      *
      * <p>When disabled:
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 202e090..3b61911f 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -72,6 +72,11 @@
         }
 
         @Override
+        public boolean shouldHandleTvPowerKey() {
+            return HdmiControlServiceWrapper.this.shouldHandleTvPowerKey();
+        }
+
+        @Override
         public void queryDisplayStatus(IHdmiControlCallback callback) {
             HdmiControlServiceWrapper.this.queryDisplayStatus(callback);
         }
@@ -368,6 +373,11 @@
     public void toggleAndFollowTvPower() {}
 
     /** @hide */
+    public boolean shouldHandleTvPowerKey() {
+        return true;
+    }
+
+    /** @hide */
     public void queryDisplayStatus(IHdmiControlCallback callback) {}
 
     /** @hide */
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index c6007f1..c0b177d 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.hardware.hdmi.HdmiControlManager.HdmiCecVersion;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -107,6 +108,8 @@
     // CEC only parameters.
     private final int mLogicalAddress;
     private final int mDeviceType;
+    @HdmiCecVersion
+    private final int mHdmiCecVersion;
     private final int mVendorId;
     private final String mDisplayName;
     private final int mDevicePowerStatus;
@@ -133,8 +136,9 @@
                             int vendorId = source.readInt();
                             int powerStatus = source.readInt();
                             String displayName = source.readString();
+                            int cecVersion = source.readInt();
                             return new HdmiDeviceInfo(logicalAddress, physicalAddress, portId,
-                                    deviceType, vendorId, displayName, powerStatus);
+                                    deviceType, vendorId, displayName, powerStatus, cecVersion);
                         case HDMI_DEVICE_TYPE_MHL:
                             int deviceId = source.readInt();
                             int adopterId = source.readInt();
@@ -167,7 +171,7 @@
      * @hide
      */
     public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
-            int vendorId, String displayName, int powerStatus) {
+            int vendorId, String displayName, int powerStatus, int hdmiCecVersion) {
         mHdmiDeviceType = HDMI_DEVICE_TYPE_CEC;
         mPhysicalAddress = physicalAddress;
         mPortId = portId;
@@ -175,6 +179,7 @@
         mId = idForCecDevice(logicalAddress);
         mLogicalAddress = logicalAddress;
         mDeviceType = deviceType;
+        mHdmiCecVersion = hdmiCecVersion;
         mVendorId = vendorId;
         mDevicePowerStatus = powerStatus;
         mDisplayName = displayName;
@@ -192,12 +197,31 @@
      * @param deviceType type of device
      * @param vendorId vendor id of device. Used for vendor specific command.
      * @param displayName name of device
+     * @param powerStatus device power status
+     * @hide
+     */
+    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);
+    }
+
+    /**
+     * Constructor. Used to initialize the instance for CEC device.
+     *
+     * @param logicalAddress  logical address of HDMI-CEC device
+     * @param physicalAddress physical address of HDMI-CEC device
+     * @param portId          HDMI port ID (1 for HDMI1)
+     * @param deviceType      type of device
+     * @param vendorId        vendor id of device. Used for vendor specific command.
+     * @param displayName     name of device
      * @hide
      */
     public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
             int vendorId, String displayName) {
         this(logicalAddress, physicalAddress, portId, deviceType,
-                vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN);
+                vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     /**
@@ -215,6 +239,7 @@
         mId = idForHardware(portId);
         mLogicalAddress = -1;
         mDeviceType = DEVICE_RESERVED;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mVendorId = 0;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "HDMI" + portId;
@@ -240,6 +265,7 @@
         mId = idForMhlDevice(portId);
         mLogicalAddress = -1;
         mDeviceType = DEVICE_RESERVED;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mVendorId = 0;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "Mobile";
@@ -261,6 +287,7 @@
 
         mLogicalAddress = -1;
         mDeviceType = DEVICE_INACTIVE;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mPortId = PORT_INVALID;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "Inactive";
@@ -339,6 +366,16 @@
     }
 
     /**
+     * Returns the CEC version the device supports.
+     *
+     * @hide
+     */
+    @HdmiCecVersion
+    public int getCecVersion() {
+        return mHdmiCecVersion;
+    }
+
+    /**
      * Returns device's power status. It should be one of the following values.
      * <ul>
      * <li>{@link HdmiControlManager#POWER_STATUS_ON}
@@ -448,6 +485,7 @@
                 dest.writeInt(mVendorId);
                 dest.writeInt(mDevicePowerStatus);
                 dest.writeString(mDisplayName);
+                dest.writeInt(mHdmiCecVersion);
                 break;
             case HDMI_DEVICE_TYPE_MHL:
                 dest.writeInt(mDeviceId);
@@ -470,6 +508,7 @@
                 s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress));
                 s.append(" ");
                 s.append("device_type: ").append(mDeviceType).append(" ");
+                s.append("cec_version: ").append(mHdmiCecVersion).append(" ");
                 s.append("vendor_id: ").append(mVendorId).append(" ");
                 s.append("display_name: ").append(mDisplayName).append(" ");
                 s.append("power_status: ").append(mDevicePowerStatus).append(" ");
@@ -507,6 +546,7 @@
                 && mPortId == other.mPortId
                 && mLogicalAddress == other.mLogicalAddress
                 && mDeviceType == other.mDeviceType
+                && mHdmiCecVersion == other.mHdmiCecVersion
                 && mVendorId == other.mVendorId
                 && mDevicePowerStatus == other.mDevicePowerStatus
                 && mDisplayName.equals(other.mDisplayName)
@@ -522,6 +562,7 @@
                 mPortId,
                 mLogicalAddress,
                 mDeviceType,
+                mHdmiCecVersion,
                 mVendorId,
                 mDevicePowerStatus,
                 mDisplayName,
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index e4b311a..625a6a5 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -192,6 +192,7 @@
 
     @Override
     public int hashCode() {
-        return mId;
+        return java.util.Objects.hash(
+                mId, mType, mAddress, mCecSupported, mArcSupported, mMhlSupported);
     }
 }
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 6d0c688..65bd856 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -43,6 +43,7 @@
     HdmiDeviceInfo getActiveSource();
     void oneTouchPlay(IHdmiControlCallback callback);
     void toggleAndFollowTvPower();
+    boolean shouldHandleTvPowerKey();
     void queryDisplayStatus(IHdmiControlCallback callback);
     void addHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
     void removeHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
new file mode 100644
index 0000000..16c15e3
--- /dev/null
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 826094
+
+include /services/core/java/com/android/server/display/OWNERS
+
+marvinramin@google.com
+nchalko@google.com
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index dc6f579..b39df4d 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -22,6 +22,9 @@
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.TouchCalibration;
+import android.os.CombinedVibrationEffect;
+import android.hardware.input.IInputSensorEventListener;
+import android.hardware.input.InputSensorInfo;
 import android.os.IBinder;
 import android.os.VibrationEffect;
 import android.view.InputDevice;
@@ -85,12 +88,15 @@
 
     // Input device vibrator control.
     void vibrate(int deviceId, in VibrationEffect effect, IBinder token);
+    void vibrateCombined(int deviceId, in CombinedVibrationEffect effect, IBinder token);
     void cancelVibrate(int deviceId, IBinder token);
+    int[] getVibratorIds(int deviceId);
+    boolean isVibrating(int deviceId);
 
     void setPointerIconType(int typeId);
     void setCustomPointerIcon(in PointerIcon icon);
 
-    void requestPointerCapture(IBinder windowToken, boolean enabled);
+    oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);
 
     /** Create an input monitor for gestures. */
     InputMonitor monitorGestureInput(String name, int displayId);
@@ -101,4 +107,17 @@
     // Remove the runtime association between the input port and the display port. Any existing
     // static association for the cleared input port will be restored.
     void removePortAssociation(in String inputPort);
+
+    InputSensorInfo[] getSensorList(int deviceId);
+
+    boolean registerSensorListener(IInputSensorEventListener listener);
+
+    void unregisterSensorListener(IInputSensorEventListener listener);
+
+    boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+                int maxBatchReportLatencyUs);
+
+    void disableSensor(int deviceId, int sensorType);
+
+    boolean flushSensor(int deviceId, int sensorType);
 }
diff --git a/core/java/android/hardware/input/IInputSensorEventListener.aidl b/core/java/android/hardware/input/IInputSensorEventListener.aidl
new file mode 100644
index 0000000..508f590
--- /dev/null
+++ b/core/java/android/hardware/input/IInputSensorEventListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+/** @hide */
+interface IInputSensorEventListener {
+    /* Called when there is a new sensor event. */
+    oneway void onInputSensorChanged(int deviceId, int sensorId, int accuracy, long timestamp,
+            in float[] values);
+
+    /* Called when the accuracy of the registered sensor has changed. */
+    oneway void onInputSensorAccuracyChanged(int deviceId, int sensorId, int accuracy);
+}
diff --git a/core/java/android/hardware/input/InputDeviceSensorManager.java b/core/java/android/hardware/input/InputDeviceSensorManager.java
new file mode 100644
index 0000000..56c2cdd
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceSensorManager.java
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.NonNull;
+import android.hardware.HardwareBuffer;
+import android.hardware.Sensor;
+import android.hardware.SensorAdditionalInfo;
+import android.hardware.SensorDirectChannel;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEventListener;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.MemoryFile;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.InputDevice;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Sensor manager implementation that communicates with the input device
+ * sensors.
+ * @hide
+ */
+public class InputDeviceSensorManager implements InputManager.InputDeviceListener {
+    private static final String TAG = "InputDeviceSensorManager";
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_SENSOR_ACCURACY_CHANGED = 1;
+    private static final int MSG_SENSOR_CHANGED = 2;
+
+    private InputManager mInputManager;
+
+    // sensor map from device id to sensor list
+    @GuardedBy("mInputSensorLock")
+    private final Map<Integer, List<Sensor>> mSensors = new HashMap<>();
+
+    private final Object mInputSensorLock = new Object();
+    private InputSensorEventListener mInputServiceSensorListener;
+    @GuardedBy("mInputSensorLock")
+    private final ArrayList<InputSensorEventListenerDelegate> mInputSensorEventListeners =
+            new ArrayList<InputSensorEventListenerDelegate>();
+    private HandlerThread mSensorThread = null;
+    private Handler mSensorHandler = null;
+
+    public InputDeviceSensorManager(InputManager inputManager) {
+        mInputManager = inputManager;
+
+        mSensorThread = new HandlerThread("SensorThread");
+        mSensorThread.start();
+        mSensorHandler = new Handler(mSensorThread.getLooper());
+
+        // Register the input device listener
+        mInputManager.registerInputDeviceListener(this, mSensorHandler);
+        // Initialize the sensor list
+        initializeSensors();
+    }
+
+    /*
+     * Get SensorManager object for specific input device
+     *
+     * @param deviceId Input device ID
+     * @return SensorManager object for input device
+     */
+    SensorManager getSensorManager(int deviceId) {
+        return new InputSensorManager(deviceId);
+    }
+
+    /*
+     * Update input device sensor info for specified input device ID.
+     */
+    private void updateInputDeviceSensorInfoLocked(int deviceId) {
+        final InputDevice inputDevice = InputDevice.getDevice(deviceId);
+        if (inputDevice.hasSensor()) {
+            final InputSensorInfo[] sensorInfos =
+                    mInputManager.getSensorList(deviceId);
+            populateSensorsForInputDeviceLocked(deviceId, sensorInfos);
+        }
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+        synchronized (mInputSensorLock) {
+            if (!mSensors.containsKey(deviceId)) {
+                updateInputDeviceSensorInfoLocked(deviceId);
+            } else {
+                Slog.e(TAG, "Received 'device added' notification for device " + deviceId
+                        + ", but it is already in the list");
+            }
+        }
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        synchronized (mInputSensorLock) {
+            mSensors.remove(deviceId);
+        }
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        synchronized (mInputSensorLock) {
+            if (mSensors.containsKey(deviceId)) {
+                mSensors.remove(deviceId);
+            }
+            updateInputDeviceSensorInfoLocked(deviceId);
+        }
+    }
+
+    private static boolean sensorEquals(@NonNull Sensor lhs, @NonNull Sensor rhs) {
+        if (lhs.getType() == rhs.getType() && lhs.getId() == rhs.getId()) {
+            return true;
+        }
+        return false;
+    }
+
+    private void populateSensorsForInputDeviceLocked(int deviceId, InputSensorInfo[] sensorInfos) {
+        List<Sensor> sensors = new ArrayList<Sensor>();
+        for (int i = 0; i < sensorInfos.length; i++) {
+            Sensor sensor = new Sensor(sensorInfos[i]);
+            if (DEBUG) {
+                Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType() + " added");
+            }
+            sensors.add(sensor);
+        }
+        mSensors.put(deviceId, sensors);
+    }
+
+    private void initializeSensors() {
+        synchronized (mInputSensorLock) {
+            mSensors.clear();
+            int[] deviceIds = mInputManager.getInputDeviceIds();
+            for (int i = 0; i < deviceIds.length; i++) {
+                final int deviceId = deviceIds[i];
+                updateInputDeviceSensorInfoLocked(deviceId);
+            }
+        }
+    }
+
+    /**
+     * Get a sensor object for input device, with specific sensor type.
+     * @param deviceId The input devicd ID
+     * @param sensorType The sensor type
+     * @return The sensor object if exists or null
+     */
+    @GuardedBy("mInputSensorLock")
+    private Sensor getInputDeviceSensorLocked(int deviceId, int sensorType) {
+        List<Sensor> sensors = mSensors.get(deviceId);
+        for (Sensor sensor : sensors) {
+            if (sensor.getType() == sensorType) {
+                return sensor;
+            }
+        }
+        return null;
+    }
+
+    @GuardedBy("mInputSensorLock")
+    private int findSensorEventListenerLocked(SensorEventListener listener) {
+        for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+            if (mInputSensorEventListeners.get(i).getListener() == listener) {
+                return i;
+            }
+        }
+        return Integer.MIN_VALUE;
+    }
+
+    private void onInputSensorChanged(int deviceId, int sensorType, int accuracy, long timestamp,
+            float[] values) {
+        if (DEBUG) {
+            Slog.d(TAG, "Sensor changed: deviceId =" + deviceId
+                    + " timestamp=" + timestamp + " sensorType=" + sensorType);
+        }
+        synchronized (mInputSensorLock) {
+            SensorEvent event = createSensorEvent(
+                    InputDevice.getDevice(deviceId), sensorType, accuracy, timestamp, values);
+            if (event == null) {
+                Slog.wtf(TAG, "Failed to create SensorEvent.");
+                return;
+            }
+            for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+                InputSensorEventListenerDelegate listener =
+                        mInputSensorEventListeners.get(i);
+                if (listener.hasSensorRegistered(deviceId, sensorType)) {
+                    listener.sendSensorChanged(event);
+                }
+            }
+        }
+    }
+
+    private void onInputSensorAccuracyChanged(int deviceId, int sensorType, int accuracy) {
+        if (DEBUG) {
+            Slog.d(TAG, "Sensor accuracy changed: "
+                    + "accuracy=" + accuracy + ", sensorType=" + sensorType);
+        }
+        synchronized (mInputSensorLock) {
+            for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+                InputSensorEventListenerDelegate listener =
+                        mInputSensorEventListeners.get(i);
+                if (listener.hasSensorRegistered(deviceId, sensorType)) {
+                    listener.sendSensorAccuracyChanged(deviceId, sensorType, accuracy);
+                }
+            }
+        }
+    }
+
+    private final class InputSensorEventListener extends IInputSensorEventListener.Stub {
+        @Override
+        public void onInputSensorChanged(int deviceId, int sensorType, int accuracy, long timestamp,
+                float[] values) throws RemoteException {
+            InputDeviceSensorManager.this.onInputSensorChanged(
+                    deviceId, sensorType, accuracy, timestamp, values);
+        }
+
+        @Override
+        public void onInputSensorAccuracyChanged(int deviceId, int sensorType, int accuracy)
+                throws RemoteException {
+            InputDeviceSensorManager.this.onInputSensorAccuracyChanged(deviceId, sensorType,
+                    accuracy);
+        }
+
+    }
+
+    private static final class InputSensorEventListenerDelegate extends Handler {
+        private final SensorEventListener mListener;
+        private final int mDelayUs;
+        private final int mMaxBatchReportLatencyUs;
+        private List<Sensor> mSensors = new ArrayList<Sensor>();
+
+        InputSensorEventListenerDelegate(SensorEventListener listener, Sensor sensor,
+                int delayUs, int maxBatchReportLatencyUs, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper());
+            mListener = listener;
+            mSensors.add(sensor);
+            mDelayUs = delayUs;
+            mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+        }
+
+        public List<Sensor> getSensors() {
+            return mSensors;
+        }
+
+        public boolean isEmpty() {
+            return mSensors.isEmpty();
+        }
+
+        /**
+         * Remove sensor from sensor list for listener
+         */
+        public void removeSensor(Sensor sensor) {
+            // If sensor is not specified the listener will be unregistered for all sensors
+            // and the sensor list is cleared.
+            if (sensor == null) {
+                mSensors.clear();
+            }
+            for (Sensor s : mSensors) {
+                if (sensorEquals(s, sensor)) {
+                    mSensors.remove(sensor);
+                }
+            }
+        }
+
+        /**
+         * Add a sensor to listener's sensor list
+         */
+        public void addSensor(@NonNull Sensor sensor) {
+            for (Sensor s : mSensors) {
+                if (sensorEquals(s, sensor)) {
+                    Slog.w(TAG, "Adding sensor " + sensor + " already exist!");
+                    return;
+                }
+            }
+            mSensors.add(sensor);
+        }
+
+        /**
+         * Check if the listener has been registered to the sensor
+         * @param deviceId The input device ID of the sensor
+         * @param sensorType The sensor type of the sensor
+         * @return true if specified sensor is registered for the listener.
+         */
+        public boolean hasSensorRegistered(int deviceId, int sensorType) {
+            for (Sensor sensor : mSensors) {
+                if (sensor.getType() == sensorType && sensor.getId() == deviceId) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Get listener handle for the delegate
+         */
+        public SensorEventListener getListener() {
+            return mListener;
+        }
+
+        /**
+         * Send sensor changed message
+         */
+        public void sendSensorChanged(SensorEvent event) {
+            SomeArgs args = SomeArgs.obtain();
+            obtainMessage(MSG_SENSOR_CHANGED, event).sendToTarget();
+        }
+
+        /**
+         * Send sensor accuracy changed message
+         */
+        public void sendSensorAccuracyChanged(int deviceId, int sensorType, int accuracy) {
+            SomeArgs args = SomeArgs.obtain();
+            obtainMessage(MSG_SENSOR_ACCURACY_CHANGED, deviceId, sensorType, accuracy)
+                    .sendToTarget();
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SENSOR_ACCURACY_CHANGED: {
+                    final int deviceId = msg.arg1;
+                    final int sensorType = msg.arg2;
+                    final int accuracy = (int) msg.obj;
+                    for (Sensor sensor : mSensors) {
+                        if (sensor.getId() == deviceId && sensor.getType() == sensorType) {
+                            mListener.onAccuracyChanged(sensor, accuracy);
+                        }
+                    }
+                    break;
+                }
+                case MSG_SENSOR_CHANGED: {
+                    SensorEvent event = (SensorEvent) msg.obj;
+                    mListener.onSensorChanged(event);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Create SensorEvent object for input device, with specified device ID, sensor Type,
+     * sensor event timestamp, accuracy, and sensor values.
+     */
+    private SensorEvent createSensorEvent(InputDevice inputDevice, int sensorType, int accuracy,
+            long timestamp, float[] values) {
+        synchronized (mInputSensorLock) {
+            Sensor sensor = getInputDeviceSensorLocked(inputDevice.getId(), sensorType);
+            if (sensor == null) {
+                Slog.wtf(TAG, "Can't get sensor type " + sensorType + " for input device "
+                        + inputDevice);
+            }
+            SensorEvent event = new SensorEvent(sensor, accuracy, timestamp, values);
+            if (event == null) {
+                Slog.wtf(TAG, "Failed to create SensorEvent.");
+            }
+            return event;
+        }
+    }
+
+    /**
+     * Return the default sensor object for input device, for specific sensor type.
+     */
+    private Sensor getSensorForInputDevice(int deviceId, int type) {
+        synchronized (mInputSensorLock) {
+            for (Map.Entry<Integer, List<Sensor>> entry : mSensors.entrySet()) {
+                for (Sensor sensor : entry.getValue()) {
+                    if (sensor.getId() == deviceId && sensor.getType() == type) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType());
+                        }
+                        return sensor;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return list of sensors that belong to an input device, specified by input device ID.
+     */
+    private List<Sensor> getFullSensorListForDevice(int deviceId) {
+        List<Sensor> sensors = new ArrayList<Sensor>();
+        synchronized (mInputSensorLock) {
+            for (Map.Entry<Integer, List<Sensor>> entry : mSensors.entrySet()) {
+                for (Sensor sensor : entry.getValue()) {
+                    if (sensor.getId() == deviceId) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType());
+                        }
+                        sensors.add(sensor);
+                    }
+                }
+            }
+        }
+        return sensors;
+    }
+
+    private boolean registerListenerInternal(SensorEventListener listener, Sensor sensor,
+            int delayUs, int maxBatchReportLatencyUs, Handler handler) {
+        if (DEBUG) {
+            Slog.d(TAG, "registerListenerImpl listener=" + listener + " sensor=" + sensor
+                    + " delayUs=" + delayUs
+                    + " maxBatchReportLatencyUs=" + maxBatchReportLatencyUs);
+        }
+        if (listener == null) {
+            Slog.e(TAG, "listener is null");
+            return false;
+        }
+
+        if (sensor == null) {
+            Slog.e(TAG, "sensor is null");
+            return false;
+        }
+
+        // Trigger Sensors should use the requestTriggerSensor call.
+        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+            Slog.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
+            return false;
+        }
+        if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
+            Slog.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
+            return false;
+        }
+
+        if (getSensorForInputDevice(sensor.getId(), sensor.getType()) != null) {
+            synchronized (mInputSensorLock) {
+                final int deviceId = sensor.getId();
+                InputDevice inputDevice = InputDevice.getDevice(deviceId);
+                if (!inputDevice.hasSensor()) {
+                    Slog.e(TAG, "The device doesn't have the sensor:" + sensor);
+                    return false;
+                }
+                if (!mInputManager.enableSensor(deviceId, sensor.getType(), delayUs,
+                        maxBatchReportLatencyUs)) {
+                    Slog.e(TAG, "Can't enable the sensor:" + sensor);
+                    return false;
+                }
+            }
+        }
+
+        synchronized (mInputSensorLock) {
+            // Register the InputManagerService sensor listener if not yet.
+            if (mInputServiceSensorListener == null) {
+                mInputServiceSensorListener = new InputSensorEventListener();
+                if (!mInputManager.registerSensorListener(mInputServiceSensorListener)) {
+                    Slog.e(TAG, "Failed registering the sensor listener");
+                    return false;
+                }
+            }
+
+            int idx = findSensorEventListenerLocked(listener);
+            if (idx < 0) {
+                InputSensorEventListenerDelegate d =
+                        new InputSensorEventListenerDelegate(listener, sensor, delayUs,
+                                maxBatchReportLatencyUs,
+                                handler == null ? mSensorHandler : handler);
+                mInputSensorEventListeners.add(d);
+            } else {
+                // The listener is already registered, see if it wants to listen to more sensors.
+                mInputSensorEventListeners.get(idx).addSensor(sensor);
+            }
+        }
+
+        return true;
+    }
+
+    private void unregisterListenerInternal(SensorEventListener listener, Sensor sensor) {
+        if (DEBUG) {
+            Slog.d(TAG, "unregisterListenerImpl listener=" + listener + " sensor=" + sensor);
+        }
+        if (listener == null) {  // it's OK for the sensor to be null
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        synchronized (mInputSensorLock) {
+            int idx = findSensorEventListenerLocked(listener);
+            // Track the sensor types and the device Id the listener has registered.
+            final List<Sensor> sensorsRegistered;
+            if (idx >= 0) {
+                InputSensorEventListenerDelegate delegate =
+                        mInputSensorEventListeners.get(idx);
+                sensorsRegistered = new ArrayList<Sensor>(delegate.getSensors());
+                // Get the sensor types the listener is listening to
+                delegate.removeSensor(sensor);
+                if (delegate.isEmpty()) {
+                    // If no sensors to listen, remove the listener delegate
+                    mInputSensorEventListeners.remove(idx);
+                }
+            } else {
+                Slog.e(TAG, "Listener is not registered");
+                return;
+            }
+            // If no delegation remains, unregister the listener to input service
+            if (mInputServiceSensorListener != null && mInputSensorEventListeners.size() == 0) {
+                mInputManager.unregisterSensorListener(mInputServiceSensorListener);
+                mInputServiceSensorListener = null;
+            }
+            // For each sensor type check if it is still in use by other listeners.
+            for (Sensor s : sensorsRegistered) {
+                final int deviceId = s.getId();
+                final int sensorType = s.getType();
+                // See if we can disable the sensor
+                boolean enableSensor = false;
+                for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+                    InputSensorEventListenerDelegate delegate =
+                            mInputSensorEventListeners.get(i);
+                    if (delegate.hasSensorRegistered(deviceId, sensorType)) {
+                        enableSensor = true;
+                        Slog.w(TAG, "device " + deviceId + " still uses sensor " + sensorType);
+                        break;
+                    }
+                }
+                // Sensor is not listened, disable it.
+                if (!enableSensor) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "device " + deviceId + " sensor " + sensorType + " disabled");
+                    }
+                    mInputManager.disableSensor(deviceId, sensorType);
+                }
+            }
+        }
+    }
+
+    private boolean flush(SensorEventListener listener) {
+        synchronized (mInputSensorLock) {
+            int idx = findSensorEventListenerLocked(listener);
+            if (idx < 0) {
+                return false;
+            }
+            for (Sensor sensor : mInputSensorEventListeners.get(idx).getSensors()) {
+                final int deviceId = sensor.getId();
+                if (!mInputManager.flushSensor(deviceId, sensor.getType())) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Sensor Manager class associated with specific input device
+     */
+    public class InputSensorManager extends SensorManager {
+        // Input device ID that the sensors belong to
+        final int mId;
+
+        InputSensorManager(int deviceId) {
+            mId = deviceId;
+        }
+
+        @Override
+        public Sensor getDefaultSensor(int type) {
+            return getSensorForInputDevice(mId, type);
+        }
+
+        @Override
+        protected List<Sensor> getFullSensorList() {
+            return getFullSensorListForDevice(mId);
+        }
+
+        @Override
+        protected List<Sensor> getFullDynamicSensorList() {
+            return new ArrayList<>();
+        }
+
+        @Override
+        protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
+                int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
+            return registerListenerInternal(listener, sensor, delayUs,
+                    maxBatchReportLatencyUs, handler);
+        }
+
+        @Override
+        protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
+            unregisterListenerInternal(listener, sensor);
+        }
+
+        @Override
+        protected boolean flushImpl(SensorEventListener listener) {
+            return flush(listener);
+        }
+
+        @Override
+        protected SensorDirectChannel createDirectChannelImpl(MemoryFile memoryFile,
+                HardwareBuffer hardwareBuffer) {
+            return null;
+        }
+
+        @Override
+        protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
+
+        }
+
+        @Override
+        protected int configureDirectChannelImpl(SensorDirectChannel channel, Sensor s, int rate) {
+            return 0;
+        }
+
+        @Override
+        protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback,
+                Handler handler) {
+
+        }
+
+        @Override
+        protected void unregisterDynamicSensorCallbackImpl(
+                DynamicSensorCallback callback) {
+
+        }
+
+        @Override
+        protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
+            return true;
+        }
+
+        @Override
+        protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
+                boolean disable) {
+            return true;
+        }
+
+        @Override
+        protected boolean initDataInjectionImpl(boolean enable) {
+            return false;
+        }
+
+        @Override
+        protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
+                long timestamp) {
+            return false;
+        }
+
+        @Override
+        protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
+            return false;
+        }
+    }
+
+}
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
new file mode 100644
index 0000000..c60d6ce
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Vibrator implementation that communicates with the input device vibrators.
+ */
+final class InputDeviceVibrator extends Vibrator {
+    // mDeviceId represents InputDevice ID the vibrator belongs to
+    private final int mDeviceId;
+    private final int mVibratorId;
+    private final Binder mToken;
+    private final InputManager mInputManager;
+
+    InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) {
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mVibratorId = vibratorId;
+        mToken = new Binder();
+    }
+
+    @Override
+    public boolean hasVibrator() {
+        return true;
+    }
+
+    @Override
+    public boolean isVibrating() {
+        return mInputManager.isVibrating(mDeviceId);
+    }
+
+    /* TODO: b/161634264 Support Vibrator listener API in input devices */
+    @Override
+    public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "addVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public void addVibratorStateListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "addVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+        throw new UnsupportedOperationException(
+            "removeVibratorStateListener not supported in InputDeviceVibrator");
+    }
+
+    @Override
+    public boolean hasAmplitudeControl() {
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
+            String reason, @NonNull VibrationAttributes attributes) {
+        mInputManager.vibrate(mDeviceId, effect, mToken);
+    }
+
+    @Override
+    public void cancel() {
+        mInputManager.cancelVibrate(mDeviceId, mToken);
+    }
+}
diff --git a/core/java/android/hardware/input/InputDeviceVibratorManager.java b/core/java/android/hardware/input/InputDeviceVibratorManager.java
new file mode 100644
index 0000000..a381b02
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceVibratorManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.os.Binder;
+import android.os.CombinedVibrationEffect;
+import android.os.NullVibrator;
+import android.os.Vibrator;
+import android.os.VibratorManager;
+import android.util.SparseArray;
+import android.view.InputDevice;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Vibrator manager implementation that communicates with the input device vibrators.
+ *
+ * @hide
+ */
+public class InputDeviceVibratorManager extends VibratorManager
+        implements InputManager.InputDeviceListener {
+    private static final String TAG = "InputDeviceVibratorManager";
+    private static final boolean DEBUG = false;
+
+    private final Binder mToken;
+    private final InputManager mInputManager;
+
+    // The input device Id.
+    private final int mDeviceId;
+    // Vibrator map from Vibrator Id to Vibrator
+    @GuardedBy("mVibrators")
+    private final SparseArray<Vibrator> mVibrators = new SparseArray<>();
+
+    public InputDeviceVibratorManager(InputManager inputManager, int deviceId) {
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mToken = new Binder();
+
+        initializeVibrators();
+    }
+
+    private void initializeVibrators() {
+        synchronized (mVibrators) {
+            mVibrators.clear();
+            InputDevice inputDevice = InputDevice.getDevice(mDeviceId);
+            final int[] vibratorIds =
+                    mInputManager.getVibratorIds(mDeviceId);
+            for (int i = 0; i < vibratorIds.length; i++) {
+                mVibrators.put(vibratorIds[i],
+                        new InputDeviceVibrator(mInputManager, mDeviceId, vibratorIds[i]));
+            }
+        }
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        synchronized (mVibrators) {
+            if (deviceId == mDeviceId) {
+                mVibrators.clear();
+            }
+        }
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        if (deviceId == mDeviceId) {
+            initializeVibrators();
+        }
+    }
+
+    @Override
+    public int[] getVibratorIds() {
+        synchronized (mVibrators) {
+            int[] vibratorIds = new int[mVibrators.size()];
+            for (int idx = 0; idx < mVibrators.size(); idx++) {
+                vibratorIds[idx++] = mVibrators.keyAt(idx);
+            }
+            return vibratorIds;
+        }
+    }
+
+    @Override
+    public Vibrator getVibrator(int vibratorId) {
+        synchronized (mVibrators) {
+            if (mVibrators.contains(vibratorId)) {
+                return mVibrators.get(vibratorId);
+            }
+        }
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public Vibrator getDefaultVibrator() {
+        // Returns vibrator ID 0
+        synchronized (mVibrators) {
+            if (mVibrators.size() > 0) {
+                return mVibrators.valueAt(0);
+            }
+        }
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public void vibrate(CombinedVibrationEffect effect) {
+        mInputManager.vibrate(mDeviceId, effect, mToken);
+    }
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 81ea2f5..300d99b 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -17,7 +17,6 @@
 package android.hardware.input;
 
 import android.Manifest;
-import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -29,9 +28,10 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.os.Binder;
+import android.hardware.SensorManager;
 import android.os.BlockUntrustedTouchesMode;
 import android.os.Build;
+import android.os.CombinedVibrationEffect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.InputEventInjectionSync;
@@ -41,9 +41,9 @@
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemClock;
-import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.os.VibratorManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
@@ -64,7 +64,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.Executor;
 
 /**
  * Provides information about input devices and available key layouts.
@@ -102,6 +101,7 @@
     private TabletModeChangedListener mTabletModeChangedListener;
     private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
 
+    private InputDeviceSensorManager mInputDeviceSensorManager;
     /**
      * Broadcast Action: Query available keyboard layouts.
      * <p>
@@ -210,6 +210,14 @@
     public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L;
 
     /**
+     * Check whether apps are using FLAG_SLIPPERY for their windows. We expect that this flag is
+     * only used by the system components. If so, we can lock it down.
+     * @hide
+     */
+    @ChangeId
+    public static final long BLOCK_FLAG_SLIPPERY = android.os.IInputConstants.BLOCK_FLAG_SLIPPERY;
+
+    /**
      * Input Event Injection Synchronization Mode: None.
      * Never blocks.  Injection is asynchronous and is assumed always to be successful.
      * @hide
@@ -285,6 +293,18 @@
     }
 
     /**
+     * Clear the instance of the input manager.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static void clearInstance() {
+        synchronized (InputManager.class) {
+            sInstance = null;
+        }
+    }
+
+    /**
      * Gets an instance of the input manager.
      *
      * @return The input manager instance.
@@ -1146,6 +1166,86 @@
     }
 
     /**
+     * Get sensors information as list.
+     *
+     * @hide
+     */
+    public InputSensorInfo[] getSensorList(int deviceId) {
+        try {
+            return mIm.getSensorList(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Enable input device sensor
+     *
+     * @hide
+     */
+    public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+            int maxBatchReportLatencyUs) {
+        try {
+            return mIm.enableSensor(deviceId, sensorType, samplingPeriodUs,
+                    maxBatchReportLatencyUs);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Enable input device sensor
+     *
+     * @hide
+     */
+    public void disableSensor(int deviceId, int sensorType) {
+        try {
+            mIm.disableSensor(deviceId, sensorType);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Flush input device sensor
+     *
+     * @hide
+     */
+    public boolean flushSensor(int deviceId, int sensorType) {
+        try {
+            return mIm.flushSensor(deviceId, sensorType);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Register input device sensor listener
+     *
+     * @hide
+     */
+    public boolean registerSensorListener(IInputSensorEventListener listener) {
+        try {
+            return mIm.registerSensorListener(listener);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister input device sensor listener
+     *
+     * @hide
+     */
+    public void unregisterSensorListener(IInputSensorEventListener listener) {
+        try {
+            mIm.unregisterSensorListener(listener);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Add a runtime association between the input port and the display port. This overrides any
      * static associations.
      * @param inputPort The port of the input device.
@@ -1283,12 +1383,92 @@
     }
 
     /**
-     * Gets a vibrator service associated with an input device, assuming it has one.
+     * Gets a vibrator service associated with an input device, always create a new instance.
      * @return The vibrator, never null.
      * @hide
      */
-    public Vibrator getInputDeviceVibrator(int deviceId) {
-        return new InputDeviceVibrator(deviceId);
+    public Vibrator getInputDeviceVibrator(int deviceId, int vibratorId) {
+        return new InputDeviceVibrator(this, deviceId, vibratorId);
+    }
+
+    /**
+     * Gets a vibrator manager service associated with an input device, always create a new
+     * instance.
+     * @return The vibrator manager, never null.
+     * @hide
+     */
+    @NonNull
+    public VibratorManager getInputDeviceVibratorManager(int deviceId) {
+        return new InputDeviceVibratorManager(InputManager.this, deviceId);
+    }
+
+    /*
+     * Get the list of device vibrators
+     * @return The list of vibrators IDs
+     */
+    int[] getVibratorIds(int deviceId) {
+        try {
+            return mIm.getVibratorIds(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Perform vibration effect
+     */
+    void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
+        try {
+            mIm.vibrate(deviceId, effect, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Perform combined vibration effect
+     */
+    void vibrate(int deviceId, CombinedVibrationEffect effect, IBinder token) {
+        try {
+            mIm.vibrateCombined(deviceId, effect, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Cancel an ongoing vibration
+     */
+    void cancelVibrate(int deviceId, IBinder token) {
+        try {
+            mIm.cancelVibrate(deviceId, token);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /*
+     * Check if input device is vibrating
+     */
+    boolean isVibrating(int deviceId)  {
+        try {
+            return mIm.isVibrating(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets a sensor manager service associated with an input device, always create a new instance.
+     * @return The sensor manager, never null.
+     * @hide
+     */
+    @NonNull
+    public SensorManager getInputDeviceSensorManager(int deviceId) {
+        if (mInputDeviceSensorManager == null) {
+            mInputDeviceSensorManager = new InputDeviceSensorManager(this);
+        }
+        return mInputDeviceSensorManager.getSensorManager(deviceId);
     }
 
     /**
@@ -1401,72 +1581,4 @@
             }
         }
     }
-
-    private final class InputDeviceVibrator extends Vibrator {
-        private final int mDeviceId;
-        private final Binder mToken;
-
-        public InputDeviceVibrator(int deviceId) {
-            mDeviceId = deviceId;
-            mToken = new Binder();
-        }
-
-        @Override
-        public boolean hasVibrator() {
-            return true;
-        }
-
-        @Override
-        public boolean isVibrating() {
-            throw new UnsupportedOperationException(
-                "isVibrating not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "addVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void addVibratorStateListener(
-                @NonNull @CallbackExecutor Executor executor,
-                @NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "addVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
-            throw new UnsupportedOperationException(
-                "removeVibratorStateListener not supported in InputDeviceVibrator");
-        }
-
-        @Override
-        public boolean hasAmplitudeControl() {
-            return true;
-        }
-
-        /**
-         * @hide
-         */
-        @Override
-        public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
-                String reason, @NonNull VibrationAttributes attributes) {
-            try {
-                mIm.vibrate(mDeviceId, effect, mToken);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-        }
-
-        @Override
-        public void cancel() {
-            try {
-                mIm.cancelVibrate(mDeviceId, mToken);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-        }
-    }
 }
diff --git a/core/java/android/hardware/input/InputSensorInfo.aidl b/core/java/android/hardware/input/InputSensorInfo.aidl
new file mode 100644
index 0000000..d9a604a
--- /dev/null
+++ b/core/java/android/hardware/input/InputSensorInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+parcelable InputSensorInfo;
diff --git a/core/java/android/hardware/input/InputSensorInfo.java b/core/java/android/hardware/input/InputSensorInfo.java
new file mode 100644
index 0000000..99b1879
--- /dev/null
+++ b/core/java/android/hardware/input/InputSensorInfo.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+/**
+ * This class represents a motion sensor for input devices.
+ *
+ * @hide
+ */
+@DataClass(
+        genToString = true,
+        genHiddenConstructor = true,
+        genHiddenConstDefs = true)
+public class InputSensorInfo implements Parcelable {
+
+    private @NonNull String  mName;
+    private @NonNull String  mVendor;
+    private int     mVersion;
+    private int     mHandle;
+    private int     mType;
+    private float   mMaxRange;
+    private float   mResolution;
+    private float   mPower;
+    private int     mMinDelay;
+    private int     mFifoReservedEventCount;
+    private int     mFifoMaxEventCount;
+    private @NonNull String  mStringType;
+    private @NonNull String  mRequiredPermission;
+    private int     mMaxDelay;
+    private int     mFlags;
+    private int     mId;
+
+
+
+    // Code below generated by codegen v1.0.20.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/InputSensorInfo.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new InputSensorInfo.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public InputSensorInfo(
+            @NonNull String name,
+            @NonNull String vendor,
+            int version,
+            int handle,
+            int type,
+            float maxRange,
+            float resolution,
+            float power,
+            int minDelay,
+            int fifoReservedEventCount,
+            int fifoMaxEventCount,
+            @NonNull String stringType,
+            @NonNull String requiredPermission,
+            int maxDelay,
+            int flags,
+            int id) {
+        this.mName = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mName);
+        this.mVendor = vendor;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mVendor);
+        this.mVersion = version;
+        this.mHandle = handle;
+        this.mType = type;
+        this.mMaxRange = maxRange;
+        this.mResolution = resolution;
+        this.mPower = power;
+        this.mMinDelay = minDelay;
+        this.mFifoReservedEventCount = fifoReservedEventCount;
+        this.mFifoMaxEventCount = fifoMaxEventCount;
+        this.mStringType = stringType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mStringType);
+        this.mRequiredPermission = requiredPermission;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRequiredPermission);
+        this.mMaxDelay = maxDelay;
+        this.mFlags = flags;
+        this.mId = id;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String getName() {
+        return mName;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String getVendor() {
+        return mVendor;
+    }
+
+    @DataClass.Generated.Member
+    public int getVersion() {
+        return mVersion;
+    }
+
+    @DataClass.Generated.Member
+    public int getHandle() {
+        return mHandle;
+    }
+
+    @DataClass.Generated.Member
+    public int getType() {
+        return mType;
+    }
+
+    @DataClass.Generated.Member
+    public float getMaxRange() {
+        return mMaxRange;
+    }
+
+    @DataClass.Generated.Member
+    public float getResolution() {
+        return mResolution;
+    }
+
+    @DataClass.Generated.Member
+    public float getPower() {
+        return mPower;
+    }
+
+    @DataClass.Generated.Member
+    public int getMinDelay() {
+        return mMinDelay;
+    }
+
+    @DataClass.Generated.Member
+    public int getFifoReservedEventCount() {
+        return mFifoReservedEventCount;
+    }
+
+    @DataClass.Generated.Member
+    public int getFifoMaxEventCount() {
+        return mFifoMaxEventCount;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String getStringType() {
+        return mStringType;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String getRequiredPermission() {
+        return mRequiredPermission;
+    }
+
+    @DataClass.Generated.Member
+    public int getMaxDelay() {
+        return mMaxDelay;
+    }
+
+    @DataClass.Generated.Member
+    public int getFlags() {
+        return mFlags;
+    }
+
+    @DataClass.Generated.Member
+    public int getId() {
+        return mId;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InputSensorInfo { " +
+                "name = " + mName + ", " +
+                "vendor = " + mVendor + ", " +
+                "version = " + mVersion + ", " +
+                "handle = " + mHandle + ", " +
+                "type = " + mType + ", " +
+                "maxRange = " + mMaxRange + ", " +
+                "resolution = " + mResolution + ", " +
+                "power = " + mPower + ", " +
+                "minDelay = " + mMinDelay + ", " +
+                "fifoReservedEventCount = " + mFifoReservedEventCount + ", " +
+                "fifoMaxEventCount = " + mFifoMaxEventCount + ", " +
+                "stringType = " + mStringType + ", " +
+                "requiredPermission = " + mRequiredPermission + ", " +
+                "maxDelay = " + mMaxDelay + ", " +
+                "flags = " + mFlags + ", " +
+                "id = " + mId +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeString(mName);
+        dest.writeString(mVendor);
+        dest.writeInt(mVersion);
+        dest.writeInt(mHandle);
+        dest.writeInt(mType);
+        dest.writeFloat(mMaxRange);
+        dest.writeFloat(mResolution);
+        dest.writeFloat(mPower);
+        dest.writeInt(mMinDelay);
+        dest.writeInt(mFifoReservedEventCount);
+        dest.writeInt(mFifoMaxEventCount);
+        dest.writeString(mStringType);
+        dest.writeString(mRequiredPermission);
+        dest.writeInt(mMaxDelay);
+        dest.writeInt(mFlags);
+        dest.writeInt(mId);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected InputSensorInfo(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        String name = in.readString();
+        String vendor = in.readString();
+        int version = in.readInt();
+        int handle = in.readInt();
+        int type = in.readInt();
+        float maxRange = in.readFloat();
+        float resolution = in.readFloat();
+        float power = in.readFloat();
+        int minDelay = in.readInt();
+        int fifoReservedEventCount = in.readInt();
+        int fifoMaxEventCount = in.readInt();
+        String stringType = in.readString();
+        String requiredPermission = in.readString();
+        int maxDelay = in.readInt();
+        int flags = in.readInt();
+        int id = in.readInt();
+
+        this.mName = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mName);
+        this.mVendor = vendor;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mVendor);
+        this.mVersion = version;
+        this.mHandle = handle;
+        this.mType = type;
+        this.mMaxRange = maxRange;
+        this.mResolution = resolution;
+        this.mPower = power;
+        this.mMinDelay = minDelay;
+        this.mFifoReservedEventCount = fifoReservedEventCount;
+        this.mFifoMaxEventCount = fifoMaxEventCount;
+        this.mStringType = stringType;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mStringType);
+        this.mRequiredPermission = requiredPermission;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRequiredPermission);
+        this.mMaxDelay = maxDelay;
+        this.mFlags = flags;
+        this.mId = id;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InputSensorInfo> CREATOR
+            = new Parcelable.Creator<InputSensorInfo>() {
+        @Override
+        public InputSensorInfo[] newArray(int size) {
+            return new InputSensorInfo[size];
+        }
+
+        @Override
+        public InputSensorInfo createFromParcel(@NonNull Parcel in) {
+            return new InputSensorInfo(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1605294854951L,
+            codegenVersion = "1.0.20",
+            sourceFile = "frameworks/base/core/java/android/hardware/input/InputSensorInfo.java",
+            inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mVendor\nprivate  int mVersion\nprivate  int mHandle\nprivate  int mType\nprivate  float mMaxRange\nprivate  float mResolution\nprivate  float mPower\nprivate  int mMinDelay\nprivate  int mFifoReservedEventCount\nprivate  int mFifoMaxEventCount\nprivate @android.annotation.NonNull java.lang.String mStringType\nprivate @android.annotation.NonNull java.lang.String mRequiredPermission\nprivate  int mMaxDelay\nprivate  int mFlags\nprivate  int mId\nclass InputSensorInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS
index 0313a40..25e02e1 100644
--- a/core/java/android/hardware/input/OWNERS
+++ b/core/java/android/hardware/input/OWNERS
@@ -1,2 +1,6 @@
+# Bug component: 136048
+
+include /services/core/java/com/android/server/input/OWNERS
+
 michaelwr@google.com
 svv@google.com
diff --git a/core/java/android/hardware/iris/OWNERS b/core/java/android/hardware/iris/OWNERS
new file mode 100644
index 0000000..33527f8
--- /dev/null
+++ b/core/java/android/hardware/iris/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 879035
+
+jaggies@google.com
diff --git a/core/java/android/hardware/lights/OWNERS b/core/java/android/hardware/lights/OWNERS
new file mode 100644
index 0000000..cb46a80
--- /dev/null
+++ b/core/java/android/hardware/lights/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/lights/OWNERS
diff --git a/core/java/android/hardware/location/OWNERS b/core/java/android/hardware/location/OWNERS
new file mode 100644
index 0000000..383321b
--- /dev/null
+++ b/core/java/android/hardware/location/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 880425
+
+mstogaitis@google.com
+wyattriley@google.com
+etn@google.com
+weiwa@google.com
diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/core/java/android/hardware/soundtrigger/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS
index 8ee72b5..8f2b39d 100644
--- a/core/java/android/hardware/usb/OWNERS
+++ b/core/java/android/hardware/usb/OWNERS
@@ -1,6 +1,4 @@
-badhri@google.com
-elaurent@google.com
+# Bug component: 175220
+
 moltmann@google.com
-albertccwang@google.com
-jameswei@google.com
-howardyen@google.com
\ No newline at end of file
+badhri@google.com
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6831eca..df9a7c2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1700,8 +1700,12 @@
         if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
             return false;
         }
-        if (mInputEditorInfo != null
-                && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
+        if ((mInputEditorInfo != null
+                && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0)
+                // If app window has portrait orientation, regardless of what display orientation
+                // is, IME shouldn't use fullscreen-mode.
+                || (mInputEditorInfo.internalImeOptions
+                        & EditorInfo.IME_FLAG_APP_WINDOW_PORTRAIT) != 0) {
             return false;
         }
         return true;
diff --git a/core/java/android/inputmethodservice/OWNERS b/core/java/android/inputmethodservice/OWNERS
index 4447197..e6a04da 100644
--- a/core/java/android/inputmethodservice/OWNERS
+++ b/core/java/android/inputmethodservice/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 34867
 set noparent
 
-include ../../../../services/core/java/com/android/server/inputmethod/OWNERS
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/core/java/android/metrics/OWNERS b/core/java/android/metrics/OWNERS
new file mode 100644
index 0000000..ba867e0
--- /dev/null
+++ b/core/java/android/metrics/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 26805
+
+cwren@android.com
+cwren@google.com
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..95a2f2e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -25,13 +25,13 @@
 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;
 import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -76,7 +76,6 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     NetworkState[] getAllNetworkState();
 
-    NetworkQuotaInfo getActiveNetworkQuotaInfo();
     boolean isActiveNetworkMetered();
 
     boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress,
@@ -235,4 +234,10 @@
                 in PersistableBundle extras);
 
     void systemReady();
+
+    void registerNetworkActivityListener(in INetworkActivityListener l);
+
+    void unregisterNetworkActivityListener(in INetworkActivityListener l);
+
+    boolean isDefaultNetworkActive();
 }
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 0676ad4..6780167 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -51,7 +51,7 @@
  * An agent manages the life cycle of a network. A network starts its
  * life cycle when {@link register} is called on NetworkAgent. The network
  * is then connecting. When full L3 connectivity has been established,
- * the agent shoud call {@link markConnected} to inform the system that
+ * the agent should call {@link markConnected} to inform the system that
  * this network is ready to use. When the network disconnects its life
  * ends and the agent should call {@link unregister}, at which point the
  * system will clean up and free resources.
@@ -94,12 +94,6 @@
     @Nullable
     private volatile Network mNetwork;
 
-    // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is
-    // that the legacy API uses NetworkInfo to convey the state, while the current API is
-    // exposing methods to manage it and generate it internally instead.
-    // TODO : remove this as soon as all agents have been converted.
-    private final boolean mIsLegacy;
-
     private final Handler mHandler;
     private volatile AsyncChannel mAsyncChannel;
     private final String LOG_TAG;
@@ -110,8 +104,6 @@
     private static final long BW_REFRESH_MIN_WIN_MS = 500;
     private boolean mBandwidthUpdateScheduled = false;
     private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false);
-    // Not used by legacy agents. Non-legacy agents use this to convert the NetworkAgent system API
-    // into the internal API of ConnectivityService.
     @NonNull
     private NetworkInfo mNetworkInfo;
     @NonNull
@@ -337,35 +329,6 @@
      */
     public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
 
-    /** @hide TODO: remove and replace usage with the public constructor. */
-    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
-            NetworkCapabilities nc, LinkProperties lp, int score) {
-        this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE);
-        // Register done by the constructor called in the previous line
-    }
-
-    /** @hide TODO: remove and replace usage with the public constructor. */
-    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
-            NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) {
-        this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE);
-        // Register done by the constructor called in the previous line
-    }
-
-    /** @hide TODO: remove and replace usage with the public constructor. */
-    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
-            NetworkCapabilities nc, LinkProperties lp, int score, int providerId) {
-        this(looper, context, logTag, ni, nc, lp, score, null, providerId);
-        // Register done by the constructor called in the previous line
-    }
-
-    /** @hide TODO: remove and replace usage with the public constructor. */
-    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
-            NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config,
-            int providerId) {
-        this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */);
-        register();
-    }
-
     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
         // The subtype can be changed with (TODO) setLegacySubtype, but it starts
         // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description.
@@ -393,7 +356,7 @@
             @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
         this(looper, context, logTag, nc, lp, score, config,
                 provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
-                getLegacyNetworkInfo(config), false /* legacy */);
+                getLegacyNetworkInfo(config));
     }
 
     private static class InitialConfiguration {
@@ -418,11 +381,9 @@
 
     private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
             @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
-            @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni,
-            boolean legacy) {
+            @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) {
         mHandler = new NetworkAgentHandler(looper);
         LOG_TAG = logTag;
-        mIsLegacy = legacy;
         mNetworkInfo = new NetworkInfo(ni);
         this.providerId = providerId;
         if (ni == null || nc == null || lp == null) {
@@ -696,11 +657,6 @@
      * Call {@link #unregister} to disconnect.
      */
     public void markConnected() {
-        if (mIsLegacy) {
-            throw new UnsupportedOperationException(
-                    "Legacy agents can't call markConnected.");
-        }
-        // |reason| cannot be used by the non-legacy agents
         mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,
                 mNetworkInfo.getExtraInfo());
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
@@ -713,9 +669,6 @@
      * the network is torn down and this agent can no longer be used.
      */
     public void unregister() {
-        if (mIsLegacy) {
-            throw new UnsupportedOperationException("Legacy agents can't call unregister.");
-        }
         // When unregistering an agent nobody should use the extrainfo (or reason) any more.
         mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */,
                 null /* extraInfo */);
@@ -735,9 +688,6 @@
      */
     @Deprecated
     public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
-        if (mIsLegacy) {
-            throw new UnsupportedOperationException("Legacy agents can't call setLegacySubtype.");
-        }
         mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
     }
@@ -760,9 +710,6 @@
      */
     @Deprecated
     public void setLegacyExtraInfo(@Nullable final String extraInfo) {
-        if (mIsLegacy) {
-            throw new UnsupportedOperationException("Legacy agents can't call setLegacyExtraInfo.");
-        }
         mNetworkInfo.setExtraInfo(extraInfo);
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
     }
@@ -773,9 +720,6 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final void sendNetworkInfo(NetworkInfo networkInfo) {
-        if (!mIsLegacy) {
-            throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo.");
-        }
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
     }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8dad11f..1a37fb9 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -975,6 +975,10 @@
         return mOwnerUid;
     }
 
+    private boolean equalsOwnerUid(@NonNull final NetworkCapabilities nc) {
+        return mOwnerUid == nc.mOwnerUid;
+    }
+
     /**
      * UIDs of packages that are administrators of this network, or empty if none.
      *
@@ -1684,6 +1688,7 @@
                 && equalsTransportInfo(that)
                 && equalsUids(that)
                 && equalsSSID(that)
+                && equalsOwnerUid(that)
                 && equalsPrivateDnsBroken(that)
                 && equalsRequestor(that)
                 && equalsAdministratorUids(that);
@@ -1697,17 +1702,18 @@
                 + ((int) (mUnwantedNetworkCapabilities >> 32) * 7)
                 + ((int) (mTransportTypes & 0xFFFFFFFF) * 11)
                 + ((int) (mTransportTypes >> 32) * 13)
-                + (mLinkUpBandwidthKbps * 17)
-                + (mLinkDownBandwidthKbps * 19)
+                + mLinkUpBandwidthKbps * 17
+                + mLinkDownBandwidthKbps * 19
                 + Objects.hashCode(mNetworkSpecifier) * 23
-                + (mSignalStrength * 29)
-                + Objects.hashCode(mUids) * 31
-                + Objects.hashCode(mSSID) * 37
-                + Objects.hashCode(mTransportInfo) * 41
-                + Objects.hashCode(mPrivateDnsBroken) * 43
-                + Objects.hashCode(mRequestorUid) * 47
-                + Objects.hashCode(mRequestorPackageName) * 53
-                + Arrays.hashCode(mAdministratorUids) * 59;
+                + mSignalStrength * 29
+                + mOwnerUid * 31
+                + Objects.hashCode(mUids) * 37
+                + Objects.hashCode(mSSID) * 41
+                + Objects.hashCode(mTransportInfo) * 43
+                + Objects.hashCode(mPrivateDnsBroken) * 47
+                + Objects.hashCode(mRequestorUid) * 53
+                + Objects.hashCode(mRequestorPackageName) * 59
+                + Arrays.hashCode(mAdministratorUids) * 61;
     }
 
     @Override
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index a0faafa..d84ee2a 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -35,7 +35,6 @@
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.util.Collection;
 import java.util.Locale;
 import java.util.TreeSet;
 
@@ -342,20 +341,6 @@
     }
 
     /**
-     * Create a string array of host addresses from a collection of InetAddresses
-     * @param addrs a Collection of InetAddresses
-     * @return an array of Strings containing their host addresses
-     */
-    public static String[] makeStrings(Collection<InetAddress> addrs) {
-        String[] result = new String[addrs.size()];
-        int i = 0;
-        for (InetAddress addr : addrs) {
-            result[i++] = addr.getHostAddress();
-        }
-        return result;
-    }
-
-    /**
      * Trim leading zeros from IPv4 address strings
      * Our base libraries will interpret that as octel..
      * Must leave non v4 addresses and host names alone.
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 5e2a718..4ea8a54 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,11 +1,5 @@
 set noparent
 
-codewiz@google.com
-jchalard@google.com
-jsharkey@android.com
-junyulai@google.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
+include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
 
 per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index f1d9669..20ccc07 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -205,7 +205,7 @@
                 if (host.equalsIgnoreCase("localhost")) {
                     return true;
                 }
-                if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
+                if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) {
                     return true;
                 }
             }
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/net/TcpRepairWindow.java b/core/java/android/net/TcpRepairWindow.java
index 86034f0..f062fa9 100644
--- a/core/java/android/net/TcpRepairWindow.java
+++ b/core/java/android/net/TcpRepairWindow.java
@@ -16,12 +16,15 @@
 
 package android.net;
 
+import android.annotation.SystemApi;
+
 /**
  * Corresponds to C's {@code struct tcp_repair_window} from
  * include/uapi/linux/tcp.h
  *
  * @hide
  */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 public final class TcpRepairWindow {
     public final int sndWl1;
     public final int sndWnd;
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 148acf1..d4a3fa7 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -15,30 +15,104 @@
  */
 package android.net.vcn;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
 
 /**
  * This class represents a configuration for a Virtual Carrier Network.
  *
+ * <p>Each {@link VcnGatewayConnectionConfig} instance added represents a connection that will be
+ * brought up on demand based on active {@link NetworkRequest}(s).
+ *
+ * @see VcnManager for more information on the Virtual Carrier Network feature
  * @hide
  */
 public final class VcnConfig implements Parcelable {
     @NonNull private static final String TAG = VcnConfig.class.getSimpleName();
 
-    private VcnConfig() {
+    private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
+    @NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
+
+    private VcnConfig(@NonNull Set<VcnGatewayConnectionConfig> tunnelConfigs) {
+        mGatewayConnectionConfigs = Collections.unmodifiableSet(tunnelConfigs);
+
         validate();
     }
-    // TODO: Implement getters, validators, etc
 
     /**
-     * Validates this configuration.
+     * Deserializes a VcnConfig from a PersistableBundle.
      *
      * @hide
      */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnConfig(@NonNull PersistableBundle in) {
+        final PersistableBundle gatewayConnectionConfigsBundle =
+                in.getPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY);
+        mGatewayConnectionConfigs =
+                new ArraySet<>(
+                        PersistableBundleUtils.toList(
+                                gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
+
+        validate();
+    }
+
     private void validate() {
-        // TODO: implement validation logic
+        Preconditions.checkCollectionNotEmpty(
+                mGatewayConnectionConfigs, "gatewayConnectionConfigs");
+    }
+
+    /** Retrieves the set of configured tunnels. */
+    @NonNull
+    public Set<VcnGatewayConnectionConfig> getGatewayConnectionConfigs() {
+        return Collections.unmodifiableSet(mGatewayConnectionConfigs);
+    }
+
+    /**
+     * Serializes this object to a PersistableBundle.
+     *
+     * @hide
+     */
+    @NonNull
+    public PersistableBundle toPersistableBundle() {
+        final PersistableBundle result = new PersistableBundle();
+
+        final PersistableBundle gatewayConnectionConfigsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mGatewayConnectionConfigs),
+                        VcnGatewayConnectionConfig::toPersistableBundle);
+        result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
+
+        return result;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mGatewayConnectionConfigs);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (!(other instanceof VcnConfig)) {
+            return false;
+        }
+
+        final VcnConfig rhs = (VcnConfig) other;
+        return mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs);
     }
 
     // Parcelable methods
@@ -49,15 +123,16 @@
     }
 
     @Override
-    public void writeToParcel(Parcel out, int flags) {}
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeParcelable(toPersistableBundle(), flags);
+    }
 
     @NonNull
     public static final Parcelable.Creator<VcnConfig> CREATOR =
             new Parcelable.Creator<VcnConfig>() {
                 @NonNull
                 public VcnConfig createFromParcel(Parcel in) {
-                    // TODO: Ensure all methods are pulled from the parcels
-                    return new VcnConfig();
+                    return new VcnConfig((PersistableBundle) in.readParcelable(null));
                 }
 
                 @NonNull
@@ -68,7 +143,23 @@
 
     /** This class is used to incrementally build {@link VcnConfig} objects. */
     public static class Builder {
-        // TODO: Implement this builder
+        @NonNull
+        private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
+
+        /**
+         * Adds a configuration for an individual gateway connection.
+         *
+         * @param gatewayConnectionConfig the configuration for an individual gateway connection
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        public Builder addGatewayConnectionConfig(
+                @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
+            Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
+
+            mGatewayConnectionConfigs.add(gatewayConnectionConfig);
+            return this;
+        }
 
         /**
          * Builds and validates the VcnConfig.
@@ -77,7 +168,7 @@
          */
         @NonNull
         public VcnConfig build() {
-            return new VcnConfig();
+            return new VcnConfig(mGatewayConnectionConfigs);
         }
     }
 }
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 8160edc..039360a 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -15,7 +15,27 @@
  */
 package android.net.vcn;
 
+import static android.net.NetworkCapabilities.NetCapability;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
  * This class represents a configuration for a connection to a Virtual Carrier Network gateway.
@@ -49,38 +69,399 @@
  *   <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MCX}
  * </ul>
  *
+ * <p>The meteredness and roaming of the VCN {@link Network} will be determined by that of the
+ * underlying Network(s).
+ *
  * @hide
  */
 public final class VcnGatewayConnectionConfig {
-    private VcnGatewayConnectionConfig() {
+    // TODO: Use MIN_MTU_V6 once it is public, @hide
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int MIN_MTU_V6 = 1280;
+
+    private static final Set<Integer> ALLOWED_CAPABILITIES;
+
+    static {
+        Set<Integer> allowedCaps = new ArraySet<>();
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX);
+
+        ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps);
+    }
+
+    private static final int DEFAULT_MAX_MTU = 1500;
+
+    /**
+     * The maximum number of retry intervals that may be specified.
+     *
+     * <p>Limited to ensure an upper bound on config sizes.
+     */
+    private static final int MAX_RETRY_INTERVAL_COUNT = 10;
+
+    /**
+     * The minimum allowable repeating retry interval
+     *
+     * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater
+     * than this value.
+     *
+     * @see {@link Builder#setRetryInterval()}
+     */
+    private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15);
+
+    private static final long[] DEFAULT_RETRY_INTERVALS_MS =
+            new long[] {
+                TimeUnit.SECONDS.toMillis(1),
+                TimeUnit.SECONDS.toMillis(2),
+                TimeUnit.SECONDS.toMillis(5),
+                TimeUnit.SECONDS.toMillis(30),
+                TimeUnit.MINUTES.toMillis(1),
+                TimeUnit.MINUTES.toMillis(5),
+                TimeUnit.MINUTES.toMillis(15)
+            };
+
+    private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
+    @NonNull private final Set<Integer> mExposedCapabilities;
+
+    private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities";
+    @NonNull private final Set<Integer> mUnderlyingCapabilities;
+
+    // TODO: Add Ike/ChildSessionParams as a subclass - maybe VcnIkeGatewayConnectionConfig
+
+    private static final String MAX_MTU_KEY = "mMaxMtu";
+    private final int mMaxMtu;
+
+    private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
+    @NonNull private final long[] mRetryIntervalsMs;
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnGatewayConnectionConfig(
+            @NonNull Set<Integer> exposedCapabilities,
+            @NonNull Set<Integer> underlyingCapabilities,
+            @NonNull long[] retryIntervalsMs,
+            @IntRange(from = MIN_MTU_V6) int maxMtu) {
+        mExposedCapabilities = exposedCapabilities;
+        mUnderlyingCapabilities = underlyingCapabilities;
+        mRetryIntervalsMs = retryIntervalsMs;
+        mMaxMtu = maxMtu;
+
         validate();
     }
 
-    // TODO: Implement getters, validators, etc
+    /** @hide */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) {
+        final PersistableBundle exposedCapsBundle =
+                in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
+        final PersistableBundle underlyingCapsBundle =
+                in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
+
+        mExposedCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+                exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+        mUnderlyingCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+                underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+        mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
+        mMaxMtu = in.getInt(MAX_MTU_KEY);
+
+        validate();
+    }
+
+    private void validate() {
+        Preconditions.checkArgument(
+                mExposedCapabilities != null && !mExposedCapabilities.isEmpty(),
+                "exposedCapsBundle was null or empty");
+        for (Integer cap : getAllExposedCapabilities()) {
+            checkValidCapability(cap);
+        }
+
+        Preconditions.checkArgument(
+                mUnderlyingCapabilities != null && !mUnderlyingCapabilities.isEmpty(),
+                "underlyingCapabilities was null or empty");
+        for (Integer cap : getAllUnderlyingCapabilities()) {
+            checkValidCapability(cap);
+        }
+
+        Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
+        validateRetryInterval(mRetryIntervalsMs);
+
+        Preconditions.checkArgument(
+                mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+    }
+
+    private static void checkValidCapability(int capability) {
+        Preconditions.checkArgument(
+                ALLOWED_CAPABILITIES.contains(capability),
+                "NetworkCapability " + capability + "out of range");
+    }
+
+    private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) {
+        Preconditions.checkArgument(
+                retryIntervalsMs != null
+                        && retryIntervalsMs.length > 0
+                        && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT,
+                "retryIntervalsMs was null, empty or exceed max interval count");
+
+        final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1];
+        if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) {
+            throw new IllegalArgumentException(
+                    "Repeating retry interval was too short, must be a minimum of 15 minutes: "
+                            + repeatingInterval);
+        }
+    }
 
     /**
-     * Validates this configuration
+     * Returns all exposed capabilities.
      *
      * @hide
      */
-    private void validate() {
-        // TODO: implement validation logic
+    @NonNull
+    public Set<Integer> getAllExposedCapabilities() {
+        return Collections.unmodifiableSet(mExposedCapabilities);
     }
 
-    // Parcelable methods
+    /**
+     * Checks if this config is configured to support/expose a specific capability.
+     *
+     * @param capability the capability to check for
+     */
+    public boolean hasExposedCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
 
-    /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects */
+        return mExposedCapabilities.contains(capability);
+    }
+
+    /**
+     * Returns all capabilities required of underlying networks.
+     *
+     * @hide
+     */
+    @NonNull
+    public Set<Integer> getAllUnderlyingCapabilities() {
+        return Collections.unmodifiableSet(mUnderlyingCapabilities);
+    }
+
+    /**
+     * Checks if this config requires an underlying network to have the specified capability.
+     *
+     * @param capability the capability to check for
+     */
+    public boolean requiresUnderlyingCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
+
+        return mUnderlyingCapabilities.contains(capability);
+    }
+
+    /** Retrieves the configured retry intervals. */
+    @NonNull
+    public long[] getRetryIntervalsMs() {
+        return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length);
+    }
+
+    /** Retrieves the maximum MTU allowed for this Gateway Connection. */
+    @IntRange(from = MIN_MTU_V6)
+    public int getMaxMtu() {
+        return mMaxMtu;
+    }
+
+    /**
+     * Converts this config to a PersistableBundle.
+     *
+     * @hide
+     */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PROTECTED)
+    public PersistableBundle toPersistableBundle() {
+        final PersistableBundle result = new PersistableBundle();
+
+        final PersistableBundle exposedCapsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mExposedCapabilities),
+                        PersistableBundleUtils.INTEGER_SERIALIZER);
+        final PersistableBundle underlyingCapsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mUnderlyingCapabilities),
+                        PersistableBundleUtils.INTEGER_SERIALIZER);
+
+        result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
+        result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
+        result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
+        result.putInt(MAX_MTU_KEY, mMaxMtu);
+
+        return result;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mExposedCapabilities,
+                mUnderlyingCapabilities,
+                Arrays.hashCode(mRetryIntervalsMs),
+                mMaxMtu);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (!(other instanceof VcnGatewayConnectionConfig)) {
+            return false;
+        }
+
+        final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
+        return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+                && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
+                && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
+                && mMaxMtu == rhs.mMaxMtu;
+    }
+
+    /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. */
     public static class Builder {
-        // TODO: Implement this builder
+        @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
+        @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
+        @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
+        private int mMaxMtu = DEFAULT_MAX_MTU;
+
+        // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
+        //       Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
+        //       when on Cell.
 
         /**
-         * Builds and validates the VcnGatewayConnectionConfig
+         * Add a capability that this VCN Gateway Connection will support.
+         *
+         * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway
+         *     Connection (i.e., the capabilities that this VCN Gateway Connection will support).
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+         *     Connection
+         */
+        public Builder addExposedCapability(@NetCapability int exposedCapability) {
+            checkValidCapability(exposedCapability);
+
+            mExposedCapabilities.add(exposedCapability);
+            return this;
+        }
+
+        /**
+         * Remove a capability that this VCN Gateway Connection will support.
+         *
+         * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway
+         *     Connection (i.e., the capabilities that this VCN Gateway Connection will support)
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+         *     Connection
+         */
+        public Builder removeExposedCapability(@NetCapability int exposedCapability) {
+            checkValidCapability(exposedCapability);
+
+            mExposedCapabilities.remove(exposedCapability);
+            return this;
+        }
+
+        /**
+         * Require a capability for Networks underlying this VCN Gateway Connection.
+         *
+         * @param underlyingCapability the capability that a network MUST have in order to be an
+         *     underlying network for this VCN Gateway Connection.
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+         *     networks
+         */
+        public Builder addRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+            checkValidCapability(underlyingCapability);
+
+            mUnderlyingCapabilities.add(underlyingCapability);
+            return this;
+        }
+
+        /**
+         * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection.
+         *
+         * <p>Calling this method will allow Networks that do NOT have this capability to be
+         * selected as an underlying network for this VCN Gateway Connection. However, underlying
+         * networks MAY still have the removed capability.
+         *
+         * @param underlyingCapability the capability that a network DOES NOT need to have in order
+         *     to be an underlying network for this VCN Gateway Connection.
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+         *     networks
+         */
+        public Builder removeRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+            checkValidCapability(underlyingCapability);
+
+            mUnderlyingCapabilities.remove(underlyingCapability);
+            return this;
+        }
+
+        /**
+         * Set the retry interval between VCN establishment attempts upon successive failures.
+         *
+         * <p>The last retry interval will be repeated until safe mode is entered, or a connection
+         * is successfully established, at which point the retry timers will be reset. For power
+         * reasons, the last (repeated) retry interval MUST be at least 15 minutes.
+         *
+         * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if
+         * the system enters a power saving mode, the retry may not occur until the device leaves
+         * the specified power saving mode. Intervals are sequential, and intervals will NOT be
+         * skipped if system power saving results in delaying retries (even if it exceed multiple
+         * retry intervals).
+         *
+         * <p>Each Gateway Connection will retry according to the retry intervals configured, but if
+         * safe mode is enabled, all Gateway Connection(s) will be disabled.
+         *
+         * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which
+         *     the VCN will attempt to retry a session initiation. The last (repeating) retry
+         *     interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m,
+         *     15m]}
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnManager for additional discussion on fail-safe mode
+         */
+        @NonNull
+        public Builder setRetryInterval(@NonNull long[] retryIntervalsMs) {
+            validateRetryInterval(retryIntervalsMs);
+
+            mRetryIntervalsMs = retryIntervalsMs;
+            return this;
+        }
+
+        /**
+         * Sets the maximum MTU allowed for this VCN Gateway Connection.
+         *
+         * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the
+         * MTU of the virtualized network.
+         *
+         * <p>The system may reduce the MTU below the maximum specified based on signals such as the
+         * MTU of the underlying networks (and adjusted for Gateway Connection overhead).
+         *
+         * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than
+         *     the IPv6 minimum MTU of 1280. Defaults to 1500.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) {
+            Preconditions.checkArgument(
+                    maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+
+            mMaxMtu = maxMtu;
+            return this;
+        }
+
+        /**
+         * Builds and validates the VcnGatewayConnectionConfig.
          *
          * @return an immutable VcnGatewayConnectionConfig instance
          */
         @NonNull
         public VcnGatewayConnectionConfig build() {
-            return new VcnGatewayConnectionConfig();
+            return new VcnGatewayConnectionConfig(
+                    mExposedCapabilities, mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu);
         }
     }
 }
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 6769b9e..19c183f 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -23,10 +23,37 @@
 import android.content.Context;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+
+import java.io.IOException;
 
 /**
  * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks.
  *
+ * <p>A VCN creates a virtualization layer to allow MVNOs to aggregate heterogeneous physical
+ * networks, unifying them as a single carrier network. This enables infrastructure flexibility on
+ * the part of MVNOs without impacting user connectivity, abstracting the physical network
+ * technologies as an implementation detail of their public network.
+ *
+ * <p>Each VCN virtualizes an Carrier's network by building tunnels to a carrier's core network over
+ * carrier-managed physical links and supports a IP mobility layer to ensure seamless transitions
+ * between the underlying networks. Each VCN is configured based on a Subscription Group (see {@link
+ * android.telephony.SubscriptionManager}) and aggregates all networks that are brought up based on
+ * a profile or suggestion in the specified Subscription Group.
+ *
+ * <p>The VCN can be configured to expose one or more {@link android.net.Network}(s), each with
+ * different capabilities, allowing for APN virtualization.
+ *
+ * <p>If a tunnel fails to connect, or otherwise encounters a fatal error, the VCN will attempt to
+ * reestablish the connection. If the tunnel still has not reconnected after a system-determined
+ * timeout, the VCN Safe Mode (see below) will be entered.
+ *
+ * <p>The VCN Safe Mode ensures that users (and carriers) have a fallback to restore system
+ * connectivity to update profiles, diagnose issues, contact support, or perform other remediation
+ * tasks. In Safe Mode, the system will allow underlying cellular networks to be used as default.
+ * Additionally, during Safe Mode, the VCN will continue to retry the connections, and will
+ * automatically exit Safe Mode if all active tunnels connect successfully.
+ *
  * @hide
  */
 @SystemService(Context.VCN_MANAGEMENT_SERVICE)
@@ -63,15 +90,20 @@
      * @param config the configuration parameters for the VCN
      * @throws SecurityException if the caller does not have carrier privileges, or is not running
      *     as the primary user
+     * @throws IOException if the configuration failed to be persisted. A caller encountering this
+     *     exception should attempt to retry (possibly after a delay).
      * @hide
      */
     @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
-    public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) {
+    public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config)
+            throws IOException {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
         requireNonNull(config, "config was null");
 
         try {
             mService.setVcnConfig(subscriptionGroup, config);
+        } catch (ServiceSpecificException e) {
+            throw new IOException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -88,14 +120,18 @@
      * @param subscriptionGroup the subscription group that the configuration should be applied to
      * @throws SecurityException if the caller does not have carrier privileges, or is not running
      *     as the primary user
+     * @throws IOException if the configuration failed to be cleared. A caller encountering this
+     *     exception should attempt to retry (possibly after a delay).
      * @hide
      */
     @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
-    public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
+    public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) throws IOException {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
 
         try {
             mService.clearVcnConfig(subscriptionGroup);
+        } catch (ServiceSpecificException e) {
+            throw new IOException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
+zachoverflow@google.com
+alisher@google.com
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index e3f996b..0af322e 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -98,6 +98,11 @@
     final boolean mRequiresDeviceUnlock;
 
     /**
+     * Whether this service should only be started when the device is screen on.
+     */
+    final boolean mRequiresDeviceScreenOn;
+
+    /**
      * The id of the service banner specified in XML.
      */
     final int mBannerResourceId;
@@ -120,6 +125,18 @@
             ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, int bannerResource, int uid,
             String settingsActivityName, String offHost, String staticOffHost) {
+        this(info, onHost, description, staticAidGroups, dynamicAidGroups,
+                requiresUnlock, onHost ? true : false, bannerResource, uid,
+                settingsActivityName, offHost, staticOffHost);
+    }
+
+    /**
+     * @hide
+     */
+    public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
+            ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+            boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
+            String settingsActivityName, String offHost, String staticOffHost) {
         this.mService = info;
         this.mDescription = description;
         this.mStaticAidGroups = new HashMap<String, AidGroup>();
@@ -128,6 +145,7 @@
         this.mStaticOffHostName = staticOffHost;
         this.mOnHost = onHost;
         this.mRequiresDeviceUnlock = requiresUnlock;
+        this.mRequiresDeviceScreenOn = requiresScreenOn;
         for (AidGroup aidGroup : staticAidGroups) {
             this.mStaticAidGroups.put(aidGroup.category, aidGroup);
         }
@@ -184,6 +202,9 @@
                 mRequiresDeviceUnlock = sa.getBoolean(
                         com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
                         false);
+                mRequiresDeviceScreenOn = sa.getBoolean(
+                        com.android.internal.R.styleable.HostApduService_requireDeviceScreenOn,
+                        true);
                 mBannerResourceId = sa.getResourceId(
                         com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
                 mSettingsActivityName = sa.getString(
@@ -197,7 +218,12 @@
                 mService = info;
                 mDescription = sa.getString(
                         com.android.internal.R.styleable.OffHostApduService_description);
-                mRequiresDeviceUnlock = false;
+                mRequiresDeviceUnlock = sa.getBoolean(
+                        com.android.internal.R.styleable.OffHostApduService_requireDeviceUnlock,
+                        false);
+                mRequiresDeviceScreenOn = sa.getBoolean(
+                        com.android.internal.R.styleable.OffHostApduService_requireDeviceScreenOn,
+                        false);
                 mBannerResourceId = sa.getResourceId(
                         com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
                 mSettingsActivityName = sa.getString(
@@ -420,6 +446,13 @@
         return mRequiresDeviceUnlock;
     }
 
+    /**
+     * Returns whether this service should only be started when the device is screen on.
+     */
+    public boolean requiresScreenOn() {
+        return mRequiresDeviceScreenOn;
+    }
+
     @UnsupportedAppUsage
     public String getDescription() {
         return mDescription;
@@ -543,6 +576,7 @@
             dest.writeTypedList(new ArrayList<AidGroup>(mDynamicAidGroups.values()));
         }
         dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
+        dest.writeInt(mRequiresDeviceScreenOn ? 1 : 0);
         dest.writeInt(mBannerResourceId);
         dest.writeInt(mUid);
         dest.writeString(mSettingsActivityName);
@@ -569,11 +603,12 @@
                 source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
             }
             boolean requiresUnlock = source.readInt() != 0;
+            boolean requiresScreenOn = source.readInt() != 0;
             int bannerResource = source.readInt();
             int uid = source.readInt();
             String settingsActivityName = source.readString();
             return new ApduServiceInfo(info, onHost, description, staticAidGroups,
-                    dynamicAidGroups, requiresUnlock, bannerResource, uid,
+                    dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid,
                     settingsActivityName, offHostName, staticOffHostName);
         }
 
@@ -608,6 +643,8 @@
             }
         }
         pw.println("    Settings Activity: " + mSettingsActivityName);
+        pw.println("    Requires Device Unlock: " + mRequiresDeviceUnlock);
+        pw.println("    Requires Device ScreenOn: " + mRequiresDeviceScreenOn);
     }
 
     /**
diff --git a/core/java/android/nfc/cardemulation/OWNERS b/core/java/android/nfc/cardemulation/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
+zachoverflow@google.com
+alisher@google.com
diff --git a/core/java/android/nfc/dta/OWNERS b/core/java/android/nfc/dta/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/dta/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
+zachoverflow@google.com
+alisher@google.com
diff --git a/core/java/android/nfc/tech/OWNERS b/core/java/android/nfc/tech/OWNERS
new file mode 100644
index 0000000..6aaf039
--- /dev/null
+++ b/core/java/android/nfc/tech/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+
+zachoverflow@google.com
+alisher@google.com
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index d00c3c3..bf8ac6e 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -36,19 +36,60 @@
      * @hide
      */
     @IntDef(prefix = {"POWER_COMPONENT_"}, value = {
+            POWER_COMPONENT_USAGE,
             POWER_COMPONENT_CPU,
+            POWER_COMPONENT_BLUETOOTH,
     })
     @Retention(RetentionPolicy.SOURCE)
     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_BLUETOOTH = 2;
 
-    public static final int POWER_COMPONENT_COUNT = 1;
+    public static final int POWER_COMPONENT_COUNT = 3;
 
     public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
     public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
 
+    /**
+     * Modeled power components are used for testing only.  They are returned if the
+     * {@link BatteryUsageStatsQuery#FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED} is set.
+     * The modeled power components are retrieved with {@link #getConsumedPowerForCustomComponent}.
+     * The ID of a modeled power component is calculated as
+     * (FIRST_MODELED_POWER_COMPONENT_ID + powerComponentId), e.g.
+     * FIRST_MODELED_POWER_COMPONENT_ID + POWER_COMPONENT_CPU.
+     */
+    public static final int FIRST_MODELED_POWER_COMPONENT_ID = 10000;
+    public static final int LAST_MODELED_POWER_COMPONENT_ID = 19999;
+
+    /**
+     * Time usage component, describing the particular part of the system
+     * that was used for the corresponding amount of time.
+     *
+     * @hide
+     */
+    @IntDef(prefix = {"TIME_COMPONENT_"}, value = {
+            TIME_COMPONENT_USAGE,
+            TIME_COMPONENT_CPU,
+            TIME_COMPONENT_CPU_FOREGROUND,
+            TIME_COMPONENT_BLUETOOTH,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public static @interface TimeComponent {
+    }
+
+    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_BLUETOOTH = 3;
+
+    public static final int TIME_COMPONENT_COUNT = 4;
+
+    public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
+    public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
+
     private final PowerComponents mPowerComponents;
 
     protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
@@ -83,7 +124,107 @@
         return mPowerComponents.getConsumedPowerForCustomComponent(componentId);
     }
 
+    /**
+     * Returns the amount of time since BatteryStats reset 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}.
+     * @return Amount of time in milliseconds.
+     */
+    public long getUsageDurationMillis(@TimeComponent int componentId) {
+        return mPowerComponents.getUsageDurationMillis(componentId);
+    }
+
+    /**
+     * Returns the amount of usage time attributed to the specified custom component
+     * since BatteryStats reset.
+     *
+     * @param componentId The ID of the custom power component.
+     * @return Amount of time in milliseconds.
+     */
+    public long getUsageDurationForCustomComponentMillis(int componentId) {
+        return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId);
+    }
+
     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,
+                boolean includeModeledComponents) {
+            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
+                    customTimeComponentCount, includeModeledComponents);
+        }
+
+        /**
+         * 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/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9c2ae4e..a89de01 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -27,6 +27,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.location.GnssSignalQuality;
 import android.os.BatteryStatsManager.WifiState;
 import android.os.BatteryStatsManager.WifiSupplState;
 import android.server.ServerProtoEnums;
@@ -47,7 +48,6 @@
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 
@@ -5087,8 +5087,9 @@
         final String[] gpsSignalQualityDescription = new String[]{
             "poor (less than 20 dBHz): ",
             "good (greater than 20 dBHz): "};
-        final int numGpsSignalQualityBins = Math.min(GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS,
-            gpsSignalQualityDescription.length);
+        final int numGpsSignalQualityBins = Math.min(
+                GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS,
+                gpsSignalQualityDescription.length);
         for (int i=0; i<numGpsSignalQualityBins; i++) {
             final long time = getGpsSignalQualityTime(i, rawRealtime, which);
             sb.append("\n    ");
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index d9e01cd..f344208 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -85,7 +85,7 @@
     public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP + 1;
 
     /** @hide */
-    @IntDef(flag = true, prefix = { "WIFI_STATE_" }, value = {
+    @IntDef(prefix = { "WIFI_STATE_" }, value = {
             WIFI_STATE_OFF,
             WIFI_STATE_OFF_SCANNING,
             WIFI_STATE_ON_NO_NETWORKS,
@@ -135,7 +135,7 @@
     public static final int NUM_WIFI_SUPPL_STATES = WIFI_SUPPL_STATE_UNINITIALIZED + 1;
 
     /** @hide */
-    @IntDef(flag = true, prefix = { "WIFI_SUPPL_STATE_" }, value = {
+    @IntDef(prefix = { "WIFI_SUPPL_STATE_" }, value = {
             WIFI_SUPPL_STATE_INVALID,
             WIFI_SUPPL_STATE_DISCONNECTED,
             WIFI_SUPPL_STATE_INTERFACE_DISABLED,
@@ -160,6 +160,7 @@
         mBatteryStats = batteryStats;
     }
 
+
     /**
      * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
      * and per-UID basis.
@@ -169,8 +170,20 @@
     @RequiresPermission(android.Manifest.permission.BATTERY_STATS)
     @NonNull
     public BatteryUsageStats getBatteryUsageStats() {
+        return getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT);
+    }
+
+    /**
+     * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
+     * and per-UID basis.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.BATTERY_STATS)
+    @NonNull
+    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
         try {
-            return mBatteryStats.getBatteryUsageStats();
+            return mBatteryStats.getBatteryUsageStats(query);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 3f036cd..a6df87d 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,11 +32,21 @@
     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;
-        mUidBatteryConsumers = builder.mUidBatteryConsumers;
+        int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
+        mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
+        for (int i = 0; i < uidBatteryConsumerCount; i++) {
+            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());
+        }
     }
 
     /**
@@ -59,6 +70,11 @@
         return mUidBatteryConsumers;
     }
 
+    @NonNull
+    public List<SystemBatteryConsumer> getSystemBatteryConsumers() {
+        return mSystemBatteryConsumers;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -67,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();
     }
@@ -74,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);
     }
@@ -93,9 +112,22 @@
      * Builder for BatteryUsageStats.
      */
     public static final class Builder {
+        private final int mCustomPowerComponentCount;
+        private final int mCustomTimeComponentCount;
+        private final boolean mIncludeModeledComponents;
         private double mConsumedPower;
         private int mDischargePercentage;
-        private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers = new ArrayList<>();
+        private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
+                new SparseArray<>();
+        private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
+                new SparseArray<>();
+
+        public Builder(int customPowerComponentCount, int customTimeComponentCount,
+                boolean includeModeledComponents) {
+            mCustomPowerComponentCount = customPowerComponentCount;
+            mCustomTimeComponentCount = customTimeComponentCount;
+            mIncludeModeledComponents = includeModeledComponents;
+        }
 
         /**
          * Constructs a read-only object using the Builder values.
@@ -108,6 +140,7 @@
         /**
          * Sets the battery discharge amount since BatteryStats reset as percentage of the full
          * charge.
+         *
          */
         @SuppressLint("PercentageInt") // See b/174188159
         @NonNull
@@ -126,13 +159,41 @@
         }
 
         /**
-         * 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 addUidBatteryConsumer(@NonNull UidBatteryConsumer uidBatteryConsumer) {
-            mUidBatteryConsumers.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, mIncludeModeledComponents, 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, mIncludeModeledComponents, drainType);
+                mSystemBatteryConsumerBuilders.put(drainType, builder);
+            }
+            return builder;
+        }
+
+        @NonNull
+        public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
+            return mUidBatteryConsumerBuilders;
         }
     }
 }
diff --git a/core/java/android/os/BatteryUsageStatsQuery.aidl b/core/java/android/os/BatteryUsageStatsQuery.aidl
new file mode 100644
index 0000000..207396c
--- /dev/null
+++ b/core/java/android/os/BatteryUsageStatsQuery.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BatteryUsageStatsQuery;
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
new file mode 100644
index 0000000..9a00679
--- /dev/null
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Query parameters for the {@link BatteryStatsManager#getBatteryUsageStats()} call.
+ *
+ * @hide
+ */
+public final class BatteryUsageStatsQuery implements Parcelable {
+
+    @NonNull
+    public static final BatteryUsageStatsQuery DEFAULT =
+            new BatteryUsageStatsQuery.Builder().build();
+
+    /**
+     * Flags for the {@link BatteryStatsManager#getBatteryUsageStats()} method.
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "FLAG_BATTERY_USAGE_STATS_" }, value = {
+            FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BatteryUsageStatsFlags {}
+
+    /**
+     * Indicates that modeled battery usage stats should be returned along with
+     * measured ones.
+     *
+     * @hide
+     */
+    public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED = 1;
+
+    private final int mFlags;
+
+    private BatteryUsageStatsQuery(@NonNull Builder builder) {
+        mFlags = builder.mFlags;
+    }
+
+    @BatteryUsageStatsFlags
+    public int getFlags() {
+        return mFlags;
+    }
+
+    private BatteryUsageStatsQuery(Parcel in) {
+        mFlags = in.readInt();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mFlags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<BatteryUsageStatsQuery> CREATOR =
+            new Creator<BatteryUsageStatsQuery>() {
+                @Override
+                public BatteryUsageStatsQuery createFromParcel(Parcel in) {
+                    return new BatteryUsageStatsQuery(in);
+                }
+
+                @Override
+                public BatteryUsageStatsQuery[] newArray(int size) {
+                    return new BatteryUsageStatsQuery[size];
+                }
+            };
+
+    /**
+     * Builder for BatteryUsageStatsQuery.
+     */
+    public static final class Builder {
+        private int mFlags;
+
+        /**
+         * Builds a read-only BatteryUsageStatsQuery object.
+         */
+        public BatteryUsageStatsQuery build() {
+            return new BatteryUsageStatsQuery(this);
+        }
+
+        /**
+         * Sets flags to modify the behavior of {@link BatteryStatsManager#getBatteryUsageStats}.
+         */
+        public Builder setFlags(@BatteryUsageStatsFlags int flags) {
+            mFlags = flags;
+            return this;
+        }
+
+        /**
+         * Requests to include modeled battery usage stats along with measured ones.
+         * Should only be used for testing and debugging.
+         */
+        public Builder includeModeled() {
+            mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED;
+            return this;
+        }
+    }
+}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index bd18150..8148c45 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -107,12 +107,24 @@
     public static final String HARDWARE = getString("ro.hardware");
 
     /**
-     * The hardware variant (SKU), if available.
+     * The SKU of the hardware (from the kernel command line). The SKU is reported by the bootloader
+     * to configure system software features.
      */
     @NonNull
     public static final String SKU = getString("ro.boot.hardware.sku");
 
     /**
+     * The SKU of the device as set by the original design manufacturer (ODM). This is a
+     * runtime-initialized property set during startup to configure device services.
+     *
+     * <p>The ODM SKU may have multiple variants for the same system SKU in case a manufacturer
+     * produces variants of the same design. For example, the same build may be released with
+     * variations in physical keyboard and/or display hardware, each with a different ODM SKU.
+     */
+    @NonNull
+    public static final String ODM_SKU = getString("ro.boot.product.hardware.sku");
+
+    /**
      * Whether this build was for an emulator device.
      * @hide
      */
diff --git a/core/java/android/os/CombinedVibrationEffect.java b/core/java/android/os/CombinedVibrationEffect.java
index c9ebc1b..7ec7fff 100644
--- a/core/java/android/os/CombinedVibrationEffect.java
+++ b/core/java/android/os/CombinedVibrationEffect.java
@@ -30,8 +30,6 @@
  * Vibrator Vibrators}.
  *
  * These effects may be any number of things, from single shot vibrations to complex waveforms.
- *
- * @hide
  * @see VibrationEffect
  */
 @SuppressWarnings({"ParcelNotFinal", "ParcelCreator"}) // Parcel only extended here.
@@ -94,7 +92,6 @@
     /**
      * A combination of haptic effects that should be played in multiple vibrators in sync.
      *
-     * @hide
      * @see CombinedVibrationEffect#startSynced()
      */
     public static final class SyncedCombination {
@@ -144,7 +141,6 @@
     /**
      * A combination of haptic effects that should be played in multiple vibrators in sequence.
      *
-     * @hide
      * @see CombinedVibrationEffect#startSequential()
      */
     public static final class SequentialCombination {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e2e1bbe..9584bc7 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2582,6 +2582,13 @@
     public static native long getIonMappedSizeKb();
 
     /**
+     * Return memory size in kilobytes used by GPU.
+     *
+     * @hide
+     */
+    public static native long getGpuTotalUsageKb();
+
+    /**
      * Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
      * Note: caller needs config_gz read sepolicy permission
      *
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index ab5637c..7b84575 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -22,11 +22,12 @@
 import android.system.Os;
 import android.util.Log;
 
+import com.android.internal.util.ArrayUtils;
+
 import libcore.io.IoBridge;
 import libcore.io.IoUtils;
 import libcore.io.Memory;
 import libcore.io.Streams;
-import libcore.util.ArrayUtils;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 379d6e6..c014ef6 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -83,6 +83,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -115,6 +116,9 @@
     private FileUtils() {
     }
 
+    private static final String CAMERA_DIR_LOWER_CASE = "/storage/emulated/" + UserHandle.myUserId()
+            + "/dcim/camera";
+
     /** Regular expression for safe filenames: no spaces or metacharacters.
       *
       * Use a preload holder so that FileUtils can be compile-time initialized.
@@ -1432,20 +1436,27 @@
         }
     }
 
+    // TODO(b/170488060): Consider better approach
     /** {@hide} */
+    @VisibleForTesting
     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)
-                    || 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
+            File realFile = ParcelFileDescriptor.getFile(fd);
+            String fileName = realFile.getName();
+            boolean isCameraVideo = !fileName.startsWith(".") && fileName.endsWith(".mp4")
+                    && contains(CAMERA_DIR_LOWER_CASE, realFile.getAbsolutePath().toLowerCase(
+                                    Locale.ROOT));
+
+            if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
+                    || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)
+                    || !isCameraVideo) {
+                // 1. If transcode is enabled we optimize by default, unless explicitly disabled.
+                // 2. Never convert modern fd for MediaProvider, because this requires
                 // MediaStore#scanFile and can cause infinite loops when MediaProvider scans
+                // 3. Only convert published mp4 videos in the DCIM/Camera dir
                 return null;
             }
-            File realFile = ParcelFileDescriptor.getFile(fd);
             Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
             ContentResolver resolver = context.getContentResolver();
 
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index e1d9005..25d84ba 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -321,16 +321,6 @@
     void setFirewallChainEnabled(int chain, boolean enable);
 
     /**
-     * Set all packets from users in ranges to go through VPN specified by netId.
-     */
-    void addVpnUidRanges(int netId, in UidRange[] ranges);
-
-    /**
-     * Clears the special VPN rules for users in ranges and VPN specified by netId.
-     */
-    void removeVpnUidRanges(int netId, in UidRange[] ranges);
-
-    /**
      * Start listening for mobile activity state changes.
      */
     void registerNetworkActivityListener(INetworkActivityListener listener);
@@ -361,7 +351,5 @@
     void removeInterfaceFromLocalNetwork(String iface);
     int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);
 
-    void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges);
-
     boolean isNetworkRestricted(int uid);
 }
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index 2561e1e..2052883 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -27,7 +27,9 @@
     boolean setupBcb(in String command);
     boolean clearBcb();
     void rebootRecoveryWithCommand(in String command);
-    boolean requestLskf(in String updateToken, in IntentSender sender);
-    boolean clearLskf();
-    boolean rebootWithLskf(in String updateToken, in String reason);
+    boolean requestLskf(in String packageName, in IntentSender sender);
+    boolean clearLskf(in String packageName);
+    boolean isLskfCaptured(in String packageName);
+    boolean rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason);
+    boolean rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch);
 }
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index 08d2019..804dc10 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -18,10 +18,14 @@
 
 import android.os.CombinedVibrationEffect;
 import android.os.VibrationAttributes;
+import android.os.VibratorInfo;
 
 /** {@hide} */
 interface IVibratorManagerService {
     int[] getVibratorIds();
+    VibratorInfo getVibratorInfo(int vibratorId);
+    boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
+            in CombinedVibrationEffect effect, in VibrationAttributes attributes);
     void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect,
             in VibrationAttributes attributes, String reason, IBinder token);
     void cancelVibrate(IBinder token);
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 615ae65..1cd48dc 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -18,6 +18,7 @@
 
 import android.os.VibrationEffect;
 import android.os.VibrationAttributes;
+import android.os.VibratorInfo;
 import android.os.IVibratorStateListener;
 
 /** {@hide} */
@@ -25,13 +26,10 @@
 {
     boolean hasVibrator();
     boolean isVibrating();
+    VibratorInfo getVibratorInfo();
     boolean registerVibratorStateListener(in IVibratorStateListener listener);
     boolean unregisterVibratorStateListener(in IVibratorStateListener listener);
     boolean hasAmplitudeControl();
-    int[] areEffectsSupported(in int[] effectIds);
-    boolean[] arePrimitivesSupported(in int[] primitiveIds);
-    boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect,
-            in VibrationAttributes attributes);
     void vibrate(int uid, String opPkg, in VibrationEffect effect,
             in VibrationAttributes attributes, String reason, IBinder token);
     void cancelVibrate(IBinder token);
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 91eb2a5..49451d9 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -16,7 +16,19 @@
 per-file PowerManager.java = michaelwr@google.com, santoscordon@google.com
 per-file PowerManagerInternal.java = michaelwr@google.com, santoscordon@google.com
 
-# Zygote
-per-file ZygoteProcess.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
+# BatteryStats
+per-file *BatteryConsumer* = file:/BATTERY_STATS_OWNERS
+per-file BatteryManager* = file:/BATTERY_STATS_OWNERS
+per-file BatteryStats* = file:/BATTERY_STATS_OWNERS
+per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS
+per-file PowerComponents.java = file:/BATTERY_STATS_OWNERS
 
 per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com
+
+per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+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/Parcel.java b/core/java/android/os/Parcel.java
index 5242750..fc65090 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -34,11 +34,11 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
-import libcore.util.ArrayUtils;
 import libcore.util.SneakyThrow;
 
 import java.io.ByteArrayInputStream;
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index 42ba1ff..18dca68 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -13,10 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package android.os;
 
-
 import android.annotation.NonNull;
 
 /**
@@ -26,24 +24,41 @@
  * @hide
  */
 class PowerComponents {
+    private static final int CUSTOM_POWER_COMPONENT_OFFSET = BatteryConsumer.POWER_COMPONENT_COUNT
+            - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+    public static final int CUSTOM_TIME_COMPONENT_OFFSET = BatteryConsumer.TIME_COMPONENT_COUNT
+            - BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID;
 
     private final double mTotalPowerConsumed;
     private final double[] mPowerComponents;
+    private final long[] mTimeComponents;
+    private final int mCustomPowerComponentCount;
+    private final int mModeledPowerComponentOffset;
 
     PowerComponents(@NonNull Builder builder) {
         mTotalPowerConsumed = builder.mTotalPowerConsumed;
+        mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
+        mModeledPowerComponentOffset = builder.mModeledPowerComponentOffset;
         mPowerComponents = builder.mPowerComponents;
+        mTimeComponents = builder.mTimeComponents;
     }
 
     PowerComponents(@NonNull Parcel source) {
         mTotalPowerConsumed = source.readDouble();
+        mCustomPowerComponentCount = source.readInt();
+        mModeledPowerComponentOffset =
+                BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentCount
+                        - BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID;
         mPowerComponents = source.createDoubleArray();
+        mTimeComponents = source.createLongArray();
     }
 
     /** Writes contents to Parcel */
     void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeDouble(mTotalPowerConsumed);
+        dest.writeInt(mCustomPowerComponentCount);
         dest.writeDoubleArray(mPowerComponents);
+        dest.writeLongArray(mTimeComponents);
     }
 
     /**
@@ -60,7 +75,7 @@
      *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
      * @return Amount of consumed power in mAh.
      */
-    public double getConsumedPower(@UidBatteryConsumer.PowerComponent int componentId) {
+    public double getConsumedPower(@BatteryConsumer.PowerComponent int componentId) {
         if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
             throw new IllegalArgumentException(
                     "Unsupported power component ID: " + componentId);
@@ -79,17 +94,63 @@
      * @return Amount of consumed power in mAh.
      */
     public double getConsumedPowerForCustomComponent(int componentId) {
-        if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
+        if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+                && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+            try {
+                return mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new IllegalArgumentException(
+                        "Unsupported custom power component ID: " + componentId);
+            }
+        } else if (componentId >= BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                && componentId < BatteryConsumer.LAST_MODELED_POWER_COMPONENT_ID) {
+            try {
+                return mPowerComponents[mModeledPowerComponentOffset + componentId];
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new IllegalArgumentException(
+                        "Unsupported modeled power component ID: " + componentId);
+            }
+        } else {
             throw new IllegalArgumentException(
                     "Unsupported custom power component ID: " + componentId);
         }
+    }
+
+    /**
+     * Returns 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 BatteryConsumer#TIME_COMPONENT_CPU}.
+     * @return Amount of time in milliseconds.
+     */
+    public long getUsageDurationMillis(@BatteryConsumer.TimeComponent int componentId) {
+        if (componentId >= BatteryConsumer.TIME_COMPONENT_COUNT) {
+            throw new IllegalArgumentException(
+                    "Unsupported time component ID: " + componentId);
+        }
         try {
-            return mPowerComponents[
-                    BatteryConsumer.POWER_COMPONENT_COUNT + componentId
-                            - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID];
+            return mTimeComponents[componentId];
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
+        }
+    }
+
+    /**
+     * Returns the amount of usage time attributed to the specified custom component.
+     *
+     * @param componentId The ID of the custom power component.
+     * @return Amount of time in milliseconds.
+     */
+    public long getUsageDurationForCustomComponentMillis(int componentId) {
+        if (componentId < BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
+            throw new IllegalArgumentException(
+                    "Unsupported custom time component ID: " + componentId);
+        }
+        try {
+            return mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
         } catch (ArrayIndexOutOfBoundsException e) {
             throw new IllegalArgumentException(
-                    "Unsupported custom power component ID: " + componentId);
+                    "Unsupported custom time component ID: " + componentId);
         }
     }
 
@@ -99,10 +160,24 @@
     static final class Builder {
         private double mTotalPowerConsumed;
         private final double[] mPowerComponents;
+        private final int mCustomPowerComponentCount;
+        private final long[] mTimeComponents;
+        private final int mModeledPowerComponentOffset;
 
-        Builder(int customPowerComponentCount) {
-            mPowerComponents = new double[BatteryConsumer.POWER_COMPONENT_COUNT
-                    + customPowerComponentCount];
+        Builder(int customPowerComponentCount, int customTimeComponentCount,
+                boolean includeModeledPowerComponents) {
+            mCustomPowerComponentCount = customPowerComponentCount;
+            int powerComponentCount =
+                    BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
+            if (includeModeledPowerComponents) {
+                powerComponentCount += BatteryConsumer.POWER_COMPONENT_COUNT;
+            }
+            mPowerComponents = new double[powerComponentCount];
+            mModeledPowerComponentOffset =
+                    BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentCount
+                            - BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID;
+            mTimeComponents =
+                    new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
         }
 
         /**
@@ -122,7 +197,7 @@
          * @param componentPower Amount of consumed power in mAh.
          */
         @NonNull
-        public Builder setConsumedPower(@UidBatteryConsumer.PowerComponent int componentId,
+        public Builder setConsumedPower(@BatteryConsumer.PowerComponent int componentId,
                 double componentPower) {
             if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
                 throw new IllegalArgumentException(
@@ -145,14 +220,23 @@
          */
         @NonNull
         public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
-            if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
-                throw new IllegalArgumentException(
-                        "Unsupported custom power component ID: " + componentId);
-            }
-            try {
-                mPowerComponents[BatteryConsumer.POWER_COMPONENT_COUNT + componentId
-                        - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID] = componentPower;
-            } catch (ArrayIndexOutOfBoundsException e) {
+            if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+                    && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+                try {
+                    mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId] = componentPower;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new IllegalArgumentException(
+                            "Unsupported custom power component ID: " + componentId);
+                }
+            } else if (componentId >= BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                    && componentId < BatteryConsumer.LAST_MODELED_POWER_COMPONENT_ID) {
+                try {
+                    mPowerComponents[mModeledPowerComponentOffset + componentId] = componentPower;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new IllegalArgumentException(
+                            "Unsupported modeled power component ID: " + componentId);
+                }
+            } else {
                 throw new IllegalArgumentException(
                         "Unsupported custom power component ID: " + componentId);
             }
@@ -160,6 +244,61 @@
         }
 
         /**
+         * 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 BatteryConsumer#TIME_COMPONENT_CPU}.
+         * @param componentUsageDurationMillis Amount of time in milliseconds.
+         */
+        @NonNull
+        public Builder setUsageDurationMillis(@BatteryConsumer.TimeComponent int componentId,
+                long componentUsageDurationMillis) {
+            if (componentId >= BatteryConsumer.TIME_COMPONENT_COUNT) {
+                throw new IllegalArgumentException(
+                        "Unsupported time component ID: " + componentId);
+            }
+            try {
+                mTimeComponents[componentId] = componentUsageDurationMillis;
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new IllegalArgumentException(
+                        "Unsupported time component ID: " + componentId);
+            }
+            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) {
+            if (componentId < BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
+                throw new IllegalArgumentException(
+                        "Unsupported custom time component ID: " + componentId);
+            }
+            try {
+                mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
+                        componentUsageDurationMillis;
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new IllegalArgumentException(
+                        "Unsupported custom time component ID: " + componentId);
+            }
+            return this;
+        }
+
+        public void addPowerAndDuration(Builder other) {
+            for (int i = 0; i < mPowerComponents.length; i++) {
+                mPowerComponents[i] += other.mPowerComponents[i];
+            }
+            for (int i = 0; i < mTimeComponents.length; i++) {
+                mTimeComponents[i] += other.mTimeComponents[i];
+            }
+        }
+
+        /**
          * Creates a read-only object out of the Builder values.
          */
         @NonNull
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 72cd8ba..93c1690 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -631,31 +631,35 @@
     /**
      * Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge
      * Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup
-     * and ready to apply the OTA.
-     * <p>
-     * When the system is already prepared for update and this API is called again with the same
-     * {@code updateToken}, it will not call the intent sender nor request the user enter their Lock
-     * Screen Knowledge Factor.
-     * <p>
-     * When this API is called again with a different {@code updateToken}, the prepared-for-update
-     * status is reset and process repeats as though it's the initial call to this method as
-     * described in the first paragraph.
+     * and ready to apply the OTA. This API is expected to handle requests from multiple clients
+     * simultaneously, e.g. from ota and mainline.
+     *
+     * <p> The behavior of multi-client Resume on Reboot works as follows
+     * <li> Each client should call this function to prepare for Resume on Reboot before calling
+     *      {@link #rebootAndApply(Context, String, boolean)} </li>
+     * <li> One client cannot clear the Resume on Reboot preparation of another client. </li>
+     * <li> If multiple clients have prepared for Resume on Reboot, the subsequent reboot will be
+     *      first come, first served. </li>
      *
      * @param context the Context to use.
-     * @param updateToken token used to indicate which update was prepared
+     * @param updateToken this parameter is deprecated and won't be used. Callers can supply with
+     *                    an empty string. See details in
+     *                    <a href="http://go/multi-client-ror">http://go/multi-client-ror</a>
+     *                    TODO(xunchang) update the link of document with the public doc.
      * @param intentSender the intent to call when the update is prepared; may be {@code null}
      * @throws IOException if there were any errors setting up unattended update
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.RECOVERY)
+    @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT})
     public static void prepareForUnattendedUpdate(@NonNull Context context,
             @NonNull String updateToken, @Nullable IntentSender intentSender) throws IOException {
         if (updateToken == null) {
             throw new NullPointerException("updateToken == null");
         }
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
-        if (!rs.requestLskf(updateToken, intentSender)) {
+        if (!rs.requestLskf(context.getPackageName(), intentSender)) {
             throw new IOException("preparation for update failed");
         }
     }
@@ -664,32 +668,38 @@
      * Request that any previously requested Lock Screen Knowledge Factor (LSKF) is cleared and
      * the preparation for unattended update is reset.
      *
+     * <p> Note that the API won't clear the underlying Resume on Reboot preparation state if
+     * another client has requested. So the reboot call from the other client can still succeed.
+     *
      * @param context the Context to use.
      * @throws IOException if there were any errors clearing the unattended update state
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.RECOVERY)
+    @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT})
     public static void clearPrepareForUnattendedUpdate(@NonNull Context context)
             throws IOException {
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
-        if (!rs.clearLskf()) {
+        if (!rs.clearLskf(context.getPackageName())) {
             throw new IOException("could not reset unattended update state");
         }
     }
 
     /**
-     * Request that the device reboot and apply the update that has been prepared. The
-     * {@code updateToken} must match what was given for {@link #prepareForUnattendedUpdate} or
-     * this will return {@code false}.
+     * Request that the device reboot and apply the update that has been prepared. This API is
+     * deprecated, and is expected to be used by OTA only on devices running Android 11.
      *
      * @param context the Context to use.
-     * @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before
+     * @param updateToken this parameter is deprecated and won't be used. See details in
+     *                    <a href="http://go/multi-client-ror">http://go/multi-client-ror</a>
+     *                    TODO(xunchang) update the link of document with the public doc.
      * @param reason the reboot reason to give to the {@link PowerManager}
      * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an
      *               unattended reboot or if the {@code updateToken} did not match the previously
      *               given token
      * @hide
+     * @deprecated Use {@link #rebootAndApply(Context, String, boolean)} instead
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.RECOVERY)
@@ -699,7 +709,47 @@
             throw new NullPointerException("updateToken == null");
         }
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
-        if (!rs.rebootWithLskf(updateToken, reason)) {
+        // OTA is the sole user, who expects a slot switch.
+        if (!rs.rebootWithLskfAssumeSlotSwitch(context.getPackageName(), reason)) {
+            throw new IOException("system not prepared to apply update");
+        }
+    }
+
+    /**
+     * Query if Resume on Reboot has been prepared for a given caller.
+     *
+     * @param context the Context to use.
+     * @throws IOException if there were any errors connecting to the service or querying the state.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT})
+    public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)
+            throws IOException {
+        RecoverySystem rs = context.getSystemService(RecoverySystem.class);
+        return rs.isLskfCaptured(context.getPackageName());
+    }
+
+    /**
+     * Request that the device reboot and apply the update that has been prepared.
+     * {@link #prepareForUnattendedUpdate} must be called before for the given client,
+     * otherwise the function call will fail.
+     *
+     * @param context the Context to use.
+     * @param reason the reboot reason to give to the {@link PowerManager}
+     * @param slotSwitch true if the caller expects the slot to be switched on A/B devices.
+     * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an
+     *               unattended reboot.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT})
+    public static void rebootAndApply(@NonNull Context context,
+            @NonNull String reason, boolean slotSwitch) throws IOException {
+        RecoverySystem rs = context.getSystemService(RecoverySystem.class);
+        if (!rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch)) {
             throw new IOException("system not prepared to apply update");
         }
     }
@@ -1291,16 +1341,15 @@
     /**
      * Begins the process of asking the user for the Lock Screen Knowledge Factor.
      *
-     * @param updateToken token that will be used in calls to {@link #rebootAndApply} to ensure
-     *                    that the preparation was for the correct update
+     * @param packageName the package name of the caller who requests Resume on Reboot
      * @return true if the request was correct
      * @throws IOException if the recovery system service could not be contacted
      */
-    private boolean requestLskf(String updateToken, IntentSender sender) throws IOException {
+    private boolean requestLskf(String packageName, IntentSender sender) throws IOException {
         try {
-            return mService.requestLskf(updateToken, sender);
+            return mService.requestLskf(packageName, sender);
         } catch (RemoteException e) {
-            throw new IOException("could request update");
+            throw new IOException("could request LSKF capture");
         }
     }
 
@@ -1310,22 +1359,52 @@
      * @return true if the setup for OTA was cleared
      * @throws IOException if the recovery system service could not be contacted
      */
-    private boolean clearLskf() throws IOException {
+    private boolean clearLskf(String packageName) throws IOException {
         try {
-            return mService.clearLskf();
+            return mService.clearLskf(packageName);
         } catch (RemoteException e) {
             throw new IOException("could not clear LSKF");
         }
     }
 
     /**
+     * Queries if the Resume on Reboot has been prepared for a given caller.
+     *
+     * @param packageName the identifier of the caller who requests Resume on Reboot
+     * @return true if Resume on Reboot is prepared.
+     * @throws IOException if the recovery system service could not be contacted
+     */
+    private boolean isLskfCaptured(String packageName) throws IOException {
+        try {
+            return mService.isLskfCaptured(packageName);
+        } catch (RemoteException e) {
+            throw new IOException("could not get LSKF capture state");
+        }
+    }
+
+    /**
      * Calls the recovery system service to reboot and apply update.
      *
-     * @param updateToken the update token for which the update was prepared
      */
-    private boolean rebootWithLskf(String updateToken, String reason) throws IOException {
+    private boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch)
+            throws IOException {
         try {
-            return mService.rebootWithLskf(updateToken, reason);
+            return mService.rebootWithLskf(packageName, reason, slotSwitch);
+        } catch (RemoteException e) {
+            throw new IOException("could not reboot for update");
+        }
+    }
+
+
+    /**
+     * Calls the recovery system service to reboot and apply update. This is the legacy API and
+     * expects a slot switch for A/B devices.
+     *
+     */
+    private boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason)
+            throws IOException {
+        try {
+            return mService.rebootWithLskfAssumeSlotSwitch(packageName, reason);
         } catch (RemoteException e) {
             throw new IOException("could not reboot for update");
         }
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 98c66d1..e9fc2f3 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -37,6 +37,11 @@
         super(message, cause, enableSuppression, writableStackTrace);
     }
 
+    /** @hide */
+    public RemoteException(Throwable cause) {
+        this(cause.getMessage(), cause, true, false);
+    }
+
     /**
      * Rethrow this as an unchecked runtime exception.
      * <p>
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index eb8e717..bb6066e 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -109,7 +109,7 @@
      * The total number of blocks that are free on the file system, including
      * reserved blocks (that are not available to normal applications). This
      * corresponds to the Unix {@code statvfs.f_bfree} field. Most applications
-     * will want to use {@link #getAvailableBlocks()} instead.
+     * will want to use {@link #getAvailableBlocksLong()} instead.
      */
     public long getFreeBlocksLong() {
         return mStat.f_bfree;
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
new file mode 100644
index 0000000..08e358f
--- /dev/null
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -0,0 +1,164 @@
+/*
+ * 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;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 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;
+        private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
+
+        Builder(int customPowerComponentCount, int customTimeComponentCount,
+                boolean includeModeledComponents, @DrainType int drainType) {
+            super(customPowerComponentCount, customTimeComponentCount, includeModeledComponents);
+            mDrainType = drainType;
+        }
+
+        /**
+         * Add a UidBatteryConsumer to this SystemBatteryConsumer. For example,
+         * the UidBatteryConsumer with the UID == {@link Process#BLUETOOTH_UID} should
+         * be added to the SystemBatteryConsumer with the drain type == {@link
+         * #DRAIN_TYPE_BLUETOOTH}.
+         * <p>
+         * Calculated power and duration components of the added battery consumers
+         * are aggregated at the time the SystemBatteryConsumer is built by the {@link #build()}
+         * method.
+         * </p>
+         */
+        public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) {
+            if (mUidBatteryConsumers == null) {
+                mUidBatteryConsumers = new ArrayList<>();
+            }
+            mUidBatteryConsumers.add(uidBatteryConsumerBuilder);
+        }
+
+        /**
+         * Creates a read-only object out of the Builder values.
+         */
+        @NonNull
+        public SystemBatteryConsumer build() {
+            if (mUidBatteryConsumers != null) {
+                for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
+                    UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i);
+                    mPowerComponentsBuilder.addPowerAndDuration(
+                            uidBatteryConsumer.mPowerComponentsBuilder);
+                }
+            }
+            return new SystemBatteryConsumer(this);
+        }
+    }
+}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 5c9067a..0330500 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -18,6 +18,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -38,8 +39,12 @@
     private static final String TAG = "Vibrator";
 
     private final IVibratorService mService;
+    private final IVibratorManagerService mManagerService;
+    private final Object mLock = new Object();
     private final Binder mToken = new Binder();
     private final Context mContext;
+    @GuardedBy("mLock")
+    private VibratorInfo mVibratorInfo;
 
     @GuardedBy("mDelegates")
     private final ArrayMap<OnVibratorStateChangedListener,
@@ -49,6 +54,8 @@
     public SystemVibrator() {
         mContext = null;
         mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
+        mManagerService = IVibratorManagerService.Stub.asInterface(
+                ServiceManager.getService("vibrator_manager"));
     }
 
     @UnsupportedAppUsage
@@ -56,6 +63,8 @@
         super(context);
         mContext = context;
         mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
+        mManagerService = IVibratorManagerService.Stub.asInterface(
+                ServiceManager.getService("vibrator_manager"));
     }
 
     @Override
@@ -207,13 +216,14 @@
     @Override
     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
             AudioAttributes attributes) {
-        if (mService == null) {
+        if (mManagerService == null) {
             Log.w(TAG, "Failed to set always-on effect; no vibrator service.");
             return false;
         }
         try {
             VibrationAttributes atr = new VibrationAttributes.Builder(attributes, effect).build();
-            return mService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, effect, atr);
+            CombinedVibrationEffect combinedEffect = CombinedVibrationEffect.createSynced(effect);
+            return mManagerService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combinedEffect, atr);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to set always-on effect.", e);
         }
@@ -236,26 +246,28 @@
 
     @Override
     public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
-        try {
-            return mService.areEffectsSupported(effectIds);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to query effect support");
-            throw e.rethrowAsRuntimeException();
+        VibratorInfo vibratorInfo = getVibratorInfo();
+        int[] supported = new int[effectIds.length];
+        for (int i = 0; i < effectIds.length; i++) {
+            supported[i] = vibratorInfo == null
+                    ? Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN
+                    : vibratorInfo.isEffectSupported(effectIds[i]);
         }
+        return supported;
     }
 
     @Override
     public boolean[] arePrimitivesSupported(
             @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
-        try {
-            return mService.arePrimitivesSupported(primitiveIds);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to query effect support");
-            throw e.rethrowAsRuntimeException();
+        VibratorInfo vibratorInfo = getVibratorInfo();
+        boolean[] supported = new boolean[primitiveIds.length];
+        for (int i = 0; i < primitiveIds.length; i++) {
+            supported[i] = vibratorInfo == null
+                    ? false : vibratorInfo.isPrimitiveSupported(primitiveIds[i]);
         }
+        return supported;
     }
 
-
     @Override
     public void cancel() {
         if (mService == null) {
@@ -267,4 +279,22 @@
             Log.w(TAG, "Failed to cancel vibration.", e);
         }
     }
+
+    @Nullable
+    private VibratorInfo getVibratorInfo() {
+        try {
+            synchronized (mLock) {
+                if (mVibratorInfo != null) {
+                    return mVibratorInfo;
+                }
+                if (mService == null) {
+                    return null;
+                }
+                return mVibratorInfo = mService.getVibratorInfo();
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to query vibrator info");
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 7dcbf7d..3161766 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -29,11 +29,21 @@
     private final int mUid;
     @Nullable
     private final String mPackageWithHighestDrain;
+    private boolean mSystemComponent;
 
     public int getUid() {
         return mUid;
     }
 
+    /**
+     * Returns true if this battery consumer is considered to be a part of the operating
+     * system itself. For example, the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID}
+     * is a system component.
+     */
+    public boolean isSystemComponent() {
+        return mSystemComponent;
+    }
+
     @Nullable
     public String getPackageWithHighestDrain() {
         return mPackageWithHighestDrain;
@@ -42,6 +52,7 @@
     private UidBatteryConsumer(@NonNull Builder builder) {
         super(builder.mPowerComponentsBuilder.build());
         mUid = builder.mUid;
+        mSystemComponent = builder.mSystemComponent;
         mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
     }
 
@@ -80,14 +91,25 @@
     /**
      * 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;
+        private boolean mSystemComponent;
 
-        public Builder(int customPowerComponentCount, int uid) {
-            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount);
-            mUid = uid;
+        public Builder(int customPowerComponentCount, int customTimeComponentCount,
+                boolean includeModeledComponents, BatteryStats.Uid batteryStatsUid) {
+            super(customPowerComponentCount, customTimeComponentCount, includeModeledComponents);
+            mBatteryStatsUid = batteryStatsUid;
+            mUid = batteryStatsUid.getUid();
+        }
+
+        public BatteryStats.Uid getBatteryStatsUid() {
+            return mBatteryStatsUid;
+        }
+
+        public int getUid() {
+            return mUid;
         }
 
         /**
@@ -99,40 +121,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 name of the package owned by this UID that consumed the highest amount
          * of power since BatteryStats reset.
          */
@@ -141,5 +129,14 @@
             mPackageWithHighestDrain = packageName;
             return this;
         }
+
+        /**
+         * Marks the UidBatteryConsumer as part of the system. For example,
+         * the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID} is considered
+         * as a system component.
+         */
+        public void setSystemComponent(boolean systemComponent) {
+            mSystemComponent = systemComponent;
+        }
     }
 }
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index d672024..7e50ebc 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -223,6 +223,14 @@
     }
 
     /**
+     * Whether a UID belongs to a shared app gid.
+     * @hide
+     */
+    public static boolean isSharedAppGid(int uid) {
+        return getAppIdFromSharedAppGid(uid) != -1;
+    }
+
+    /**
      * Returns the user for a given uid.
      * @param uid A uid for an application running in a particular user.
      * @return A {@link UserHandle} for that user.
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index f76eb86..b57418d 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -477,6 +477,28 @@
     }
 
     /** @hide */
+    public static String effectIdToString(int effectId) {
+        switch (effectId) {
+            case EFFECT_CLICK:
+                return "CLICK";
+            case EFFECT_TICK:
+                return "TICK";
+            case EFFECT_HEAVY_CLICK:
+                return "HEAVY_CLICK";
+            case EFFECT_DOUBLE_CLICK:
+                return "DOUBLE_CLICK";
+            case EFFECT_POP:
+                return "POP";
+            case EFFECT_THUD:
+                return "THUD";
+            case EFFECT_TEXTURE_TICK:
+                return "TEXTURE_TICK";
+            default:
+                return Integer.toString(effectId);
+        }
+    }
+
+    /** @hide */
     @TestApi
     public static class OneShot extends VibrationEffect implements Parcelable {
         private final long mDuration;
@@ -1201,10 +1223,8 @@
                     return "PRIMITIVE_QUICK_FALL";
                 case PRIMITIVE_TICK:
                     return "PRIMITIVE_TICK";
-
                 default:
                     return Integer.toString(id);
-
             }
         }
 
diff --git a/core/java/android/os/VibratorInfo.aidl b/core/java/android/os/VibratorInfo.aidl
new file mode 100644
index 0000000..9a7cb13
--- /dev/null
+++ b/core/java/android/os/VibratorInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable VibratorInfo;
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
new file mode 100644
index 0000000..07272e7
--- /dev/null
+++ b/core/java/android/os/VibratorInfo.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.SparseBooleanArray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A VibratorInfo describes the capabilities of a {@link Vibrator}.
+ *
+ * This description includes its capabilities, list of supported effects and composition primitives.
+ *
+ * @hide
+ */
+public final class VibratorInfo implements Parcelable {
+
+    /**
+     * Capability to set amplitude values to vibrations.
+     * @hide
+     */
+    // Internally this maps to the HAL constant IVibrator::CAP_AMPLITUDE_CONTROL
+    public static final int CAPABILITY_AMPLITUDE_CONTROL = 4;
+
+    /**
+     * Capability to compose primitives into a single effect.
+     * @hide
+     */
+    // Internally this maps to the HAL constant IVibrator::CAP_COMPOSE_EFFECTS
+    public static final int CAPABILITY_COMPOSE_EFFECTS = 32;
+
+    private final int mId;
+    private final long mCapabilities;
+    @Nullable
+    private final SparseBooleanArray mSupportedEffects;
+    @Nullable
+    private final SparseBooleanArray mSupportedPrimitives;
+
+    VibratorInfo(Parcel in) {
+        mId = in.readInt();
+        mCapabilities = in.readLong();
+        mSupportedEffects = in.readSparseBooleanArray();
+        mSupportedPrimitives = in.readSparseBooleanArray();
+    }
+
+    /** @hide */
+    public VibratorInfo(int id, long capabilities, int[] supportedEffects,
+            int[] supportedPrimitives) {
+        mId = id;
+        mCapabilities = capabilities;
+        mSupportedEffects = toSparseBooleanArray(supportedEffects);
+        mSupportedPrimitives = toSparseBooleanArray(supportedPrimitives);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mId);
+        dest.writeLong(mCapabilities);
+        dest.writeSparseBooleanArray(mSupportedEffects);
+        dest.writeSparseBooleanArray(mSupportedPrimitives);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof VibratorInfo)) {
+            return false;
+        }
+        VibratorInfo that = (VibratorInfo) o;
+        return mId == that.mId && mCapabilities == that.mCapabilities
+                && Objects.equals(mSupportedEffects, that.mSupportedEffects)
+                && Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives);
+    }
+
+    @Override
+    public String toString() {
+        return "VibratorInfo{"
+                + "mId=" + mId
+                + ", mCapabilities=" + Arrays.toString(getCapabilitiesNames())
+                + ", mCapabilities flags=" + mCapabilities
+                + ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames())
+                + ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames())
+                + '}';
+    }
+
+    /** Return the id of this vibrator. */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * Check whether the vibrator has amplitude control.
+     *
+     * @return True if the hardware can control the amplitude of the vibrations, otherwise false.
+     */
+    public boolean hasAmplitudeControl() {
+        return hasCapability(CAPABILITY_AMPLITUDE_CONTROL);
+    }
+
+    /**
+     * Query whether the vibrator supports the given effect.
+     *
+     * @param effectId Which effects to query for.
+     * @return {@link Vibrator#VIBRATION_EFFECT_SUPPORT_YES} if the effect is supported,
+     * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
+     * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
+     * supported or not.
+     */
+    @Vibrator.VibrationEffectSupport
+    public int isEffectSupported(@VibrationEffect.EffectType int effectId) {
+        if (mSupportedEffects == null) {
+            return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN;
+        }
+        return mSupportedEffects.get(effectId, false) ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES
+                : Vibrator.VIBRATION_EFFECT_SUPPORT_NO;
+    }
+
+    /**
+     * Query whether the vibrator supports the given primitive.
+     *
+     * @param primitiveId Which primitives to query for.
+     * @return Whether the primitive is supported.
+     */
+    public boolean isPrimitiveSupported(@VibrationEffect.Composition.Primitive int primitiveId) {
+        return hasCapability(CAPABILITY_COMPOSE_EFFECTS) && mSupportedPrimitives != null
+                && mSupportedPrimitives.get(primitiveId, false);
+    }
+
+    /**
+     * Check against this vibrator capabilities.
+     *
+     * @param capability one of IVibrator.CAP_*
+     * @return true if this vibrator has this capability, false otherwise
+     * @hide
+     */
+    public boolean hasCapability(long capability) {
+        return (mCapabilities & capability) == capability;
+    }
+
+    private String[] getCapabilitiesNames() {
+        List<String> names = new ArrayList<>();
+        if (hasCapability(CAPABILITY_AMPLITUDE_CONTROL)) {
+            names.add("AMPLITUDE_CONTROL");
+        }
+        if (hasCapability(CAPABILITY_COMPOSE_EFFECTS)) {
+            names.add("COMPOSE_EFFECTS");
+        }
+        return names.toArray(new String[names.size()]);
+    }
+
+    private String[] getSupportedEffectsNames() {
+        if (mSupportedEffects == null) {
+            return new String[0];
+        }
+        String[] names = new String[mSupportedEffects.size()];
+        for (int i = 0; i < mSupportedEffects.size(); i++) {
+            names[i] = VibrationEffect.effectIdToString(mSupportedEffects.keyAt(i));
+        }
+        return names;
+    }
+
+    private String[] getSupportedPrimitivesNames() {
+        if (mSupportedPrimitives == null) {
+            return new String[0];
+        }
+        String[] names = new String[mSupportedPrimitives.size()];
+        for (int i = 0; i < mSupportedPrimitives.size(); i++) {
+            names[i] = VibrationEffect.Composition.primitiveToString(mSupportedPrimitives.keyAt(i));
+        }
+        return names;
+    }
+
+    @Nullable
+    private static SparseBooleanArray toSparseBooleanArray(int[] values) {
+        if (values == null) {
+            return null;
+        }
+        SparseBooleanArray array = new SparseBooleanArray();
+        for (int value : values) {
+            array.put(value, true);
+        }
+        return array;
+    }
+
+    @NonNull
+    public static final Creator<VibratorInfo> CREATOR =
+            new Creator<VibratorInfo>() {
+                @Override
+                public VibratorInfo createFromParcel(Parcel in) {
+                    return new VibratorInfo(in);
+                }
+
+                @Override
+                public VibratorInfo[] newArray(int size) {
+                    return new VibratorInfo[size];
+                }
+            };
+}
diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java
new file mode 100644
index 0000000..1d5a587
--- /dev/null
+++ b/core/java/android/os/VibratorManager.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+
+/**
+ * VibratorManager provides access to multiple vibrators, as well as the ability to run them in
+ * a synchronized fashion.
+ */
+public abstract class VibratorManager {
+    /** @hide */
+    protected static final String TAG = "VibratorManager";
+
+    /**
+     * {@hide}
+     */
+    public VibratorManager() {
+    }
+
+    /**
+     * This method lists all available actuator ids, returning a possible empty list.
+     * If the device has only a single actuator, this should return a single entry with a
+     * default id.
+     */
+    @NonNull
+    public abstract int[] getVibratorIds();
+
+    /**
+    * Returns a Vibrator service for given id.
+    * This allows users to perform a vibration effect on a single actuator.
+    */
+    @NonNull
+    public abstract Vibrator getVibrator(int vibratorId);
+
+    /**
+    * Returns the system default Vibrator service.
+    */
+    @NonNull
+    public abstract Vibrator getDefaultVibrator();
+
+    /**
+     * Vibrates all actuators by passing each VibrationEffect within CombinedVibrationEffect
+     * to the respective actuator, in sync.
+     */
+    public abstract void vibrate(@NonNull CombinedVibrationEffect effect);
+}
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.java b/core/java/android/os/connectivity/GpsBatteryStats.java
index ef03caa..5e21bd3 100644
--- a/core/java/android/os/connectivity/GpsBatteryStats.java
+++ b/core/java/android/os/connectivity/GpsBatteryStats.java
@@ -15,11 +15,10 @@
  */
 package android.os.connectivity;
 
+import android.location.GnssSignalQuality;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.internal.location.gnssmetrics.GnssMetrics;
-
 import java.util.Arrays;
 
 /**
@@ -85,7 +84,7 @@
 
   public void setTimeInGpsSignalQualityLevel(long[] t) {
     mTimeInGpsSignalQualityLevel = Arrays.copyOfRange(t, 0,
-        Math.min(t.length, GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS));
+        Math.min(t.length, GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS));
     return;
   }
 
@@ -102,7 +101,7 @@
   private void initialize() {
     mLoggingDurationMs = 0;
     mEnergyConsumedMaMs = 0;
-    mTimeInGpsSignalQualityLevel = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+    mTimeInGpsSignalQualityLevel = new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
     return;
   }
 }
\ No newline at end of file
diff --git a/core/java/android/os/connectivity/OWNERS b/core/java/android/os/connectivity/OWNERS
new file mode 100644
index 0000000..a0f0238
--- /dev/null
+++ b/core/java/android/os/connectivity/OWNERS
@@ -0,0 +1 @@
+dplotnikov@google.com
diff --git a/core/java/android/os/health/OWNERS b/core/java/android/os/health/OWNERS
new file mode 100644
index 0000000..6045344
--- /dev/null
+++ b/core/java/android/os/health/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 26805
+
+dplotnikov@google.com
+mwachens@google.com
diff --git a/core/java/android/os/image/OWNERS b/core/java/android/os/image/OWNERS
new file mode 100644
index 0000000..389b55b
--- /dev/null
+++ b/core/java/android/os/image/OWNERS
@@ -0,0 +1 @@
+andrewhsieh@google.com
diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS
new file mode 100644
index 0000000..3795493
--- /dev/null
+++ b/core/java/android/os/incremental/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 554432
+alexbuy@google.com
+schfan@google.com
+toddke@google.com
+zyy@google.com
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
new file mode 100644
index 0000000..8af7de5
--- /dev/null
+++ b/core/java/android/os/storage/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 95221
+
+narayan@google.com
+nandana@google.com
+corinac@google.com
+zezeozue@google.com
+maco@google.com
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 55ba15a..b12bb2e 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -101,4 +101,15 @@
      * Return true if uid is external storage service.
      */
     public abstract boolean isExternalStorageService(int uid);
+
+    /**
+     * Frees cache held by ExternalStorageService.
+     *
+     * <p> Blocks until the service frees the cache or fails in doing so.
+     *
+     * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed,
+     *                   null value indicates private internal volume.
+     * @param bytes number of bytes which need to be freed
+     */
+    public abstract void freeCache(@Nullable String volumeUuid, long bytes);
 }
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/permission/ILegacyPermissionManager.aidl b/core/java/android/permission/ILegacyPermissionManager.aidl
new file mode 100644
index 0000000..3bd4bf5
--- /dev/null
+++ b/core/java/android/permission/ILegacyPermissionManager.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.permission;
+
+import android.content.pm.ParceledListSlice;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.os.UserHandle;
+import android.permission.IOnPermissionsChangeListener;
+
+/**
+ * Interface to communicate directly with the legacy permission manager service.
+ *
+ * @see PermissionManager
+ * @hide
+ */
+interface ILegacyPermissionManager {
+    int checkDeviceIdentifierAccess(String packageName, String callingFeatureId, String message, int pid, int uid);
+
+    void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToEnabledTelephonyDataServices(
+            in String[] packageNames, int userId);
+
+    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+            in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
+
+    void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
+}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index a94077d..441908d 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -52,19 +52,17 @@
 
     int checkUidPermission(String permName, int uid);
 
-    int checkDeviceIdentifierAccess(String packageName, String callingFeatureId, String message, int pid, int uid);
-
     void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
 
     void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
 
-    List<String> getWhitelistedRestrictedPermissions(String packageName,
+    List<String> getAllowlistedRestrictedPermissions(String packageName,
             int flags, int userId);
 
-    boolean addWhitelistedRestrictedPermission(String packageName, String permName,
+    boolean addAllowlistedRestrictedPermission(String packageName, String permissionName,
             int flags, int userId);
 
-    boolean removeWhitelistedRestrictedPermission(String packageName, String permName,
+    boolean removeAllowlistedRestrictedPermission(String packageName, String permissionName,
             int flags, int userId);
 
     void grantRuntimePermission(String packageName, String permName, int userId);
@@ -73,20 +71,6 @@
 
     void resetRuntimePermissions();
 
-    void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
-
-    void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
-
-    void grantDefaultPermissionsToEnabledTelephonyDataServices(
-            in String[] packageNames, int userId);
-
-    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-            in String[] packageNames, int userId);
-
-    void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
-
-    void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
-
     boolean shouldShowRequestPermissionRationale(String permName,
             String packageName, int userId);
 
@@ -103,7 +87,7 @@
 
     List<String> getAutoRevokeExemptionGrantedPackages(int userId);
 
-    boolean setAutoRevokeWhitelisted(String packageName, boolean whitelisted, int userId);
+    boolean setAutoRevokeExempted(String packageName, boolean exempted, int userId);
 
-    boolean isAutoRevokeWhitelisted(String packageName, int userId);
+    boolean isAutoRevokeExempted(String packageName, int userId);
 }
diff --git a/core/java/android/permission/LegacyPermissionManager.java b/core/java/android/permission/LegacyPermissionManager.java
new file mode 100644
index 0000000..b66dd82
--- /dev/null
+++ b/core/java/android/permission/LegacyPermissionManager.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * System level service for accessing the permission capabilities of the platform, version 2.
+ *
+ * @hide
+ */
+//@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+@SystemService(Context.LEGACY_PERMISSION_SERVICE)
+public final class LegacyPermissionManager {
+    private final ILegacyPermissionManager mLegacyPermissionManager;
+
+    /**
+     * Creates a new instance.
+     *
+     * @hide
+     */
+    public LegacyPermissionManager() throws ServiceManager.ServiceNotFoundException {
+        this(ILegacyPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
+                "legacy_permission")));
+    }
+
+    /**
+     * Creates a new instance with the provided instantiation of the ILegacyPermissionManager.
+     *
+     * @param legacyPermissionManager injectable legacy permission manager service
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public LegacyPermissionManager(@NonNull ILegacyPermissionManager legacyPermissionManager) {
+        mLegacyPermissionManager = legacyPermissionManager;
+    }
+
+    /**
+     * Checks whether the package with the given pid/uid can read device identifiers.
+     *
+     * @param packageName      the name of the package to be checked for identifier access
+     * @param message          the message to be used for logging during identifier access
+     *                         verification
+     * @param callingFeatureId the feature in the package
+     * @param pid              the process id of the package to be checked
+     * @param uid              the uid of the package to be checked
+     * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier
+     * access, {@link PackageManager#PERMISSION_DENIED} otherwise
+     * @hide
+     */
+    //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
+            @Nullable String callingFeatureId, int pid, int uid) {
+        try {
+            return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message,
+                    callingFeatureId, pid, uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grant default permissions to currently active LUI app
+     * @param packageName The package name for the LUI app
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void grantDefaultPermissionsToLuiApp(
+            @NonNull String packageName, @NonNull UserHandle user,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.grantDefaultPermissionsToActiveLuiApp(
+                    packageName, user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Revoke default permissions to currently active LUI app
+     * @param packageNames The package names for the LUI apps
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void revokeDefaultPermissionsFromLuiApps(
+            @NonNull String[] packageNames, @NonNull UserHandle user,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.revokeDefaultPermissionsFromLuiApps(
+                    packageNames, user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grant default permissions to currently active Ims services
+     * @param packageNames The package names for the Ims services
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void grantDefaultPermissionsToEnabledImsServices(
+            @NonNull String[] packageNames, @NonNull UserHandle user,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.grantDefaultPermissionsToEnabledImsServices(
+                    packageNames, user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grant default permissions to currently enabled telephony data services
+     * @param packageNames The package name for the services
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void grantDefaultPermissionsToEnabledTelephonyDataServices(
+            @NonNull String[] packageNames, @NonNull UserHandle user,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices(
+                    packageNames, user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Revoke default permissions to currently active telephony data services
+     * @param packageNames The package name for the services
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when revoke completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+            @NonNull String[] packageNames, @NonNull UserHandle user,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+                    packageNames, user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grant default permissions to currently enabled carrier apps
+     * @param packageNames Package names of the apps to be granted permissions
+     * @param user The user handle
+     * @param executor The executor for the callback
+     * @param callback The callback provided by caller to be notified when grant completes
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+    public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames,
+            @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<Boolean> callback) {
+        try {
+            mLegacyPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
+                    user.getIdentifier());
+            executor.execute(() -> callback.accept(true));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
new file mode 100644
index 0000000..d09f351
--- /dev/null
+++ b/core/java/android/permission/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137825
+
+moltmann@google.com
+evanseverson@google.com
+ntmyren@google.com
+zhanghai@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index e4220dd..87f3764 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -19,7 +19,7 @@
 import static android.os.Build.VERSION_CODES.S;
 
 import android.Manifest;
-import android.annotation.CallbackExecutor;
+import android.annotation.CheckResult;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -29,6 +29,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.PropertyInvalidatedCache;
 import android.compat.annotation.ChangeId;
@@ -36,15 +37,25 @@
 import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
 import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.DebugUtils;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.Immutable;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.CollectionUtils;
 
 import java.util.ArrayList;
@@ -52,8 +63,6 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
 
 /**
  * System level service for accessing the permission capabilities of the platform.
@@ -63,7 +72,7 @@
 @SystemApi
 @SystemService(Context.PERMISSION_SERVICE)
 public final class PermissionManager {
-    private static final String TAG = PermissionManager.class.getName();
+    private static final String LOG_TAG = PermissionManager.class.getName();
 
     /** @hide */
     public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
@@ -83,41 +92,688 @@
     @EnabledAfter(targetSdkVersion = S)
     public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
 
+    /**
+     * Note: Changing this won't do anything on its own - you should also change the filtering in
+     * {@link #shouldTraceGrant}.
+     *
+     * @hide
+     */
+    public static final boolean DEBUG_TRACE_GRANTS = false;
+    /**
+     * @hide
+     */
+    public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
+
     private final @NonNull Context mContext;
 
     private final IPackageManager mPackageManager;
 
     private final IPermissionManager mPermissionManager;
 
+    private final LegacyPermissionManager mLegacyPermissionManager;
+
+    private final ArrayMap<PackageManager.OnPermissionsChangedListener,
+            IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
+
     private List<SplitPermissionInfo> mSplitPermissionInfos;
 
     /**
      * Creates a new instance.
      *
-     * @param context The current context in which to operate.
+     * @param context The current context in which to operate
+     *
      * @hide
      */
-    public PermissionManager(@NonNull Context context, IPackageManager packageManager)
+    public PermissionManager(@NonNull Context context)
             throws ServiceManager.ServiceNotFoundException {
-        this(context, packageManager, IPermissionManager.Stub.asInterface(
-                ServiceManager.getServiceOrThrow("permissionmgr")));
+        mContext = context;
+        mPackageManager = AppGlobals.getPackageManager();
+        mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
+                "permissionmgr"));
+        mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
     }
 
     /**
-     * Creates a new instance with the provided instantiation of the IPermissionManager.
+     * Retrieve all of the information we know about a particular permission.
      *
-     * @param context           the current context in which to operate
-     * @param packageManager    package manager service to be used for package related permission
-     *                          requests
-     * @param permissionManager injectable permission manager service
+     * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the
+     *                       permission you are interested in
+     * @param flags additional option flags to modify the data returned
+     * @return a {@link PermissionInfo} containing information about the permission, or {@code null}
+     *         if not found
+     *
+     * @hide Pending API
+     */
+    @Nullable
+    public PermissionInfo getPermissionInfo(@NonNull String permissionName,
+            @PackageManager.PermissionInfoFlags int flags) {
+        try {
+            final String packageName = mContext.getOpPackageName();
+            return mPermissionManager.getPermissionInfo(permissionName, packageName, flags);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Query for all of the permissions associated with a particular group.
+     *
+     * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the
+     *                  permission group you are interested in. Use {@code null} to find all of the
+     *                  permissions not associated with a group
+     * @param flags additional option flags to modify the data returned
+     * @return a list of {@link PermissionInfo} containing information about all of the permissions
+     *         in the given group, or {@code null} if the group is not found
+     *
+     * @hide Pending API
+     */
+    @Nullable
+    public List<PermissionInfo> queryPermissionsByGroup(@NonNull String groupName,
+            @PackageManager.PermissionInfoFlags int flags) {
+        try {
+            final ParceledListSlice<PermissionInfo> parceledList =
+                    mPermissionManager.queryPermissionsByGroup(groupName, flags);
+            if (parceledList == null) {
+                return null;
+            }
+            return parceledList.getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Add a new dynamic permission to the system. For this to work, your package must have defined
+     * a permission tree through the
+     * {@link android.R.styleable#AndroidManifestPermissionTree &lt;permission-tree&gt;} tag in its
+     * manifest. A package can only add permissions to trees that were defined by either its own
+     * package or another with the same user id; a permission is in a tree if it matches the name of
+     * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree
+     * "com.foo".
+     * <p>
+     * It is good to make your permission tree name descriptive, because you are taking possession
+     * of that entire set of permission names. Thus, it must be under a domain you control, with a
+     * suffix that will not match any normal permissions that may be declared in any applications
+     * that are part of that domain.
+     * <p>
+     * New permissions must be added before any .apks are installed that use those permissions.
+     * Permissions you add through this method are remembered across reboots of the device. If the
+     * given permission already exists, the info you supply here will be used to update it.
+     *
+     * @param permissionInfo description of the permission to be added
+     * @param async whether the persistence of the permission should be asynchronous, allowing it to
+     *              return quicker and batch a series of adds, at the expense of no guarantee the
+     *              added permission will be retained if the device is rebooted before it is
+     *              written.
+     * @return {@code true} if a new permission was created, {@code false} if an existing one was
+     *         updated
+     * @throws SecurityException if you are not allowed to add the given permission name
+     *
+     * @see #removePermission(String)
+     *
+     * @hide Pending API
+     */
+    public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) {
+        try {
+            return mPermissionManager.addPermission(permissionInfo, async);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Removes a permission that was previously added with
+     * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are
+     * only allowed to remove permissions that you are allowed to add.
+     *
+     * @param permissionName the name of the permission to remove
+     * @throws SecurityException if you are not allowed to remove the given permission name
+     *
+     * @see #addPermission(PermissionInfo, boolean)
+     *
+     * @hide Pending API
+     */
+    public void removePermission(@NonNull String permissionName) {
+        try {
+            mPermissionManager.removePermission(permissionName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Retrieve all of the information we know about a particular group of permissions.
+     *
+     * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the
+     *                  permission you are interested in
+     * @param flags additional option flags to modify the data returned
+     * @return a {@link PermissionGroupInfo} containing information about the permission, or
+     *         {@code null} if not found
+     *
+     * @hide Pending API
+     */
+    @Nullable
+    public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
+            @PackageManager.PermissionGroupInfoFlags int flags) {
+        try {
+            return mPermissionManager.getPermissionGroupInfo(groupName, flags);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Retrieve all of the known permission groups in the system.
+     *
+     * @param flags additional option flags to modify the data returned
+     * @return a list of {@link PermissionGroupInfo} containing information about all of the known
+     *         permission groups
+     *
+     * @hide Pending API
+     */
+    @NonNull
+    public List<PermissionGroupInfo> getAllPermissionGroups(
+            @PackageManager.PermissionGroupInfoFlags int flags) {
+        try {
+            final ParceledListSlice<PermissionGroupInfo> parceledList =
+                    mPermissionManager.getAllPermissionGroups(flags);
+            if (parceledList == null) {
+                return Collections.emptyList();
+            }
+            return parceledList.getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Checks whether a particular permissions has been revoked for a package by policy. Typically
+     * the device owner or the profile owner may apply such a policy. The user cannot grant policy
+     * revoked permissions, hence the only way for an app to get such a permission is by a policy
+     * change.
+     *
+     * @param packageName the name of the package you are checking against
+     * @param permissionName the name of the permission you are checking for
+     *
+     * @return whether the permission is restricted by policy
+     *
+     * @hide Pending API
+     */
+    @CheckResult
+    public boolean isPermissionRevokedByPolicy(@NonNull String packageName,
+            @NonNull String permissionName) {
+        try {
+            return mPermissionManager.isPermissionRevokedByPolicy(permissionName, packageName,
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) {
+        // To be modified when debugging
+        return false;
+    }
+
+    /**
+     * Grant a runtime permission to an application which the application does not already have. The
+     * permission must have been requested by the application. If the application is not allowed to
+     * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
+     * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current
+     * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param packageName the package to which to grant the permission
+     * @param permissionName the permission name to grant
+     * @param user the user for which to grant the permission
+     *
+     * @see #revokeRuntimePermission(String, String, android.os.UserHandle)
+     *
      * @hide
      */
-    @VisibleForTesting
-    public PermissionManager(@NonNull Context context, IPackageManager packageManager,
-            IPermissionManager permissionManager) {
-        mContext = context;
-        mPackageManager = packageManager;
-        mPermissionManager = permissionManager;
+    @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
+    //@SystemApi
+    public void grantRuntimePermission(@NonNull String packageName,
+            @NonNull String permissionName, @NonNull UserHandle user) {
+        if (DEBUG_TRACE_GRANTS
+                && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
+            Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " "
+                    + permissionName + " for user " + user.getIdentifier(), new RuntimeException());
+        }
+        try {
+            mPermissionManager.grantRuntimePermission(packageName, permissionName,
+                    user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Revoke a runtime permission that was previously granted by
+     * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must
+     * have been requested by and granted to the application. If the application is not allowed to
+     * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
+     * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current
+     * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param packageName the package from which to revoke the permission
+     * @param permName the permission name to revoke
+     * @param user the user for which to revoke the permission
+     * @param reason the reason for the revoke, or {@code null} for unspecified
+     *
+     * @see #grantRuntimePermission(String, String, android.os.UserHandle)
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
+    //@SystemApi
+    public void revokeRuntimePermission(@NonNull String packageName,
+            @NonNull String permName, @NonNull UserHandle user, @Nullable String reason) {
+        if (DEBUG_TRACE_PERMISSION_UPDATES
+                && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
+            Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
+                    + permName + " for user " + user.getIdentifier() + " with reason "
+                    + reason, new RuntimeException());
+        }
+        try {
+            mPermissionManager
+                    .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the state flags associated with a permission.
+     *
+     * @param packageName the package name for which to get the flags
+     * @param permissionName the permission for which to get the flags
+     * @param user the user for which to get permission flags
+     * @return the permission flags
+     *
+     * @hide
+     */
+    @PackageManager.PermissionFlags
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.GET_RUNTIME_PERMISSIONS
+    })
+    //@SystemApi
+    public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName,
+            @NonNull UserHandle user) {
+        try {
+            return mPermissionManager.getPermissionFlags(permissionName, packageName,
+                    user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Updates the flags associated with a permission by replacing the flags in the specified mask
+     * with the provided flag values.
+     *
+     * @param packageName The package name for which to update the flags
+     * @param permissionName The permission for which to update the flags
+     * @param flagMask The flags which to replace
+     * @param flagValues The flags with which to replace
+     * @param user The user for which to update the permission flags
+     *
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+    })
+    //@SystemApi
+    public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName,
+            @PackageManager.PermissionFlags int flagMask,
+            @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) {
+        if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName,
+                user.getIdentifier())) {
+            Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for "
+                    + packageName + " " + permissionName + " for user "
+                    + user.getIdentifier() + ": " + DebugUtils.flagsToString(
+                    PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := "
+                    + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_",
+                    flagValues), new RuntimeException());
+        }
+        try {
+            final boolean checkAdjustPolicyFlagPermission =
+                    mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
+            mPermissionManager.updatePermissionFlags(permissionName, packageName, flagMask,
+                    flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the restricted permissions that have been allowlisted and the app is allowed to have
+     * them granted in their full form.
+     * <p>
+     * Permissions can be hard restricted which means that the app cannot hold them or soft
+     * restricted where the app can hold the permission but in a weaker form. Whether a permission
+     * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
+     * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
+     * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
+     * and allowlisting a soft restricted permission allows the app to hold the permission in its
+     * full, unrestricted form.
+     * <p>
+     * There are four allowlists:
+     * <ol>
+     * <li>
+     * One for cases where the system permission policy allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
+     * accessed by pre-installed holders of a dedicated permission.
+     * <li>
+     * One for cases where the system allowlists the permission when upgrading from an OS version in
+     * which the permission was not restricted to an OS version in which the permission is
+     * restricted. This list corresponds to the
+     * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
+     * pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the installer of the package allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the system exempts the permission when granting a role. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission.
+     * </ol>
+     *
+     * @param packageName the app for which to get allowlisted permissions
+     * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be
+     *                      passed.
+     * @return the allowlisted permissions that are on any of the allowlists you query for
+     * @throws SecurityException if you try to access a allowlist that you have no access to
+     *
+     * @see #addAllowlistedRestrictedPermission(String, String, int)
+     * @see #removeAllowlistedRestrictedPermission(String, String, int)
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
+     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
+     *
+     * @hide Pending API
+     */
+    @NonNull
+    @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
+            conditional = true)
+    public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
+            @PackageManager.PermissionWhitelistFlags int allowlistFlag) {
+        try {
+            final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions(
+                    packageName, allowlistFlag, mContext.getUserId());
+            if (allowlist == null) {
+                return Collections.emptySet();
+            }
+            return new ArraySet<>(allowlist);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Adds a allowlisted restricted permission for an app.
+     * <p>
+     * Permissions can be hard restricted which means that the app cannot hold them or soft
+     * restricted where the app can hold the permission but in a weaker form. Whether a permission
+     * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
+     * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
+     * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
+     * and allowlisting a soft restricted permission allows the app to hold the permission in its
+     * full, unrestricted form.
+     * <p>There are four allowlists:
+     * <ol>
+     * <li>
+     * One for cases where the system permission policy allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
+     * accessed by pre-installed holders of a dedicated permission.
+     * <li>
+     * One for cases where the system allowlists the permission when upgrading from an OS version in
+     * which the permission was not restricted to an OS version in which the permission is
+     * restricted. This list corresponds to the
+     * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
+     * pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the installer of the package allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the system exempts the permission when granting a role. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission.
+     * </ol>
+     * <p>
+     * You need to specify the allowlists for which to set the allowlisted permissions which will
+     * clear the previous allowlisted permissions and replace them with the provided ones.
+     *
+     * @param packageName the app for which to get allowlisted permissions
+     * @param permissionName the allowlisted permission to add
+     * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all
+     *                       specified allowlists.
+     * @return whether the permission was added to the allowlist
+     * @throws SecurityException if you try to modify a allowlist that you have no access to.
+     *
+     * @see #getAllowlistedRestrictedPermissions(String, int)
+     * @see #removeAllowlistedRestrictedPermission(String, String, int)
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
+     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
+     *
+     * @hide Pending API
+     */
+    @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
+            conditional = true)
+    public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permissionName,
+            @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
+        try {
+            return mPermissionManager.addAllowlistedRestrictedPermission(packageName,
+                    permissionName, allowlistFlags, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Removes a allowlisted restricted permission for an app.
+     * <p>
+     * Permissions can be hard restricted which means that the app cannot hold them or soft
+     * restricted where the app can hold the permission but in a weaker form. Whether a permission
+     * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
+     * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
+     * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
+     * and allowlisting a soft restricted permission allows the app to hold the permission in its
+     * full, unrestricted form.
+     * <p>There are four allowlists:
+     * <ol>
+     * <li>
+     * One for cases where the system permission policy allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
+     * accessed by pre-installed holders of a dedicated permission.
+     * <li>
+     * One for cases where the system allowlists the permission when upgrading from an OS version in
+     * which the permission was not restricted to an OS version in which the permission is
+     * restricted. This list corresponds to the
+     * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
+     * pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the installer of the package allowlists a permission. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission or the installer on record.
+     * <li>
+     * One for cases where the system exempts the permission when granting a role. This list
+     * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
+     * accessed by pre-installed holders of a dedicated permission.
+     * </ol>
+     * <p>
+     * You need to specify the allowlists for which to set the allowlisted permissions which will
+     * clear the previous allowlisted permissions and replace them with the provided ones.
+     *
+     * @param packageName the app for which to get allowlisted permissions
+     * @param permissionName the allowlisted permission to remove
+     * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all
+     *                       specified allowlists.
+     * @return whether the permission was removed from the allowlist
+     * @throws SecurityException if you try to modify a allowlist that you have no access to.
+     *
+     * @see #getAllowlistedRestrictedPermissions(String, int)
+     * @see #addAllowlistedRestrictedPermission(String, String, int)
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
+     * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
+     * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
+     *
+     * @hide Pending API
+     */
+    @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
+            conditional = true)
+    public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permissionName,
+            @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
+        try {
+            return mPermissionManager.removeAllowlistedRestrictedPermission(packageName,
+                    permissionName, allowlistFlags, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Checks whether an application is exempted from having its permissions be automatically
+     * revoked when the app is unused for an extended period of time.
+     * <p>
+     * Only the installer on record that installed the given package, or a holder of
+     * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this.
+     *
+     * @param packageName the app for which to set exemption
+     * @return whether the app is exempted
+     * @throws SecurityException if you you have no access to this
+     *
+     * @see #setAutoRevokeExempted
+     *
+     * @hide Pending API
+     */
+    @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
+            conditional = true)
+    public boolean isAutoRevokeExempted(@NonNull String packageName) {
+        try {
+            return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Marks an application exempted from having its permissions be automatically revoked when the
+     * app is unused for an extended period of time.
+     * <p>
+     * Only the installer on record that installed the given package is allowed to call this.
+     * <p>
+     * Packages start in exempted state, and it is the installer's responsibility to un-exempt the
+     * packages it installs, unless auto-revoking permissions from that package would cause
+     * breakages beyond having to re-request the permission(s).
+     *
+     * @param packageName the app for which to set exemption
+     * @param exempted whether the app should be exempted
+     * @return whether any change took effect
+     * @throws SecurityException if you you have no access to modify this
+     *
+     * @see #isAutoRevokeExempted
+     *
+     * @hide Pending API
+     */
+    @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
+            conditional = true)
+    public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) {
+        try {
+            return mPermissionManager.setAutoRevokeExempted(packageName, exempted,
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get whether you should show UI with rationale for requesting a permission. You should do this
+     * only if you do not have the permission and the context in which the permission is requested
+     * does not clearly communicate to the user what would be the benefit from grating this
+     * permission.
+     *
+     * @param permissionName a permission your app wants to request
+     * @return whether you can show permission rationale UI
+     *
+     * @hide
+     */
+    //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) {
+        try {
+            final String packageName = mContext.getPackageName();
+            return mPermissionManager.shouldShowRequestPermissionRationale(permissionName,
+                    packageName, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Add a listener for permission changes for installed packages.
+     *
+     * @param listener the listener to add
+     *
+     * @hide
+     */
+    //@SystemApi
+    @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
+    public void addOnPermissionsChangeListener(
+            @NonNull PackageManager.OnPermissionsChangedListener listener) {
+        synchronized (mPermissionListeners) {
+            if (mPermissionListeners.get(listener) != null) {
+                return;
+            }
+            final OnPermissionsChangeListenerDelegate delegate =
+                    new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
+            try {
+                mPermissionManager.addOnPermissionsChangeListener(delegate);
+                mPermissionListeners.put(listener, delegate);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Remove a listener for permission changes for installed packages.
+     *
+     * @param listener the listener to remove
+     *
+     * @hide
+     */
+    //@SystemApi
+    @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
+    public void removeOnPermissionsChangeListener(
+            @NonNull PackageManager.OnPermissionsChangedListener listener) {
+        synchronized (mPermissionListeners) {
+            final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
+            if (delegate != null) {
+                try {
+                    mPermissionManager.removeOnPermissionsChangeListener(delegate);
+                    mPermissionListeners.remove(listener);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
     }
 
     /**
@@ -188,7 +844,7 @@
         try {
             parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
         } catch (RemoteException e) {
-            Slog.e(TAG, "Error getting split permissions", e);
+            Slog.e(LOG_TAG, "Error getting split permissions", e);
             return Collections.emptyList();
         }
 
@@ -198,132 +854,6 @@
     }
 
     /**
-     * Grant default permissions to currently active LUI app
-     * @param packageName The package name for the LUI app
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when grant completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void grantDefaultPermissionsToLuiApp(
-            @NonNull String packageName, @NonNull UserHandle user,
-            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.grantDefaultPermissionsToActiveLuiApp(
-                    packageName, user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Revoke default permissions to currently active LUI app
-     * @param packageNames The package names for the LUI apps
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when grant completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void revokeDefaultPermissionsFromLuiApps(
-            @NonNull String[] packageNames, @NonNull UserHandle user,
-            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.revokeDefaultPermissionsFromLuiApps(
-                    packageNames, user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Grant default permissions to currently active Ims services
-     * @param packageNames The package names for the Ims services
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when grant completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void grantDefaultPermissionsToEnabledImsServices(
-            @NonNull String[] packageNames, @NonNull UserHandle user,
-            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.grantDefaultPermissionsToEnabledImsServices(
-                    packageNames, user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Grant default permissions to currently enabled telephony data services
-     * @param packageNames The package name for the services
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when grant completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void grantDefaultPermissionsToEnabledTelephonyDataServices(
-            @NonNull String[] packageNames, @NonNull UserHandle user,
-            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices(
-                    packageNames, user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Revoke default permissions to currently active telephony data services
-     * @param packageNames The package name for the services
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when revoke completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-            @NonNull String[] packageNames, @NonNull UserHandle user,
-            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-                    packageNames, user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Grant default permissions to currently enabled carrier apps
-     * @param packageNames Package names of the apps to be granted permissions
-     * @param user The user handle
-     * @param executor The executor for the callback
-     * @param callback The callback provided by caller to be notified when grant completes
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
-    public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames,
-            @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Boolean> callback) {
-        try {
-            mPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
-                    user.getIdentifier());
-            executor.execute(() -> callback.accept(true));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Gets the list of packages that have permissions that specified
      * {@code requestDontAutoRevokePermissions=true} in their
      * {@code application} manifest declaration.
@@ -530,12 +1060,8 @@
     @SystemApi
     public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
             @Nullable String callingFeatureId, int pid, int uid) {
-        try {
-            return mPermissionManager.checkDeviceIdentifierAccess(packageName, message,
-                    callingFeatureId, pid, uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message,
+                callingFeatureId, pid, uid);
     }
 
     /* @hide */
@@ -547,10 +1073,11 @@
             // permission this is.
             final int appId = UserHandle.getAppId(uid);
             if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
-                Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
+                Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " holds "
+                        + permission);
                 return PackageManager.PERMISSION_GRANTED;
             }
-            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
+            Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
                     + permission);
             return PackageManager.PERMISSION_DENIED;
         }
@@ -730,4 +1257,35 @@
         sPackageNamePermissionCache.disableLocal();
     }
 
+    private final class OnPermissionsChangeListenerDelegate
+            extends IOnPermissionsChangeListener.Stub implements Handler.Callback{
+        private static final int MSG_PERMISSIONS_CHANGED = 1;
+
+        private final PackageManager.OnPermissionsChangedListener mListener;
+        private final Handler mHandler;
+
+        public OnPermissionsChangeListenerDelegate(
+                PackageManager.OnPermissionsChangedListener listener, Looper looper) {
+            mListener = listener;
+            mHandler = new Handler(looper, this);
+        }
+
+        @Override
+        public void onPermissionsChanged(int uid) {
+            mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+        }
+
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_PERMISSIONS_CHANGED: {
+                    final int uid = msg.arg1;
+                    mListener.onPermissionsChanged(uid);
+                    return true;
+                }
+                default:
+                    return false;
+            }
+        }
+    }
 }
diff --git a/core/java/android/permissionpresenterservice/OWNERS b/core/java/android/permissionpresenterservice/OWNERS
new file mode 100644
index 0000000..d09f351
--- /dev/null
+++ b/core/java/android/permissionpresenterservice/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137825
+
+moltmann@google.com
+evanseverson@google.com
+ntmyren@google.com
+zhanghai@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/print/OWNERS b/core/java/android/print/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/print/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/print/pdf/OWNERS b/core/java/android/print/pdf/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/print/pdf/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/printservice/OWNERS b/core/java/android/printservice/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/printservice/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/printservice/recommendation/OWNERS b/core/java/android/printservice/recommendation/OWNERS
new file mode 100644
index 0000000..72f0983
--- /dev/null
+++ b/core/java/android/printservice/recommendation/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 47273
+
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 105ffaa..d1aa489 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,7 +17,14 @@
 
 package android.provider;
 
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
 import android.annotation.LongDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -30,6 +37,9 @@
 import android.location.CountryDetector;
 import android.net.Uri;
 import android.os.Build;
+import android.os.OutcomeReceiver;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelableException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.ContactsContract.CommonDataKinds.Callable;
@@ -44,9 +54,15 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
 
 /**
  * The CallLog provider contains information about placed and received calls.
@@ -63,6 +79,12 @@
     public static final Uri CONTENT_URI =
         Uri.parse("content://" + AUTHORITY);
 
+    /** @hide */
+    public static final String CALL_COMPOSER_SEGMENT = "call_composer";
+
+    /** @hide */
+    public static final Uri CALL_COMPOSER_PICTURE_URI =
+            CONTENT_URI.buildUpon().appendPath(CALL_COMPOSER_SEGMENT).build();
 
     /**
      * The "shadow" provider stores calllog when the real calllog provider is encrypted.  The
@@ -75,6 +97,172 @@
     public static final String SHADOW_AUTHORITY = "call_log_shadow";
 
     /**
+     * Describes an error encountered while storing a call composer picture in the call log.
+     * @hide
+     */
+    @SystemApi
+    public static class CallComposerLoggingException extends Throwable {
+        /**
+         * Indicates an unknown error.
+         */
+        public static final int ERROR_UNKNOWN = 0;
+
+        /**
+         * Indicates that the process hosting the call log died or otherwise encountered an
+         * unrecoverable error while storing the picture.
+         *
+         * The caller should retry if this error is encountered.
+         */
+        public static final int ERROR_REMOTE_END_CLOSED = 1;
+
+        /**
+         * Indicates that the device has insufficient space to store this picture.
+         *
+         * The caller should not retry if this error is encountered.
+         */
+        public static final int ERROR_STORAGE_FULL = 2;
+
+        /**
+         * Indicates that the {@link InputStream} passed to {@link #storeCallComposerPictureAsUser}
+         * was closed.
+         *
+         * The caller should retry if this error is encountered, and be sure to not close the stream
+         * before the callback is called this time.
+         */
+        public static final int ERROR_INPUT_CLOSED = 3;
+
+        /** @hide */
+        @IntDef(prefix = {"ERROR_"}, value = {
+                ERROR_UNKNOWN,
+                ERROR_REMOTE_END_CLOSED,
+                ERROR_STORAGE_FULL,
+                ERROR_INPUT_CLOSED,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface CallComposerLoggingError { }
+
+        private final int mErrorCode;
+
+        /** @hide */
+        public CallComposerLoggingException(@CallComposerLoggingError int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        /**
+         * @return The error code for this exception.
+         */
+        public @CallComposerLoggingError int getErrorCode() {
+            return mErrorCode;
+        }
+    }
+
+    /**
+     * Supplies a call composer picture to the call log for persistent storage.
+     *
+     * This method is used by Telephony to store pictures selected by the user or sent from the
+     * remote party as part of a voice call with call composer. The {@link Uri} supplied in the
+     * callback can be used to retrieve the image via {@link ContentResolver#openFile} or stored in
+     * the {@link Calls} table in the TODO: link column name.
+     *
+     * The caller is responsible for closing the {@link InputStream} after the callback indicating
+     * success or failure.
+     *
+     * @param context An instance of {@link Context}.
+     * @param user The user for whom the picture is stored. If {@code null}, the picture will be
+     *             stored for all users.
+     * @param input An input stream from which the picture to store should be read. The input data
+     *              must be decodeable as either a JPEG, PNG, or GIF image.
+     * @param executor The {@link Executor} on which to perform the file transfer operation and
+     *                 call the supplied callback.
+     * @param callback Callback that's called after the picture is successfully stored or when an
+     *                 error occurs.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.WRITE_CALL_LOG)
+    public static void storeCallComposerPictureAsUser(@NonNull Context context,
+            @Nullable UserHandle user,
+            @NonNull InputStream input,
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OutcomeReceiver<Uri, CallComposerLoggingException> callback) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(input);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        executor.execute(() -> {
+            Uri pictureFileUri;
+            Uri pictureInsertionUri = context.getSystemService(UserManager.class)
+                    .isUserUnlocked() ? CALL_COMPOSER_PICTURE_URI
+                    : CALL_COMPOSER_PICTURE_URI.buildUpon().authority(SHADOW_AUTHORITY).build();
+            try {
+                // ContentResolver#insert says that the second argument is nullable. It is in fact
+                // not nullable.
+                ContentValues cv = new ContentValues();
+                pictureFileUri = context.getContentResolver().insert(pictureInsertionUri, cv);
+            } catch (ParcelableException e) {
+                // Most likely an IOException. We don't have a good way of distinguishing them so
+                // just return an unknown error.
+                sendCallComposerError(callback, CallComposerLoggingException.ERROR_UNKNOWN);
+                return;
+            }
+            if (pictureFileUri == null) {
+                // If the call log provider returns null, it means that there's not enough space
+                // left to store the maximum-sized call composer image.
+                sendCallComposerError(callback, CallComposerLoggingException.ERROR_STORAGE_FULL);
+                return;
+            }
+
+            boolean wroteSuccessfully = false;
+            try (ParcelFileDescriptor pfd =
+                         context.getContentResolver().openFileDescriptor(pictureFileUri, "w")) {
+                FileOutputStream output = new FileOutputStream(pfd.getFileDescriptor());
+                byte[] buffer = new byte[1024];
+                int bytesRead;
+                while (true) {
+                    try {
+                        bytesRead = input.read(buffer);
+                    } catch (IOException e) {
+                        sendCallComposerError(callback,
+                                CallComposerLoggingException.ERROR_INPUT_CLOSED);
+                        throw e;
+                    }
+                    if (bytesRead < 0) {
+                        break;
+                    }
+                    try {
+                        output.write(buffer, 0, bytesRead);
+                    } catch (IOException e) {
+                        sendCallComposerError(callback,
+                                CallComposerLoggingException.ERROR_REMOTE_END_CLOSED);
+                        throw e;
+                    }
+                }
+                wroteSuccessfully = true;
+            } catch (FileNotFoundException e) {
+                callback.onError(new CallComposerLoggingException(
+                        CallComposerLoggingException.ERROR_UNKNOWN));
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "IOException while writing call composer pic to call log: "
+                        + e);
+            }
+
+            if (wroteSuccessfully) {
+                callback.onResult(pictureFileUri);
+            } else {
+                // Clean up our mess if we didn't successfully write the file.
+                context.getContentResolver().delete(pictureFileUri, null);
+            }
+        });
+    }
+
+    // Only call on the correct executor.
+    private static void sendCallComposerError(OutcomeReceiver<?, CallComposerLoggingException> cb,
+            int error) {
+        cb.onError(new CallComposerLoggingException(error));
+    }
+
+    /**
      * Contains the recent calls.
      */
     public static class Calls implements BaseColumns {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index da06e82..376d942 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -4313,13 +4313,23 @@
          * <P>
          * Type: INTEGER (A bitmask of CARRIER_PRESENCE_* fields)
          * </P>
+         *
+         * @deprecated The contacts database will only show presence
+         * information on devices where
+         * {@link android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is true,
+         * otherwise use {@link android.telephony.ims.RcsUceAdapter}.
          */
+        @Deprecated
         public static final String CARRIER_PRESENCE = "carrier_presence";
 
         /**
          * Indicates that the entry is Video Telephony (VT) capable on the
          * current carrier. An allowed bitmask of {@link #CARRIER_PRESENCE}.
+         *
+         * @deprecated Same as {@link DataColumns#CARRIER_PRESENCE}.
+         *
          */
+        @Deprecated
         public static final int CARRIER_PRESENCE_VT_CAPABLE = 0x01;
 
         /**
@@ -8368,10 +8378,10 @@
         public static final int UNKNOWN_EF_TYPE = 0;
         /** EF type identifier for the ADN partition. */
         public static final int ADN_EF_TYPE = 1;
-        /** EF type identifier for the SDN partition. */
-        public static final int SDN_EF_TYPE = 2;
         /** EF type identifier for the FDN partition. */
-        public static final int FDN_EF_TYPE = 3;
+        public static final int FDN_EF_TYPE = 2;
+        /** EF type identifier for the SDN partition. */
+        public static final int SDN_EF_TYPE = 3;
 
         /**
          * The account_name of this SIM account. See {@link RawContacts#ACCOUNT_NAME}.
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/OWNERS b/core/java/android/provider/OWNERS
index 97e0156..b02102b 100644
--- a/core/java/android/provider/OWNERS
+++ b/core/java/android/provider/OWNERS
@@ -1,5 +1,17 @@
-per-file DeviceConfig.java = svetoslavganov@google.com
-per-file DeviceConfig.java = hackbod@google.com
-per-file DeviceConfig.java = schfan@google.com
+per-file *BlockedNumber* = file:/telephony/OWNERS
+per-file *Telephony* = file:/telephony/OWNERS
 
+per-file *CallLog* = file:platform/packages/providers/ContactsProvider:/OWNERS
+per-file *Contacts* = file:platform/packages/providers/ContactsProvider:/OWNERS
+per-file *Voicemail* = file:platform/packages/providers/ContactsProvider:/OWNERS
 
+per-file *Calendar* = file:platform/packages/providers/CalendarProvider:/OWNERS
+
+per-file *Downloads* = file:platform/packages/providers/DownloadProvider:/OWNERS
+
+per-file *DeviceConfig* = file:/packages/SettingsProvider/OWNERS
+
+per-file *Documents* = file:/core/java/android/os/storage/OWNERS
+per-file *Documents* = file:platform/packages/apps/DocumentsUI:/OWNERS
+
+per-file *Slices* = file:/core/java/android/app/slice/OWNERS
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 12791bc..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>
@@ -3060,6 +3060,7 @@
         // com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSystemSettingsLocked.
 
         private static final float DEFAULT_FONT_SCALE = 1.0f;
+        private static final int DEFAULT_FONT_WEIGHT = 0;
 
         /**
          * The content:// style URL for this table
@@ -3581,9 +3582,7 @@
                 outConfig.fontScale = DEFAULT_FONT_SCALE;
             }
             outConfig.fontWeightAdjustment = Settings.Secure.getIntForUser(
-                    cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT,
-                    Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED,
-                    userHandle);
+                    cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT, DEFAULT_FONT_WEIGHT, userHandle);
 
             final String localeValue =
                     Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle);
@@ -7761,6 +7760,32 @@
                 "minimal_post_processing_allowed";
 
         /**
+         * No mode switching will happen.
+         *
+         * @see #MATCH_CONTENT_FRAME_RATE
+         * @hide
+         */
+        public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0;
+
+        /**
+         * Allow only refresh rate switching between modes in the same configuration group.
+         * This way only switches without visual interruptions for the user will be allowed.
+         *
+         * @see #MATCH_CONTENT_FRAME_RATE
+         * @hide
+         */
+        public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1;
+
+        /**
+         * Allow refresh rate switching between all refresh rates even if the switch will have
+         * visual interruptions for the user.
+         *
+         * @see #MATCH_CONTENT_FRAME_RATE
+         * @hide
+         */
+        public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2;
+
+        /**
          * User's preference for refresh rate switching.
          *
          * <p>Values:
@@ -7770,6 +7795,9 @@
          *     for the user.
          *
          * @see android.view.Surface#setFrameRate
+         * @see #MATCH_CONTENT_FRAMERATE_NEVER
+         * @see #MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY
+         * @see #MATCH_CONTENT_FRAMERATE_ALWAYS
          * @hide
          */
         public static final String MATCH_CONTENT_FRAME_RATE =
@@ -14484,10 +14512,11 @@
         public static final String SHOW_PEOPLE_SPACE = "show_people_space";
 
         /**
-         * Which types of conversations to show in People Space.
+         * Which types of conversation(s) to show in People Space.
          * Values are:
-         * 0: All conversations (default)
+         * 0: Single user-selected conversation (default)
          * 1: Priority conversations only
+         * 2: All conversations
          * @hide
          */
         public static final String PEOPLE_SPACE_CONVERSATION_TYPE =
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 83cab0a..d4c86e8 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5280,5 +5280,13 @@
          * @hide
          */
         public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types";
+
+        /**
+         * TelephonyProvider column name for RCS configuration.
+         * <p>TYPE: BLOB
+         *
+         * @hide
+         */
+        public static final String COLUMN_RCS_CONFIG = "rcs_config";
     }
 }
diff --git a/core/java/android/se/OWNERS b/core/java/android/se/OWNERS
new file mode 100644
index 0000000..f1539dc
--- /dev/null
+++ b/core/java/android/se/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 456592
+
+cbrubaker@google.com
+vishwath@google.com
diff --git a/core/java/android/se/omapi/OWNERS b/core/java/android/se/omapi/OWNERS
new file mode 100644
index 0000000..f1539dc
--- /dev/null
+++ b/core/java/android/se/omapi/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 456592
+
+cbrubaker@google.com
+vishwath@google.com
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index 7120376..7140ff1 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -1,4 +1,11 @@
+# Bug component: 36824
+
+cbrubaker@google.com
+vishwath@google.com
+
 per-file NetworkSecurityPolicy.java = cbrubaker@google.com
 per-file NetworkSecurityPolicy.java = klyubin@google.com
 per-file FrameworkNetworkSecurityPolicy.java = cbrubaker@google.com
 per-file FrameworkNetworkSecurityPolicy.java = klyubin@google.com
+per-file Confirmation*.java = jdanis@google.com
+per-file Confirmation*.java = swillden@google.com
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 6ef9e7e..017f405 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -16,18 +16,18 @@
 
 package android.security.keymaster;
 
-import android.hardware.keymint.Algorithm;
-import android.hardware.keymint.BlockMode;
-import android.hardware.keymint.Digest;
-import android.hardware.keymint.ErrorCode;
-import android.hardware.keymint.HardwareAuthenticatorType;
-import android.hardware.keymint.KeyFormat;
-import android.hardware.keymint.KeyOrigin;
-import android.hardware.keymint.KeyPurpose;
-import android.hardware.keymint.PaddingMode;
-import android.hardware.keymint.SecurityLevel;
-import android.hardware.keymint.Tag;
-import android.hardware.keymint.TagType;
+import android.hardware.security.keymint.Algorithm;
+import android.hardware.security.keymint.BlockMode;
+import android.hardware.security.keymint.Digest;
+import android.hardware.security.keymint.ErrorCode;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.hardware.security.keymint.KeyFormat;
+import android.hardware.security.keymint.KeyOrigin;
+import android.hardware.security.keymint.KeyPurpose;
+import android.hardware.security.keymint.PaddingMode;
+import android.hardware.security.keymint.SecurityLevel;
+import android.hardware.security.keymint.Tag;
+import android.hardware.security.keymint.TagType;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/core/java/android/security/keymaster/OWNERS b/core/java/android/security/keymaster/OWNERS
new file mode 100644
index 0000000..65129a4
--- /dev/null
+++ b/core/java/android/security/keymaster/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 189335
+
+swillden@google.com
+jdanis@google.com
+jbires@google.com
diff --git a/core/java/android/security/keystore/OWNERS b/core/java/android/security/keystore/OWNERS
index bb487fb..65129a4 100644
--- a/core/java/android/security/keystore/OWNERS
+++ b/core/java/android/security/keystore/OWNERS
@@ -1,4 +1,5 @@
-aseemk@google.com
-bozhu@google.com
-dementyev@google.com
-robertberry@google.com
+# Bug component: 189335
+
+swillden@google.com
+jdanis@google.com
+jbires@google.com
diff --git a/core/java/android/security/keystore/recovery/OWNERS b/core/java/android/security/keystore/recovery/OWNERS
new file mode 100644
index 0000000..65129a4
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 189335
+
+swillden@google.com
+jdanis@google.com
+jbires@google.com
diff --git a/core/java/android/security/net/OWNERS b/core/java/android/security/net/OWNERS
new file mode 100644
index 0000000..d828164
--- /dev/null
+++ b/core/java/android/security/net/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 36824
+
+cbrubaker@google.com
+brambonne@google.com
diff --git a/core/java/android/security/net/config/OWNERS b/core/java/android/security/net/config/OWNERS
index 5350373..85ce3c6 100644
--- a/core/java/android/security/net/config/OWNERS
+++ b/core/java/android/security/net/config/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 36824
 set noparent
+
 cbrubaker@google.com
-klyubin@google.com
+brambonne@google.com
diff --git a/core/java/android/service/appprediction/OWNERS b/core/java/android/service/appprediction/OWNERS
new file mode 100644
index 0000000..fe012da
--- /dev/null
+++ b/core/java/android/service/appprediction/OWNERS
@@ -0,0 +1,2 @@
+adamcohen@google.com
+sunnygoyal@google.com
diff --git a/core/java/android/service/attention/OWNERS b/core/java/android/service/attention/OWNERS
new file mode 100644
index 0000000..dd579b6
--- /dev/null
+++ b/core/java/android/service/attention/OWNERS
@@ -0,0 +1 @@
+asalo@google.com
diff --git a/core/java/android/service/attestation/OWNERS b/core/java/android/service/attestation/OWNERS
new file mode 100644
index 0000000..b9e7b99
--- /dev/null
+++ b/core/java/android/service/attestation/OWNERS
@@ -0,0 +1,2 @@
+chaviw@google.com
+ogunwale@google.com
diff --git a/core/java/android/service/autofill/OWNERS b/core/java/android/service/autofill/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/service/autofill/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/autofill/augmented/OWNERS b/core/java/android/service/autofill/augmented/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/carrier/OWNERS b/core/java/android/service/carrier/OWNERS
new file mode 100644
index 0000000..d768ef4
--- /dev/null
+++ b/core/java/android/service/carrier/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+fionaxu@google.com
diff --git a/core/java/android/service/chooser/OWNERS b/core/java/android/service/chooser/OWNERS
new file mode 100644
index 0000000..a5acba5
--- /dev/null
+++ b/core/java/android/service/chooser/OWNERS
@@ -0,0 +1,4 @@
+asc@google.com
+mpietal@google.com
+dsandler@android.com
+dsandler@google.com
diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS
new file mode 100644
index 0000000..6337327
--- /dev/null
+++ b/core/java/android/service/contentcapture/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 544200
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/service/contentsuggestions/OWNERS
@@ -0,0 +1,7 @@
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/dreams/OWNERS b/core/java/android/service/dreams/OWNERS
index 708ab4c..f831805 100644
--- a/core/java/android/service/dreams/OWNERS
+++ b/core/java/android/service/dreams/OWNERS
@@ -1,4 +1,3 @@
-dsandler@android.com
-michaelwr@google.com
-roosa@google.com
-galinap@google.com
+# Bug component: 78010
+
+dsandler@google.com
diff --git a/core/java/android/service/gatekeeper/OWNERS b/core/java/android/service/gatekeeper/OWNERS
new file mode 100644
index 0000000..2ca52cd
--- /dev/null
+++ b/core/java/android/service/gatekeeper/OWNERS
@@ -0,0 +1,3 @@
+swillden@google.com
+jdanis@google.com
+jbires@google.com
diff --git a/core/java/android/service/media/OWNERS b/core/java/android/service/media/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/core/java/android/service/media/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
+hdmoon@google.com
+insun@google.com
+jaewan@google.com
+jinpark@google.com
+klhyun@google.com
+gyumin@google.com
diff --git a/core/java/android/service/notification/OWNERS b/core/java/android/service/notification/OWNERS
index 2e94be5..debb493 100644
--- a/core/java/android/service/notification/OWNERS
+++ b/core/java/android/service/notification/OWNERS
@@ -1,4 +1,6 @@
+# Bug component: 34005
+
 juliacr@google.com
-beverlyt@google.com
+pixel@google.com
 dsandler@android.com
-pixel@google.com
\ No newline at end of file
+dsandler@google.com
diff --git a/core/java/android/service/quicksettings/OWNERS b/core/java/android/service/quicksettings/OWNERS
new file mode 100644
index 0000000..12eb7c7
--- /dev/null
+++ b/core/java/android/service/quicksettings/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 78010
+
+kozynski@google.com
+pixel@google.com
+dsandler@android.com
+dsandler@google.com
diff --git a/core/java/android/service/resolver/OWNERS b/core/java/android/service/resolver/OWNERS
new file mode 100644
index 0000000..10150c37
--- /dev/null
+++ b/core/java/android/service/resolver/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 78010
+
+asc@google.com
+mpietal@google.com
+dsandler@android.com
+dsandler@google.com
diff --git a/core/java/android/service/restrictions/OWNERS b/core/java/android/service/restrictions/OWNERS
new file mode 100644
index 0000000..eaba2e9
--- /dev/null
+++ b/core/java/android/service/restrictions/OWNERS
@@ -0,0 +1 @@
+yamasani@google.com
diff --git a/core/java/android/service/search/ISearchUiService.aidl b/core/java/android/service/search/ISearchUiService.aidl
new file mode 100644
index 0000000..aae66ca
--- /dev/null
+++ b/core/java/android/service/search/ISearchUiService.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.search;
+
+import android.app.search.Query;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.app.search.SearchSessionId;
+import android.app.search.SearchContext;
+import android.app.search.ISearchCallback;
+import android.content.pm.ParceledListSlice;
+
+/**
+ * Interface from the system to a search service.
+ *
+ * @hide
+ */
+oneway interface ISearchUiService {
+
+    void onCreateSearchSession(in SearchContext context, in SearchSessionId sessionId);
+
+    void onQuery(in SearchSessionId sessionId, in Query input, in ISearchCallback callback);
+
+    void onNotifyEvent(in SearchSessionId sessionId, in Query input, in SearchTargetEvent event);
+
+    void onDestroy(in SearchSessionId sessionId);
+}
diff --git a/core/java/android/service/search/SearchUiService.java b/core/java/android/service/search/SearchUiService.java
new file mode 100644
index 0000000..d0e4195
--- /dev/null
+++ b/core/java/android/service/search/SearchUiService.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.search;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.app.search.ISearchCallback;
+import android.app.search.Query;
+import android.app.search.SearchContext;
+import android.app.search.SearchSessionId;
+import android.app.search.SearchTarget;
+import android.app.search.SearchTargetEvent;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.service.search.ISearchUiService.Stub;
+import android.util.Slog;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * A service used to share the lifecycle of search UI (open, close, interaction)
+ * and also to return search result on a query.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class SearchUiService extends Service {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "SearchUiService";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     *
+     * <p>The service must also require the {@link android.permission#MANAGE_SEARCH_UI}
+     * permission.
+     *
+     * @hide
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.search.SearchUiService";
+
+    private Handler mHandler;
+
+    private final android.service.search.ISearchUiService mInterface = new Stub() {
+
+        @Override
+        public void onCreateSearchSession(SearchContext context, SearchSessionId sessionId) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::onCreateSearchSession,
+                            SearchUiService.this, context, sessionId));
+        }
+
+        @Override
+        public void onQuery(SearchSessionId sessionId, Query input,
+                ISearchCallback callback) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::onQuery,
+                            SearchUiService.this, sessionId, input,
+                            new CallbackWrapper(callback, null)));
+        }
+
+        @Override
+        public void onNotifyEvent(SearchSessionId sessionId, Query query, SearchTargetEvent event) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::onNotifyEvent,
+                            SearchUiService.this, sessionId, query, event));
+        }
+
+        @Override
+        public void onDestroy(SearchSessionId sessionId) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::doDestroy,
+                            SearchUiService.this, sessionId));
+        }
+    };
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    @Override
+    @NonNull
+    public final IBinder onBind(@NonNull Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Slog.w(TAG, "Tried to bind to wrong intent (should be "
+                + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    /**
+     * Creates a new search session.
+     */
+    public void onCreateSearchSession(@NonNull SearchContext context,
+            @NonNull SearchSessionId sessionId) {}
+
+    /**
+     * Called by the client to request search results using a query string.
+     */
+    @MainThread
+    public abstract void onQuery(@NonNull SearchSessionId sessionId,
+            @NonNull Query query,
+            @NonNull Consumer<List<SearchTarget>> callback);
+
+    /**
+     * Called by a client to indicate an interaction (tap, long press, drag, etc) on target(s).
+     */
+    @MainThread
+    public abstract void onNotifyEvent(@NonNull SearchSessionId sessionId,
+            @NonNull Query query,
+            @NonNull SearchTargetEvent event);
+
+    private void doDestroy(@NonNull SearchSessionId sessionId) {
+        super.onDestroy();
+        onDestroy(sessionId);
+    }
+
+    /**
+     * Destroys a search session.
+     */
+    @MainThread
+    public abstract void onDestroy(@NonNull SearchSessionId sessionId);
+
+    private static final class CallbackWrapper implements Consumer<List<SearchTarget>>,
+            IBinder.DeathRecipient {
+
+        private ISearchCallback mCallback;
+        private final Consumer<CallbackWrapper> mOnBinderDied;
+
+        CallbackWrapper(ISearchCallback callback,
+                @Nullable Consumer<CallbackWrapper> onBinderDied) {
+            mCallback = callback;
+            mOnBinderDied = onBinderDied;
+            try {
+                mCallback.asBinder().linkToDeath(this, 0);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to link to death: " + e);
+            }
+        }
+
+        @Override
+        public void accept(List<SearchTarget> searchTargets) {
+            try {
+                if (mCallback != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "CallbackWrapper.accept searchTargets=" + searchTargets);
+                    }
+                    mCallback.onResult(new ParceledListSlice(searchTargets));
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error sending result:" + e);
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            mCallback.asBinder().unlinkToDeath(this, 0);
+            mCallback = null;
+            if (mOnBinderDied != null) {
+                mOnBinderDied.accept(this);
+            }
+        }
+    }
+}
diff --git a/core/java/android/service/storage/ExternalStorageService.java b/core/java/android/service/storage/ExternalStorageService.java
index 3b4d84a..0123c36 100644
--- a/core/java/android/service/storage/ExternalStorageService.java
+++ b/core/java/android/service/storage/ExternalStorageService.java
@@ -16,6 +16,7 @@
 
 package android.service.storage;
 
+import android.annotation.BytesLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
@@ -29,6 +30,7 @@
 import android.os.ParcelableException;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
 
 import com.android.internal.os.BackgroundThread;
@@ -37,6 +39,7 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.UUID;
 
 /**
  * A service to handle filesystem I/O from other apps.
@@ -147,6 +150,18 @@
      */
     public abstract void onVolumeStateChanged(@NonNull StorageVolume vol) throws IOException;
 
+    /**
+     * Called when any cache held by the ExternalStorageService needs to be freed.
+     *
+     * <p> Blocks until the service frees the cache or fails in doing so.
+     *
+     * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+     * @param bytes number of bytes which need to be freed
+     */
+    public void onFreeCacheRequested(@NonNull UUID volumeUuid, @BytesLong long bytes) {
+        throw new UnsupportedOperationException("onFreeCacheRequested not implemented");
+    }
+
     @Override
     @NonNull
     public final IBinder onBind(@NonNull Intent intent) {
@@ -183,6 +198,19 @@
         }
 
         @Override
+        public void freeCache(String sessionId, String volumeUuid, long bytes,
+                RemoteCallback callback) {
+            mHandler.post(() -> {
+                try {
+                    onFreeCacheRequested(StorageManager.convert(volumeUuid), bytes);
+                    sendResult(sessionId, null /* throwable */, callback);
+                } catch (Throwable t) {
+                    sendResult(sessionId, t, callback);
+                }
+            });
+        }
+
+        @Override
         public void endSession(String sessionId, RemoteCallback callback) throws RemoteException {
             mHandler.post(() -> {
                 try {
diff --git a/core/java/android/service/storage/IExternalStorageService.aidl b/core/java/android/service/storage/IExternalStorageService.aidl
index 30fefd3..d06671b 100644
--- a/core/java/android/service/storage/IExternalStorageService.aidl
+++ b/core/java/android/service/storage/IExternalStorageService.aidl
@@ -30,4 +30,6 @@
     void endSession(@utf8InCpp String sessionId, in RemoteCallback callback);
     void notifyVolumeStateChanged(@utf8InCpp String sessionId, in StorageVolume vol,
         in RemoteCallback callback);
+    void freeCache(@utf8InCpp String sessionId, in String volumeUuid, long bytes,
+        in RemoteCallback callback);
 }
\ No newline at end of file
diff --git a/core/java/android/service/storage/OWNERS b/core/java/android/service/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/core/java/android/service/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS
new file mode 100644
index 0000000..a535f52
--- /dev/null
+++ b/core/java/android/service/textclassifier/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 709498
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/textservice/OWNERS b/core/java/android/service/textservice/OWNERS
new file mode 100644
index 0000000..10b8b76
--- /dev/null
+++ b/core/java/android/service/textservice/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include ../../inputmethodservice/OWNERS
\ No newline at end of file
diff --git a/core/java/android/service/timezone/ITimeZoneProvider.aidl b/core/java/android/service/timezone/ITimeZoneProvider.aidl
new file mode 100644
index 0000000..62fa157
--- /dev/null
+++ b/core/java/android/service/timezone/ITimeZoneProvider.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import android.service.timezone.ITimeZoneProviderManager;
+
+/**
+ * @hide
+ */
+oneway interface ITimeZoneProvider {
+    void setTimeZoneProviderManager(in @nullable ITimeZoneProviderManager manager);
+    void startUpdates(in long initializationTimeoutMillis);
+    void stopUpdates();
+}
diff --git a/core/java/android/service/timezone/ITimeZoneProviderManager.aidl b/core/java/android/service/timezone/ITimeZoneProviderManager.aidl
new file mode 100644
index 0000000..bf4fe0a
--- /dev/null
+++ b/core/java/android/service/timezone/ITimeZoneProviderManager.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import android.service.timezone.TimeZoneProviderSuggestion;
+
+/**
+ * @hide
+ */
+oneway interface ITimeZoneProviderManager {
+    void onTimeZoneProviderSuggestion(in TimeZoneProviderSuggestion timeZoneProviderSuggestion);
+    void onTimeZoneProviderUncertain();
+    void onTimeZoneProviderPermanentFailure(in String failureReason);
+}
diff --git a/core/java/android/service/timezone/TimeZoneProviderService.java b/core/java/android/service/timezone/TimeZoneProviderService.java
new file mode 100644
index 0000000..9533a8f
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderService.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import android.annotation.DurationMillisLong;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.os.BackgroundThread;
+
+import java.util.Objects;
+
+/**
+ * A service to generate time zone callbacks to the platform. Developers must extend this class.
+ *
+ * <p>Provider implementations are started via a call to {@link #onStartUpdates(long)} and stopped
+ * via a call to {@link #onStopUpdates()}.
+ *
+ * <p>Once started, providers are expected to detect the time zone if possible, and report the
+ * result via {@link #reportSuggestion(TimeZoneProviderSuggestion)} or {@link
+ * #reportUncertain()}. Providers may also report that they have permanently failed
+ * by calling {@link #reportPermanentFailure(Throwable)}. See the javadocs for each
+ * method for details.
+ *
+ * <p>After starting, providers are expected to issue their first callback within the timeout
+ * duration specified in {@link #onStartUpdates(long)}, or they will be implicitly considered to be
+ * uncertain.
+ *
+ * <p>Once stopped or failed, providers are required to stop generating callbacks.
+ *
+ * <p>Provider discovery:
+ *
+ * <p>You must declare the service in your manifest file with the
+ * {@link android.Manifest.permission#INSTALL_LOCATION_TIME_ZONE_PROVIDER} permission,
+ * and include an intent filter with the necessary action indicating what type of provider it is.
+ *
+ * <p>Device configuration can influence how {@link TimeZoneProviderService}s are discovered.
+ * In one mode, there can be multiple {@link TimeZoneProviderService}s configured with the same
+ * action, and the one with the highest "serviceVersion" metadata will be used.
+ *
+ * <p>{@link TimeZoneProviderService}s may be deployed into processes that run once-per-user
+ * or once-per-device (i.e. they service multiple users). The "serviceIsMultiuser" metadata must
+ * be set accordingly.
+ *
+ * <p>Provider types:
+ *
+ * <p>Android currently supports up to two location-derived time zone providers. These are called
+ * the "primary" and "secondary" location time zone provider, configured using {@link
+ * #PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE} and {@link
+ * #SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE} respectively. The primary location time
+ * zone provider is started first and will be used until becomes uncertain or fails, at which point
+ * the secondary provider will be started.
+ *
+ * For example:
+ * <pre>
+ *     &lt;service android:name=".FooTimeZoneProviderService"
+ *             android:exported="true"
+ *             android:permission="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER"&gt;
+ *         &lt;intent-filter&gt;
+ *             &lt;action
+ *             android:name="android.service.timezone.SecondaryLocationTimeZoneProviderService"
+ *             /&gt;
+ *         &lt;/intent-filter&gt;
+ *         &lt;meta-data android:name="serviceVersion" android:value="1" /&gt;
+ *         &lt;meta-data android:name="serviceIsMultiuser" android:value="true" /&gt;
+ *     &lt;/service&gt;
+ * </pre>
+ *
+ *
+ * <p>Threading:
+ *
+ * <p>Calls to {@code report} methods can be made on on any thread and will be passed asynchronously
+ * to the system server. Calls to {@link #onStartUpdates(long)} and {@link #onStopUpdates()} will
+ * occur on a single thread.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class TimeZoneProviderService extends Service {
+
+    private static final String TAG = "TimeZoneProviderService";
+
+    private final Handler mHandler = BackgroundThread.getHandler();
+
+    /**
+     * The Intent action that the primary location-derived time zone provider service must respond
+     * to. Add it to the intent filter of the service in its manifest.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE =
+            "android.service.timezone.PrimaryLocationTimeZoneProviderService";
+
+    /**
+     * The Intent action that the secondary location-based time zone provider service must respond
+     * to. Add it to the intent filter of the service in its manifest.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE =
+            "android.service.timezone.SecondaryLocationTimeZoneProviderService";
+
+    /**
+     * The permission that a service must require to ensure that only Android system can bind to it.
+     * If this permission is not enforced in the AndroidManifest of the service, the system will
+     * skip that service.
+     */
+    public static final String BIND_PERMISSION =
+            "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
+
+    private final TimeZoneProviderServiceWrapper mWrapper = new TimeZoneProviderServiceWrapper();
+
+    /** Set by {@link #mHandler} thread. */
+    @Nullable
+    private ITimeZoneProviderManager mManager;
+
+    @Override
+    @NonNull
+    public final IBinder onBind(@NonNull Intent intent) {
+        return mWrapper;
+    }
+
+    /**
+     * Indicates a successful time zone detection. See {@link TimeZoneProviderSuggestion} for
+     * details.
+     */
+    public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion) {
+        Objects.requireNonNull(suggestion);
+
+        mHandler.post(() -> {
+            ITimeZoneProviderManager manager = mManager;
+            if (manager != null) {
+                try {
+                    manager.onTimeZoneProviderSuggestion(suggestion);
+                } catch (RemoteException | RuntimeException e) {
+                    Log.w(TAG, e);
+                }
+            }
+        });
+    }
+
+    /**
+     * Indicates the time zone is not known because of an expected runtime state or error, e.g. when
+     * the provider is unable to detect location, or there was a problem when resolving the location
+     * to a time zone.
+     */
+    public final void reportUncertain() {
+        mHandler.post(() -> {
+            ITimeZoneProviderManager manager = mManager;
+            if (manager != null) {
+                try {
+                    manager.onTimeZoneProviderUncertain();
+                } catch (RemoteException | RuntimeException e) {
+                    Log.w(TAG, e);
+                }
+            }
+        });
+    }
+
+    /**
+     * Indicates there was a permanent failure. This is not generally expected, and probably means a
+     * required backend service has been turned down, or the client is unreasonably old.
+     */
+    public final void reportPermanentFailure(@NonNull Throwable cause) {
+        Objects.requireNonNull(cause);
+
+        mHandler.post(() -> {
+            ITimeZoneProviderManager manager = mManager;
+            if (manager != null) {
+                try {
+                    manager.onTimeZoneProviderPermanentFailure(cause.getMessage());
+                } catch (RemoteException | RuntimeException e) {
+                    Log.w(TAG, e);
+                }
+            }
+        });
+    }
+
+    /**
+     * Starts the provider sending updates.
+     */
+    public abstract void onStartUpdates(@DurationMillisLong long initializationTimeoutMillis);
+
+    /**
+     * Stops the provider sending updates.
+     */
+    public abstract void onStopUpdates();
+
+    private class TimeZoneProviderServiceWrapper extends ITimeZoneProvider.Stub {
+
+        @Override
+        public void setTimeZoneProviderManager(ITimeZoneProviderManager manager) {
+            Objects.requireNonNull(manager);
+            mHandler.post(() -> TimeZoneProviderService.this.mManager = manager);
+        }
+
+        public void startUpdates(@DurationMillisLong long initializationTimeoutMillis) {
+            mHandler.post(() -> onStartUpdates(initializationTimeoutMillis));
+        }
+
+        public void stopUpdates() {
+            mHandler.post(TimeZoneProviderService.this::onStopUpdates);
+        }
+    }
+}
diff --git a/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl b/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl
new file mode 100644
index 0000000..d0cb73b
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+/**
+ * @hide
+ */
+parcelable TimeZoneProviderSuggestion;
diff --git a/core/java/android/service/timezone/TimeZoneProviderSuggestion.java b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
new file mode 100644
index 0000000..cf299a7
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A suggestion from a {@link TimeZoneProviderService} containing zero or more time zones.
+ *
+ * @hide
+ */
+@SystemApi
+public final class TimeZoneProviderSuggestion implements Parcelable {
+
+    @NonNull
+    private final List<String> mTimeZoneIds;
+
+    @ElapsedRealtimeLong
+    private final long mElapsedRealtimeMillis;
+
+    private TimeZoneProviderSuggestion(@NonNull List<String> timeZoneIds,
+            @ElapsedRealtimeLong long elapsedRealtimeMillis) {
+        mTimeZoneIds = immutableList(timeZoneIds);
+        mElapsedRealtimeMillis = elapsedRealtimeMillis;
+    }
+
+    /**
+     * Returns the time of the suggestion in elapsed real-time since system boot. Where possible,
+     * the time should be based on the time of the data used when determining time zone. For
+     * example, if it was based on a {@link android.location.Location} then it should be the time
+     * associated with that location.
+     *
+     * <p>This value is compared to {@link
+     * android.os.SystemClock#elapsedRealtime()}, to calculate the age of a fix and to compare
+     * {@link TimeZoneProviderSuggestion} instances.
+     *
+     * @return elapsed real-time of fix, in milliseconds
+     */
+    @ElapsedRealtimeLong
+    public long getElapsedRealtimeMillis() {
+        return mElapsedRealtimeMillis;
+    }
+
+    /**
+     * Returns the zero or more time zone IDs for this suggestion.
+     *
+     * <p>Time zone IDs are TZDB IDs like "America/Los_Angeles" that would be accepted by {@link
+     * java.util.TimeZone#getTimeZone(String)}.
+     *
+     * <p>Most often a suggestion will contain a single time zone ID but other possibilities are
+     * valid. A suggestion with zero time zone IDs means the provider is certain there are no time
+     * zones for the current location, e.g. for oceans, boundaries or disputed areas. A suggestion
+     * with multiple IDs can occur on boundaries or disputed areas. The ordering should be in order
+     * of likelihood if possible, but the time zone detection service may choose from any of the
+     * zones suggested if it has other supporting information available.
+     */
+    @NonNull
+    public List<String> getTimeZoneIds() {
+        return mTimeZoneIds;
+    }
+
+    @Override
+    public String toString() {
+        return "TimeZoneProviderSuggestion{"
+                + "mTimeZoneIds=" + mTimeZoneIds
+                + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+                + "(" + Duration.ofMillis(mElapsedRealtimeMillis) + ")"
+                + '}';
+    }
+
+    public static final @NonNull Creator<TimeZoneProviderSuggestion> CREATOR =
+            new Creator<TimeZoneProviderSuggestion>() {
+                @Override
+                public TimeZoneProviderSuggestion createFromParcel(Parcel in) {
+                    @SuppressWarnings("unchecked")
+                    ArrayList<String> timeZoneIds =
+                            (ArrayList<String>) in.readArrayList(null /* classLoader */);
+                    long elapsedRealtimeMillis = in.readLong();
+                    return new TimeZoneProviderSuggestion(timeZoneIds, elapsedRealtimeMillis);
+                }
+
+                @Override
+                public TimeZoneProviderSuggestion[] newArray(int size) {
+                    return new TimeZoneProviderSuggestion[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
+        parcel.writeList(mTimeZoneIds);
+        parcel.writeLong(mElapsedRealtimeMillis);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TimeZoneProviderSuggestion that = (TimeZoneProviderSuggestion) o;
+        return mElapsedRealtimeMillis == that.mElapsedRealtimeMillis
+                && mTimeZoneIds.equals(that.mTimeZoneIds);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mTimeZoneIds, mElapsedRealtimeMillis);
+    }
+
+    /** A builder for {@link TimeZoneProviderSuggestion}. */
+    public static final class Builder {
+
+        private @NonNull List<String> mTimeZoneIds = Collections.emptyList();
+        @ElapsedRealtimeLong
+        private long mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
+
+        /**
+         * Sets the time zone IDs of this suggestion.
+         */
+        @NonNull
+        public Builder setTimeZoneIds(@NonNull List<String> timeZoneIds) {
+            mTimeZoneIds = Objects.requireNonNull(timeZoneIds);
+            return this;
+        }
+
+        /**
+         * Sets the time of this suggestion, in elapsed real-time since system boot.
+         */
+        @NonNull
+        public Builder setElapsedRealtimeMillis(@ElapsedRealtimeLong long time) {
+            mElapsedRealtimeMillis = time;
+            return this;
+        }
+
+        /**
+         * Builds a {@link TimeZoneProviderSuggestion} instance.
+         */
+        @NonNull
+        public TimeZoneProviderSuggestion build() {
+            return new TimeZoneProviderSuggestion(mTimeZoneIds, mElapsedRealtimeMillis);
+        }
+    }
+
+    @NonNull
+    private static List<String> immutableList(@NonNull List<String> list) {
+        Objects.requireNonNull(list);
+        if (list.isEmpty()) {
+            return Collections.emptyList();
+        } else {
+            return Collections.unmodifiableList(new ArrayList<>(list));
+        }
+    }
+}
diff --git a/core/java/android/service/trust/OWNERS b/core/java/android/service/trust/OWNERS
new file mode 100644
index 0000000..affe471
--- /dev/null
+++ b/core/java/android/service/trust/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 36824
+
+cbrubaker@google.com
+vishwath@google.com
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
new file mode 100644
index 0000000..46b5ea0
--- /dev/null
+++ b/core/java/android/service/voice/OWNERS
@@ -0,0 +1,7 @@
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 0b6d371..c1b66c7 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1220,7 +1220,7 @@
      * your UI, which will eventually culminate in {@link #onShow}.  This is similar to calling
      * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
      * @param args Arbitrary arguments that will be propagated {@link #onShow}.
-     * @param flags Indicates additional optional behavior that should be performed.  May
+     * @param flags Indicates additional optional behavior that should be performed. May
      * be any combination of
      * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and
      * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT
@@ -1583,6 +1583,11 @@
      *
      * @param args The arguments that were supplied to
      * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+     * Some example keys include : "invocation_type", "invocation_phone_state",
+     * "invocation_time_ms", Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing
+     * in milliseconds of the KeyEvent that triggered Assistant and
+     * Intent.EXTRA_ASSIST_INPUT_DEVICE_ID (android.intent.extra.ASSIST_INPUT_DEVICE_ID)
+     *  referring to the device that sent the request.
      * @param showFlags The show flags originally provided to
      * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
      */
diff --git a/core/java/android/service/wallpaper/OWNERS b/core/java/android/service/wallpaper/OWNERS
new file mode 100644
index 0000000..756eef8
--- /dev/null
+++ b/core/java/android/service/wallpaper/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 78010
+
+dupin@google.com
+dsandler@android.com
+dsandler@google.com
diff --git a/core/java/android/service/watchdog/OWNERS b/core/java/android/service/watchdog/OWNERS
new file mode 100644
index 0000000..1c045e1
--- /dev/null
+++ b/core/java/android/service/watchdog/OWNERS
@@ -0,0 +1,3 @@
+narayan@google.com
+nandana@google.com
+olilan@google.com
diff --git a/core/java/android/telephony/OWNERS b/core/java/android/telephony/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/core/java/android/telephony/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index cc3284a..a9548b0 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -786,6 +786,21 @@
         }
     }
 
+    /**
+     * Notify that the data enabled has changed.
+     *
+     * @param enabled True if data is enabled, otherwise disabled.
+     * @param reason Reason for data enabled/disabled. See {@code REASON_*} in
+     * {@link TelephonyManager}.
+     */
+    public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) {
+        try {
+            sRegistry.notifyDataEnabled(enabled, reason);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
     public @NonNull Set<Integer> getEventsFromListener(@NonNull PhoneStateListener listener) {
 
         Set<Integer> eventList = new ArraySet<>();
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 1f15d46..4a48832 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -402,6 +402,10 @@
             }
         } else if (autoCorrection) {
             tp.setUnderlineText(mAutoCorrectionUnderlineColor, mAutoCorrectionUnderlineThickness);
+        } else if (misspelled) {
+            tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
+        } else if (grammarError) {
+            tp.setUnderlineText(mGrammarErrorUnderlineColor, mGrammarErrorUnderlineThickness);
         }
     }
 
@@ -425,6 +429,10 @@
             }
         } else if (autoCorrection) {
             return mAutoCorrectionUnderlineColor;
+        } else if (misspelled) {
+            return mMisspelledUnderlineColor;
+        } else if (grammarError) {
+            return mGrammarErrorUnderlineColor;
         }
         return 0;
     }
diff --git a/core/java/android/timezone/OWNERS b/core/java/android/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/transition/OWNERS b/core/java/android/transition/OWNERS
new file mode 100644
index 0000000..eb5a581
--- /dev/null
+++ b/core/java/android/transition/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 25700
+
+romainguy@google.com
+mount@google.com
+alanv@google.com
+adamp@google.com
diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java
index 1a397b3..4b511ac 100644
--- a/core/java/android/util/ExceptionUtils.java
+++ b/core/java/android/util/ExceptionUtils.java
@@ -98,4 +98,6 @@
         }
         return t;
     }
+
+
 }
\ No newline at end of file
diff --git a/core/java/android/util/TypedXmlPullParser.java b/core/java/android/util/TypedXmlPullParser.java
index b3b51b5..aa68bf4 100644
--- a/core/java/android/util/TypedXmlPullParser.java
+++ b/core/java/android/util/TypedXmlPullParser.java
@@ -30,67 +30,168 @@
  */
 public interface TypedXmlPullParser extends XmlPullParser {
     /**
-     * @return decoded strongly-typed {@link #getAttributeValue}
-     * @throws XmlPullParserException if the value is malformed or undefined
+     * @return index of requested attribute, otherwise {@code -1} if undefined
      */
-    @NonNull byte[] getAttributeBytesHex(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default int getAttributeIndex(@Nullable String namespace, @NonNull String name) {
+        final boolean namespaceNull = (namespace == null);
+        final int count = getAttributeCount();
+        for (int i = 0; i < count; i++) {
+            if ((namespaceNull || namespace.equals(getAttributeNamespace(i)))
+                    && name.equals(getAttributeName(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * @return index of requested attribute
+     * @throws XmlPullParserException if the value is undefined
+     */
+    default int getAttributeIndexOrThrow(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) {
+            throw new XmlPullParserException("Missing attribute " + name);
+        } else {
+            return index;
+        }
+    }
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    @NonNull byte[] getAttributeBytesHex(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    @NonNull byte[] getAttributeBytesBase64(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    int getAttributeInt(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    int getAttributeIntHex(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    long getAttributeLong(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    long getAttributeLongHex(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    float getAttributeFloat(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    double getAttributeDouble(int index) throws XmlPullParserException;
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed
+     */
+    boolean getAttributeBoolean(int index) throws XmlPullParserException;
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default @NonNull byte[] getAttributeBytesHex(@Nullable String namespace,
+            @NonNull String name) throws XmlPullParserException {
+        return getAttributeBytesHex(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    int getAttributeInt(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace,
+            @NonNull String name) throws XmlPullParserException {
+        return getAttributeBytesBase64(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    int getAttributeIntHex(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default int getAttributeInt(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeInt(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    long getAttributeLong(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default int getAttributeIntHex(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeIntHex(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    long getAttributeLongHex(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default long getAttributeLong(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeLong(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    float getAttributeFloat(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default long getAttributeLongHex(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeLongHex(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    double getAttributeDouble(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default float getAttributeFloat(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeFloat(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}
      * @throws XmlPullParserException if the value is malformed or undefined
      */
-    boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name)
-            throws XmlPullParserException;
+    default double getAttributeDouble(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeDouble(getAttributeIndexOrThrow(namespace, name));
+    }
+
+    /**
+     * @return decoded strongly-typed {@link #getAttributeValue}
+     * @throws XmlPullParserException if the value is malformed or undefined
+     */
+    default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name)
+            throws XmlPullParserException {
+        return getAttributeBoolean(getAttributeIndexOrThrow(namespace, name));
+    }
 
     /**
      * @return decoded strongly-typed {@link #getAttributeValue}, otherwise
@@ -98,8 +199,10 @@
      */
     default @Nullable byte[] getAttributeBytesHex(@Nullable String namespace,
             @NonNull String name, @Nullable byte[] defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeBytesHex(namespace, name);
+            return getAttributeBytesHex(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -111,8 +214,10 @@
      */
     default @Nullable byte[] getAttributeBytesBase64(@Nullable String namespace,
             @NonNull String name, @Nullable byte[] defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeBytesBase64(namespace, name);
+            return getAttributeBytesBase64(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -124,8 +229,10 @@
      */
     default int getAttributeInt(@Nullable String namespace, @NonNull String name,
             int defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeInt(namespace, name);
+            return getAttributeInt(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -137,8 +244,10 @@
      */
     default int getAttributeIntHex(@Nullable String namespace, @NonNull String name,
             int defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeIntHex(namespace, name);
+            return getAttributeIntHex(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -150,8 +259,10 @@
      */
     default long getAttributeLong(@Nullable String namespace, @NonNull String name,
             long defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeLong(namespace, name);
+            return getAttributeLong(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -163,8 +274,10 @@
      */
     default long getAttributeLongHex(@Nullable String namespace, @NonNull String name,
             long defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeLongHex(namespace, name);
+            return getAttributeLongHex(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -176,8 +289,10 @@
      */
     default float getAttributeFloat(@Nullable String namespace, @NonNull String name,
             float defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeFloat(namespace, name);
+            return getAttributeFloat(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -189,8 +304,10 @@
      */
     default double getAttributeDouble(@Nullable String namespace, @NonNull String name,
             double defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeDouble(namespace, name);
+            return getAttributeDouble(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
@@ -202,8 +319,10 @@
      */
     default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name,
             boolean defaultValue) {
+        final int index = getAttributeIndex(namespace, name);
+        if (index == -1) return defaultValue;
         try {
-            return getAttributeBoolean(namespace, name);
+            return getAttributeBoolean(index);
         } catch (Exception ignored) {
             return defaultValue;
         }
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
index c8193b3..38decf9 100644
--- a/core/java/android/util/Xml.java
+++ b/core/java/android/util/Xml.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.SystemProperties;
 import android.system.ErrnoException;
 import android.system.Os;
 
@@ -64,8 +65,11 @@
     /**
      * Feature flag: when set, {@link #resolveSerializer(OutputStream)} will
      * emit binary XML by default.
+     *
+     * @hide
      */
-    private static final boolean ENABLE_BINARY_DEFAULT = false;
+    public static final boolean ENABLE_BINARY_DEFAULT = SystemProperties
+            .getBoolean("persist.sys.binary_xml", true);
 
     /**
      * Parses the given xml string and fires events on the given SAX handler.
@@ -172,7 +176,7 @@
             if (!in.markSupported()) {
                 in = new BufferedInputStream(in);
             }
-            in.mark(4);
+            in.mark(8);
             in.read(magic);
             in.reset();
         }
diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java
index 6cc652d..2c27639 100644
--- a/core/java/android/util/imetracing/ImeTracingClientImpl.java
+++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java
@@ -25,6 +25,9 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.inputmethod.InputMethodManager;
 
+import com.android.internal.inputmethod.Completable;
+import com.android.internal.inputmethod.ResultCallbacks;
+
 import java.io.PrintWriter;
 
 /**
@@ -32,7 +35,9 @@
  */
 class ImeTracingClientImpl extends ImeTracing {
     ImeTracingClientImpl() throws ServiceNotFoundException, RemoteException {
-        sEnabled = mService.isImeTraceEnabled();
+        final Completable.Boolean value = Completable.createBoolean();
+        mService.isImeTraceEnabled(ResultCallbacks.of(value));
+        sEnabled = Completable.getResult(value);
     }
 
     @Override
diff --git a/core/java/android/util/proto/OWNERS b/core/java/android/util/proto/OWNERS
new file mode 100644
index 0000000..1eb6abf
--- /dev/null
+++ b/core/java/android/util/proto/OWNERS
@@ -0,0 +1,2 @@
+dplotnikov@google.com
+mwachens@google.com
diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java
index 33bc121..93b5fd4 100644
--- a/core/java/android/uwb/AngleMeasurement.java
+++ b/core/java/android/uwb/AngleMeasurement.java
@@ -17,6 +17,7 @@
 package android.uwb;
 
 import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -109,7 +110,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeDouble(mRadians);
         dest.writeDouble(mErrorRadians);
         dest.writeDouble(mConfidenceLevel);
@@ -146,6 +147,7 @@
          * @param radians angle in radians
          * @throws IllegalArgumentException if angle exceeds allowed limits of [-Math.PI, +Math.PI]
          */
+        @NonNull
         public Builder setRadians(double radians) {
             if (radians < -Math.PI || radians > Math.PI) {
                 throw new IllegalArgumentException("Invalid radians: " + radians);
@@ -160,6 +162,7 @@
          * @param errorRadians error of the angle in radians
          * @throws IllegalArgumentException if the error exceeds the allowed limits of [0, +Math.PI]
          */
+        @NonNull
         public Builder setErrorRadians(double errorRadians) {
             if (errorRadians < 0.0 || errorRadians > Math.PI) {
                 throw new IllegalArgumentException(
@@ -175,6 +178,7 @@
          * @param confidenceLevel level of confidence of the angle measurement
          * @throws IllegalArgumentException if the error exceeds the allowed limits of [0.0, 1.0]
          */
+        @NonNull
         public Builder setConfidenceLevel(double confidenceLevel) {
             if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
                 throw new IllegalArgumentException(
@@ -189,6 +193,7 @@
          *
          * @throws IllegalStateException if angle, error, or confidence values are missing
          */
+        @NonNull
         public AngleMeasurement build() {
             if (Double.isNaN(mRadians)) {
                 throw new IllegalStateException("Angle is not set");
diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java
index cd5af69..20a1c7a 100644
--- a/core/java/android/uwb/AngleOfArrivalMeasurement.java
+++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java
@@ -53,7 +53,7 @@
      * @return the azimuth {@link AngleMeasurement}
      */
     @NonNull
-    public AngleMeasurement getAzimuth() {
+    public AngleMeasurement getAzimuthAngleMeasurement() {
         return mAzimuthAngleMeasurement;
     }
 
@@ -70,7 +70,7 @@
      * @return altitude {@link AngleMeasurement} or null when this is not available
      */
     @Nullable
-    public AngleMeasurement getAltitude() {
+    public AngleMeasurement getAltitudeAngleMeasurement() {
         return mAltitudeAngleMeasurement;
     }
 
@@ -85,8 +85,8 @@
 
         if (obj instanceof AngleOfArrivalMeasurement) {
             AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj;
-            return mAzimuthAngleMeasurement.equals(other.getAzimuth())
-                    && mAltitudeAngleMeasurement.equals(other.getAltitude());
+            return mAzimuthAngleMeasurement.equals(other.getAzimuthAngleMeasurement())
+                    && mAltitudeAngleMeasurement.equals(other.getAltitudeAngleMeasurement());
         }
         return false;
     }
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelable(mAzimuthAngleMeasurement, flags);
         dest.writeParcelable(mAltitudeAngleMeasurement, flags);
     }
@@ -143,6 +143,7 @@
          *
          * @param azimuthAngle azimuth angle
          */
+        @NonNull
         public Builder setAzimuthAngleMeasurement(@NonNull AngleMeasurement azimuthAngle) {
             mAzimuthAngleMeasurement = azimuthAngle;
             return this;
@@ -153,6 +154,7 @@
          *
          * @param altitudeAngle altitude angle
          */
+        @NonNull
         public Builder setAltitudeAngleMeasurement(@NonNull AngleMeasurement altitudeAngle) {
             mAltitudeAngleMeasurement = altitudeAngle;
             return this;
@@ -163,6 +165,7 @@
          *
          * @throws IllegalStateException if the required azimuth angle is not provided
          */
+        @NonNull
         public AngleOfArrivalMeasurement build() {
             if (mAzimuthAngleMeasurement == null) {
                 throw new IllegalStateException("Azimuth angle measurement is not set");
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
index c959840..10c2172 100644
--- a/core/java/android/uwb/DistanceMeasurement.java
+++ b/core/java/android/uwb/DistanceMeasurement.java
@@ -17,6 +17,7 @@
 package android.uwb;
 
 import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -106,7 +107,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeDouble(mMeters);
         dest.writeDouble(mErrorMeters);
         dest.writeDouble(mConfidenceLevel);
@@ -143,6 +144,7 @@
          * @param meters distance in meters
          * @throws IllegalArgumentException if meters is NaN
          */
+        @NonNull
         public Builder setMeters(double meters) {
             if (Double.isNaN(meters)) {
                 throw new IllegalArgumentException("meters cannot be NaN");
@@ -157,6 +159,7 @@
          * @param errorMeters distance error in meters
          * @throws IllegalArgumentException if error is negative or NaN
          */
+        @NonNull
         public Builder setErrorMeters(double errorMeters) {
             if (Double.isNaN(errorMeters) || errorMeters < 0.0) {
                 throw new IllegalArgumentException(
@@ -172,6 +175,7 @@
          * @param confidenceLevel the confidence level in the distance measurement
          * @throws IllegalArgumentException if confidence level is not in the range of [0.0, 1.0]
          */
+        @NonNull
         public Builder setConfidenceLevel(double confidenceLevel) {
             if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
                 throw new IllegalArgumentException(
@@ -186,6 +190,7 @@
          *
          * @throws IllegalStateException if meters, error, or confidence are not set
          */
+        @NonNull
         public DistanceMeasurement build() {
             if (Double.isNaN(mMeters)) {
                 throw new IllegalStateException("Meters cannot be NaN");
diff --git a/core/java/android/uwb/OWNERS b/core/java/android/uwb/OWNERS
new file mode 100644
index 0000000..ea41c39
--- /dev/null
+++ b/core/java/android/uwb/OWNERS
@@ -0,0 +1,5 @@
+bstack@google.com
+eliptus@google.com
+jsolnit@google.com
+siyuanh@google.com
+zachoverflow@google.com
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
new file mode 100644
index 0000000..a9bf4ab
--- /dev/null
+++ b/core/java/android/uwb/RangingManager.java
@@ -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.
+ */
+
+package android.uwb;
+
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Hashtable;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
+    private static final String TAG = "Uwb.RangingManager";
+
+    private final IUwbAdapter mAdapter;
+    private final Hashtable<SessionHandle, RangingSession> mRangingSessionTable = new Hashtable<>();
+
+    public RangingManager(IUwbAdapter adapter) {
+        mAdapter = adapter;
+    }
+
+    /**
+     * Open a new ranging session
+     *
+     * @param params the parameters that define the ranging session
+     * @param executor {@link Executor} to run callbacks
+     * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession}
+     *                  that is being opened.
+     * @return a new {@link RangingSession}
+     */
+    public RangingSession openSession(@NonNull PersistableBundle params, @NonNull Executor executor,
+            @NonNull RangingSession.Callback callbacks) {
+        SessionHandle sessionHandle;
+        try {
+            sessionHandle = mAdapter.startRanging(this, params);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        synchronized (this) {
+            if (hasSession(sessionHandle)) {
+                Log.w(TAG, "Newly created session unexpectedly reuses an active SessionHandle");
+                executor.execute(() -> callbacks.onClosed(
+                        RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR,
+                        new PersistableBundle()));
+            }
+
+            RangingSession session =
+                    new RangingSession(executor, callbacks, mAdapter, sessionHandle);
+            mRangingSessionTable.put(sessionHandle, session);
+            return session;
+        }
+    }
+
+    private boolean hasSession(SessionHandle sessionHandle) {
+        return mRangingSessionTable.containsKey(sessionHandle);
+    }
+
+    @Override
+    public void onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters) {
+        synchronized (this) {
+            if (!hasSession(sessionHandle)) {
+                Log.w(TAG,
+                        "onRangingStarted - received unexpected SessionHandle: " + sessionHandle);
+                return;
+            }
+
+            RangingSession session = mRangingSessionTable.get(sessionHandle);
+            session.onRangingStarted(parameters);
+        }
+    }
+
+    @Override
+    public void onRangingStartFailed(SessionHandle sessionHandle, int reason,
+            PersistableBundle params) {
+        synchronized (this) {
+            if (!hasSession(sessionHandle)) {
+                Log.w(TAG, "onRangingStartFailed - received unexpected SessionHandle: "
+                        + sessionHandle);
+                return;
+            }
+
+            RangingSession session = mRangingSessionTable.get(sessionHandle);
+            session.onRangingClosed(convertStartFailureToCloseReason(reason), params);
+            mRangingSessionTable.remove(sessionHandle);
+        }
+    }
+
+    @Override
+    public void onRangingClosed(SessionHandle sessionHandle, int reason, PersistableBundle params) {
+        synchronized (this) {
+            if (!hasSession(sessionHandle)) {
+                Log.w(TAG, "onRangingClosed - received unexpected SessionHandle: " + sessionHandle);
+                return;
+            }
+
+            RangingSession session = mRangingSessionTable.get(sessionHandle);
+            session.onRangingClosed(convertToCloseReason(reason), params);
+            mRangingSessionTable.remove(sessionHandle);
+        }
+    }
+
+    @Override
+    public void onRangingResult(SessionHandle sessionHandle, RangingReport result) {
+        synchronized (this) {
+            if (!hasSession(sessionHandle)) {
+                Log.w(TAG, "onRangingResult - received unexpected SessionHandle: " + sessionHandle);
+                return;
+            }
+
+            RangingSession session = mRangingSessionTable.get(sessionHandle);
+            session.onRangingResult(result);
+        }
+    }
+
+    @RangingSession.Callback.CloseReason
+    private static int convertToCloseReason(@CloseReason int reason) {
+        switch (reason) {
+            case CloseReason.LOCAL_API:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API;
+
+            case CloseReason.MAX_SESSIONS_REACHED:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
+
+            case CloseReason.SYSTEM_POLICY:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+
+            case CloseReason.REMOTE_REQUEST:
+                return RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST;
+
+            case CloseReason.PROTOCOL_SPECIFIC:
+                return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
+
+            case CloseReason.UNKNOWN:
+            default:
+                return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
+        }
+    }
+
+    @RangingSession.Callback.CloseReason
+    private static int convertStartFailureToCloseReason(@StartFailureReason int reason) {
+        switch (reason) {
+            case StartFailureReason.BAD_PARAMETERS:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS;
+
+            case StartFailureReason.MAX_SESSIONS_REACHED:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
+
+            case StartFailureReason.SYSTEM_POLICY:
+                return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+
+            case StartFailureReason.PROTOCOL_SPECIFIC:
+                return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
+
+            case StartFailureReason.UNKNOWN:
+            default:
+                return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
+        }
+    }
+}
diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java
index f1c3162..50e5f0d 100644
--- a/core/java/android/uwb/RangingMeasurement.java
+++ b/core/java/android/uwb/RangingMeasurement.java
@@ -60,6 +60,9 @@
         return mRemoteDeviceAddress;
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
             RANGING_STATUS_SUCCESS,
@@ -115,7 +118,7 @@
      *         {@link #RANGING_STATUS_SUCCESS}
      */
     @Nullable
-    public DistanceMeasurement getDistance() {
+    public DistanceMeasurement getDistanceMeasurement() {
         return mDistanceMeasurement;
     }
 
@@ -126,7 +129,7 @@
      *         {@link #RANGING_STATUS_SUCCESS}
      */
     @Nullable
-    public AngleOfArrivalMeasurement getAngleOfArrival() {
+    public AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() {
         return mAngleOfArrivalMeasurement;
     }
 
@@ -144,8 +147,8 @@
             return mRemoteDeviceAddress.equals(other.getRemoteDeviceAddress())
                     && mStatus == other.getStatus()
                     && mElapsedRealtimeNanos == other.getElapsedRealtimeNanos()
-                    && mDistanceMeasurement.equals(other.getDistance())
-                    && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrival());
+                    && mDistanceMeasurement.equals(other.getDistanceMeasurement())
+                    && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrivalMeasurement());
         }
         return false;
     }
@@ -165,7 +168,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelable(mRemoteDeviceAddress, flags);
         dest.writeInt(mStatus);
         dest.writeLong(mElapsedRealtimeNanos);
@@ -210,6 +213,7 @@
          *
          * @param remoteDeviceAddress remote device's address
          */
+        @NonNull
         public Builder setRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
             mRemoteDeviceAddress = remoteDeviceAddress;
             return this;
@@ -220,6 +224,7 @@
          *
          * @param status the status of the ranging measurement
          */
+        @NonNull
         public Builder setStatus(@Status int status) {
             mStatus = status;
             return this;
@@ -230,6 +235,7 @@
          *
          * @param elapsedRealtimeNanos time the ranging measurement occurred
          */
+        @NonNull
         public Builder setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
             if (elapsedRealtimeNanos < 0) {
                 throw new IllegalArgumentException("elapsedRealtimeNanos must be >= 0");
@@ -243,6 +249,7 @@
          *
          * @param distanceMeasurement the distance measurement for this ranging measurement
          */
+        @NonNull
         public Builder setDistanceMeasurement(@NonNull DistanceMeasurement distanceMeasurement) {
             mDistanceMeasurement = distanceMeasurement;
             return this;
@@ -254,6 +261,7 @@
          * @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging
          *                                  measurement
          */
+        @NonNull
         public Builder setAngleOfArrivalMeasurement(
                 @NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
             mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
@@ -268,6 +276,7 @@
          *                               elapsedRealtimeNanos of the measurement is invalid, or
          *                               if no remote device address is set
          */
+        @NonNull
         public RangingMeasurement build() {
             if (mStatus != RANGING_STATUS_SUCCESS) {
                 if (mDistanceMeasurement != null) {
diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java
index 45180bf..5b5f084 100644
--- a/core/java/android/uwb/RangingReport.java
+++ b/core/java/android/uwb/RangingReport.java
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedList(mRangingMeasurements);
     }
 
@@ -113,6 +113,7 @@
          *
          * @param rangingMeasurement a ranging measurement
          */
+        @NonNull
         public Builder addMeasurement(@NonNull RangingMeasurement rangingMeasurement) {
             mMeasurements.add(rangingMeasurement);
             return this;
@@ -123,6 +124,7 @@
          *
          * @param rangingMeasurements {@link List} of {@link RangingMeasurement}s to add
          */
+        @NonNull
         public Builder addMeasurements(@NonNull List<RangingMeasurement> rangingMeasurements) {
             mMeasurements.addAll(rangingMeasurements);
             return this;
@@ -133,6 +135,7 @@
          *
          * @throws IllegalStateException if measurements are not in monotonically increasing order
          */
+        @NonNull
         public RangingReport build() {
             // Verify that all measurement timestamps are monotonically increasing
             RangingMeasurement prevMeasurement = null;
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
index 8639269..b0dbd85 100644
--- a/core/java/android/uwb/RangingSession.java
+++ b/core/java/android/uwb/RangingSession.java
@@ -17,7 +17,11 @@
 package android.uwb;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Binder;
 import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.util.Log;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -33,12 +37,26 @@
  * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
  * session. Once the session is opened, a {@link RangingSession} object is provided through
  * {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)}. If opening a
- * session fails, the failure is reported through {@link RangingSession.Callback#onClosed(int)} with
- * the failure reason.
+ * session fails, the failure is reported through
+ * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} with the failure reason.
  *
  * @hide
  */
 public final class RangingSession implements AutoCloseable {
+    private static final String TAG = "Uwb.RangingSession";
+    private final SessionHandle mSessionHandle;
+    private final IUwbAdapter mAdapter;
+    private final Executor mExecutor;
+    private final Callback mCallback;
+
+    private enum State {
+        INIT,
+        OPEN,
+        CLOSED,
+    }
+
+    private State mState;
+
     /**
      * Interface for receiving {@link RangingSession} events
      */
@@ -50,8 +68,11 @@
          * @param session the newly opened {@link RangingSession}
          * @param sessionInfo session specific parameters from lower layers
          */
-        void onOpenSuccess(RangingSession session, PersistableBundle sessionInfo);
+        void onOpenSuccess(@NonNull RangingSession session, @NonNull PersistableBundle sessionInfo);
 
+        /**
+         * @hide
+         */
         @Retention(RetentionPolicy.SOURCE)
         @IntDef(value = {
                 CLOSE_REASON_UNKNOWN,
@@ -112,20 +133,46 @@
         int CLOSE_REASON_REMOTE_REQUEST = 7;
 
         /**
+         * Indicates that the session was closed for a protocol specific reason. The associated
+         * {@link PersistableBundle} should be consulted for additional information.
+         */
+        int CLOSE_REASON_PROTOCOL_SPECIFIC = 8;
+
+        /**
          * Invoked when session is either closed spontaneously, or per user request via
          * {@link RangingSession#close()} or {@link AutoCloseable#close()}, or when session failed
          * to open.
          *
          * @param reason reason for the session closure
+         * @param parameters protocol specific parameters related to the close reason
          */
-        void onClosed(@CloseReason int reason);
+        void onClosed(@CloseReason int reason, @NonNull PersistableBundle parameters);
 
         /**
          * Called once per ranging interval even when a ranging measurement fails
          *
          * @param rangingReport ranging report for this interval's measurements
          */
-        void onReportReceived(RangingReport rangingReport);
+        void onReportReceived(@NonNull RangingReport rangingReport);
+    }
+
+    /**
+     * @hide
+     */
+    public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
+            SessionHandle sessionHandle) {
+        mState = State.INIT;
+        mExecutor = executor;
+        mCallback = callback;
+        mAdapter = adapter;
+        mSessionHandle = sessionHandle;
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isOpen() {
+        return mState == State.OPEN;
     }
 
     /**
@@ -133,16 +180,74 @@
      * <p>If this session is currently open, it will close and stop the session.
      * <p>If the session is in the process of being opened, it will attempt to stop the session from
      * being opened.
-     * <p>If the session is already closed, the registered {@link Callback#onClosed(int)} callback
-     * will still be invoked.
+     * <p>If the session is already closed, the registered
+     * {@link Callback#onClosed(int, PersistableBundle)} callback will still be invoked.
      *
-     * <p>{@link Callback#onClosed(int)} will be invoked using the same callback
+     * <p>{@link Callback#onClosed(int, PersistableBundle)} will be invoked using the same callback
      * object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
      * when the {@link RangingSession} was opened. The callback will be invoked after each call to
      * {@link #close()}, even if the {@link RangingSession} is already closed.
      */
     @Override
     public void close() {
-        throw new UnsupportedOperationException();
+        if (mState == State.CLOSED) {
+            mExecutor.execute(() -> mCallback.onClosed(
+                    Callback.CLOSE_REASON_LOCAL_CLOSE_API, new PersistableBundle()));
+            return;
+        }
+
+        try {
+            mAdapter.closeRanging(mSessionHandle);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onRangingStarted(@NonNull PersistableBundle parameters) {
+        if (mState == State.CLOSED) {
+            Log.w(TAG, "onRangingStarted invoked for a closed session");
+            return;
+        }
+
+        mState = State.OPEN;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(() -> mCallback.onOpenSuccess(this, parameters));
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onRangingClosed(@Callback.CloseReason int reason, PersistableBundle parameters) {
+        mState = State.CLOSED;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(() -> mCallback.onClosed(reason, parameters));
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onRangingResult(@NonNull RangingReport report) {
+        if (!isOpen()) {
+            Log.w(TAG, "onRangingResult invoked for non-open session");
+            return;
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(() -> mCallback.onReportReceived(report));
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 }
diff --git a/core/java/android/uwb/UwbAddress.java b/core/java/android/uwb/UwbAddress.java
index 828324c..b9523a3 100644
--- a/core/java/android/uwb/UwbAddress.java
+++ b/core/java/android/uwb/UwbAddress.java
@@ -51,7 +51,7 @@
      *       {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes
      */
     @NonNull
-    public static UwbAddress fromBytes(@NonNull byte[] address) throws IllegalArgumentException {
+    public static UwbAddress fromBytes(@NonNull byte[] address) {
         if (address.length != SHORT_ADDRESS_BYTE_LENGTH
                 && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) {
             throw new IllegalArgumentException("Invalid UwbAddress length " + address.length);
@@ -107,7 +107,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mAddressBytes.length);
         dest.writeByteArray(mAddressBytes);
     }
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index ed5cf36..f4d8018 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -49,12 +49,16 @@
     private IUwbAdapter mUwbAdapter;
     private static final String SERVICE_NAME = "uwb";
 
-    private AdapterStateListener mAdapterStateListener;
+    private final AdapterStateListener mAdapterStateListener;
+    private final RangingManager mRangingManager;
 
     /**
      * Interface for receiving UWB adapter state changes
      */
     public interface AdapterStateCallback {
+        /**
+         * @hide
+         */
         @Retention(RetentionPolicy.SOURCE)
         @IntDef(value = {
                 STATE_CHANGED_REASON_SESSION_STARTED,
@@ -116,6 +120,7 @@
     private UwbManager(IUwbAdapter adapter) {
         mUwbAdapter = adapter;
         mAdapterStateListener = new AdapterStateListener(adapter);
+        mRangingManager = new RangingManager(adapter);
     }
 
     /**
@@ -195,6 +200,9 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
             ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE,
@@ -387,8 +395,8 @@
      */
     @NonNull
     public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters,
-            @NonNull Executor executor,
+            @NonNull @CallbackExecutor Executor executor,
             @NonNull RangingSession.Callback callbacks) {
-        throw new UnsupportedOperationException();
+        return mRangingManager.openSession(parameters, executor, callbacks);
     }
 }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index cc18b99d..2e90619 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -26,7 +26,6 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -114,6 +113,8 @@
 
     private AddNodeInfosForViewId mAddNodeInfosForViewId;
 
+    private List<Message> mPendingFindNodeByIdMessages;
+
     @GuardedBy("mLock")
     private int mNumActiveRequestPreparers;
     @GuardedBy("mLock")
@@ -129,6 +130,7 @@
         mViewRootImpl = viewRootImpl;
         mPrefetcher = new AccessibilityNodePrefetcher();
         mA11yManager = mViewRootImpl.mContext.getSystemService(AccessibilityManager.class);
+        mPendingFindNodeByIdMessages = new ArrayList<>();
     }
 
     private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid,
@@ -178,6 +180,7 @@
         args.arg4 = arguments;
         message.obj = args;
 
+        mPendingFindNodeByIdMessages.add(message);
         scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS);
     }
 
@@ -316,6 +319,8 @@
     }
 
     private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
+        mPendingFindNodeByIdMessages.remove(message);
+
         final int flags = message.arg1;
 
         SomeArgs args = (SomeArgs) message.obj;
@@ -330,22 +335,58 @@
 
         args.recycle();
 
-        List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
-        infos.clear();
+        View rootView = null;
+        AccessibilityNodeInfo rootNode = null;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
                 return;
             }
             mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
-            final View root = findViewByAccessibilityId(accessibilityViewId);
-            if (root != null && isShown(root)) {
-                mPrefetcher.prefetchAccessibilityNodeInfos(
-                        root, virtualDescendantId, flags, infos, arguments);
+            rootView = findViewByAccessibilityId(accessibilityViewId);
+            if (rootView != null && isShown(rootView)) {
+                rootNode = populateAccessibilityNodeInfoForView(
+                        rootView, arguments, virtualDescendantId);
             }
         } finally {
-            updateInfosForViewportAndReturnFindNodeResult(
-                    infos, callback, interactionId, spec, interactiveRegion);
+            updateInfoForViewportAndReturnFindNodeResult(
+                    rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
+                    callback, interactionId, spec, interactiveRegion);
         }
+        List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
+        infos.clear();
+        mPrefetcher.prefetchAccessibilityNodeInfos(
+                rootView, rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
+                virtualDescendantId, flags, infos);
+        mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+        updateInfosForViewPort(infos, spec, interactiveRegion);
+        returnPrefetchResult(interactionId, infos, callback);
+        returnPendingFindAccessibilityNodeInfosInPrefetch(infos);
+    }
+
+    private AccessibilityNodeInfo populateAccessibilityNodeInfoForView(
+            View view, Bundle arguments, int virtualViewId) {
+        AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+        // Determine if we'll be populating extra data
+        final String extraDataRequested = (arguments == null) ? null
+                : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
+        AccessibilityNodeInfo root = null;
+        if (provider == null) {
+            root = view.createAccessibilityNodeInfo();
+            if (root != null) {
+                if (extraDataRequested != null) {
+                    view.addExtraDataToAccessibilityNodeInfo(root, extraDataRequested, arguments);
+                }
+            }
+        } else {
+            root = provider.createAccessibilityNodeInfo(virtualViewId);
+            if (root != null) {
+                if (extraDataRequested != null) {
+                    provider.addExtraDataToAccessibilityNodeInfo(
+                            virtualViewId, root, extraDataRequested, arguments);
+                }
+            }
+        }
+        return root;
     }
 
     public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
@@ -403,6 +444,7 @@
                 mAddNodeInfosForViewId.reset();
             }
         } finally {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             updateInfosForViewportAndReturnFindNodeResult(
                     infos, callback, interactionId, spec, interactiveRegion);
         }
@@ -485,6 +527,7 @@
                 }
             }
         } finally {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             updateInfosForViewportAndReturnFindNodeResult(
                     infos, callback, interactionId, spec, interactiveRegion);
         }
@@ -576,6 +619,7 @@
                 }
             }
         } finally {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             updateInfoForViewportAndReturnFindNodeResult(
                     focused, callback, interactionId, spec, interactiveRegion);
         }
@@ -630,6 +674,7 @@
                 }
             }
         } finally {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             updateInfoForViewportAndReturnFindNodeResult(
                     next, callback, interactionId, spec, interactiveRegion);
         }
@@ -786,33 +831,6 @@
         }
     }
 
-    private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos,
-            MagnificationSpec spec) {
-        if (infos == null) {
-            return;
-        }
-        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
-        if (shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
-            final int infoCount = infos.size();
-            for (int i = 0; i < infoCount; i++) {
-                AccessibilityNodeInfo info = infos.get(i);
-                applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
-            }
-        }
-    }
-
-    private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos,
-            Region interactiveRegion) {
-        if (interactiveRegion == null || infos == null) {
-            return;
-        }
-        final int infoCount = infos.size();
-        for (int i = 0; i < infoCount; i++) {
-            AccessibilityNodeInfo info = infos.get(i);
-            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
-        }
-    }
-
     private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
             Region interactiveRegion) {
         if (interactiveRegion == null || info == null) {
@@ -833,17 +851,6 @@
         return false;
     }
 
-    private void adjustBoundsInScreenIfNeeded(List<AccessibilityNodeInfo> infos) {
-        if (infos == null || shouldBypassAdjustBoundsInScreen()) {
-            return;
-        }
-        final int infoCount = infos.size();
-        for (int i = 0; i < infoCount; i++) {
-            final AccessibilityNodeInfo info = infos.get(i);
-            adjustBoundsInScreenIfNeeded(info);
-        }
-    }
-
     private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) {
         if (info == null || shouldBypassAdjustBoundsInScreen()) {
             return;
@@ -891,17 +898,6 @@
         return screenMatrix == null || screenMatrix.isIdentity();
     }
 
-    private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
-        if (infos == null || shouldBypassAssociateLeashedParent()) {
-            return;
-        }
-        final int infoCount = infos.size();
-        for (int i = 0; i < infoCount; i++) {
-            final AccessibilityNodeInfo info = infos.get(i);
-            associateLeashedParentIfNeeded(info);
-        }
-    }
-
     private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) {
         if (info == null || shouldBypassAssociateLeashedParent()) {
             return;
@@ -975,63 +971,98 @@
         return (appScale != 1.0f || (spec != null && !spec.isNop()));
     }
 
+    private void updateInfosForViewPort(List<AccessibilityNodeInfo> infos, MagnificationSpec spec,
+                                        Region interactiveRegion) {
+        for (int i = 0; i < infos.size(); i++) {
+            updateInfoForViewPort(infos.get(i), spec, interactiveRegion);
+        }
+    }
+
+    private void updateInfoForViewPort(AccessibilityNodeInfo info, MagnificationSpec spec,
+                                       Region interactiveRegion) {
+        associateLeashedParentIfNeeded(info);
+        applyScreenMatrixIfNeeded(info);
+        adjustBoundsInScreenIfNeeded(info);
+        // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
+        // then impact the visibility result, we need to adjust visibility before apply scale.
+        adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+        applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
+    }
+
     private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos,
             IAccessibilityInteractionConnectionCallback callback, int interactionId,
             MagnificationSpec spec, Region interactiveRegion) {
+        if (infos != null) {
+            updateInfosForViewPort(infos, spec, interactiveRegion);
+        }
+        returnFindNodesResult(infos, callback, interactionId);
+    }
+
+    private void returnFindNodeResult(AccessibilityNodeInfo info,
+                                      IAccessibilityInteractionConnectionCallback callback,
+                                      int interactionId) {
         try {
-            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-            associateLeashedParentIfNeeded(infos);
-            applyScreenMatrixIfNeeded(infos);
-            adjustBoundsInScreenIfNeeded(infos);
-            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
-            // then impact the visibility result, we need to adjust visibility before apply scale.
-            adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
-            applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+            callback.setFindAccessibilityNodeInfoResult(info, interactionId);
+        } catch (RemoteException re) {
+            /* ignore - the other side will time out */
+        }
+    }
+
+    private void returnFindNodesResult(List<AccessibilityNodeInfo> infos,
+            IAccessibilityInteractionConnectionCallback callback, int interactionId) {
+        try {
             callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             if (infos != null) {
                 infos.clear();
             }
         } catch (RemoteException re) {
             /* ignore - the other side will time out */
-        } finally {
-            recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion);
+        }
+    }
+
+    private void returnPendingFindAccessibilityNodeInfosInPrefetch(
+            List<AccessibilityNodeInfo> infos) {
+        for (Message pendingMessage : mPendingFindNodeByIdMessages) {
+            SomeArgs args = (SomeArgs) pendingMessage.obj;
+            final int accessibilityViewId = args.argi1;
+            final int virtualDescendantId = args.argi2;
+            final int interactionId = args.argi3;
+            final IAccessibilityInteractionConnectionCallback callback =
+                    (IAccessibilityInteractionConnectionCallback) args.arg1;
+            final long nodeId =
+                    AccessibilityNodeInfo.makeNodeId(accessibilityViewId, virtualDescendantId);
+            for (int i = 0; i < infos.size(); i++) {
+                AccessibilityNodeInfo info = infos.get(i);
+                if (info.getSourceNodeId() == nodeId) {
+                    returnFindNodeResult(
+                            AccessibilityNodeInfo.obtain(info), callback, interactionId);
+                    mHandler.removeMessages(
+                            PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID,
+                            pendingMessage.obj);
+                    args.recycle();
+                    break;
+                }
+            }
+        }
+        mPendingFindNodeByIdMessages.clear();
+    }
+
+    private void returnPrefetchResult(int interactionId, List<AccessibilityNodeInfo> infos,
+                                      IAccessibilityInteractionConnectionCallback callback) {
+        if (infos.size() > 0) {
+            try {
+                callback.setPrefetchAccessibilityNodeInfoResult(infos, interactionId);
+            } catch (RemoteException re) {
+                /* ignore - other side isn't too bothered if this doesn't arrive */
+            }
         }
     }
 
     private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info,
             IAccessibilityInteractionConnectionCallback callback, int interactionId,
             MagnificationSpec spec, Region interactiveRegion) {
-        try {
-            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-            associateLeashedParentIfNeeded(info);
-            applyScreenMatrixIfNeeded(info);
-            adjustBoundsInScreenIfNeeded(info);
-            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
-            // then impact the visibility result, we need to adjust visibility before apply scale.
-            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
-            applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
-            callback.setFindAccessibilityNodeInfoResult(info, interactionId);
-        } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-        } finally {
-            recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion);
-        }
-    }
-
-    private void recycleMagnificationSpecAndRegionIfNeeded(MagnificationSpec spec, Region region) {
-        if (android.os.Process.myPid() != Binder.getCallingPid()) {
-            // Specs are cached in the system process and obtained from a pool when read from
-            // a parcel, so only recycle the spec if called from another process.
-            if (spec != null) {
-                spec.recycle();
-            }
-        } else {
-            // Regions are obtained in the system process and instantiated when read from
-            // a parcel, so only recycle the region if caled from the same process.
-            if (region != null) {
-                region.recycle();
-            }
-        }
+        updateInfoForViewPort(info, spec, interactiveRegion);
+        returnFindNodeResult(info, callback, interactionId);
     }
 
     private boolean handleClickableSpanActionUiThread(
@@ -1074,20 +1105,11 @@
 
         private final ArrayList<View> mTempViewList = new ArrayList<View>();
 
-        public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags,
-                List<AccessibilityNodeInfo> outInfos, Bundle arguments) {
-            AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
-            // Determine if we'll be populating extra data
-            final String extraDataRequested = (arguments == null) ? null
-                    : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
-            if (provider == null) {
-                AccessibilityNodeInfo root = view.createAccessibilityNodeInfo();
-                if (root != null) {
-                    if (extraDataRequested != null) {
-                        view.addExtraDataToAccessibilityNodeInfo(
-                                root, extraDataRequested, arguments);
-                    }
-                    outInfos.add(root);
+        public void prefetchAccessibilityNodeInfos(View view, AccessibilityNodeInfo root,
+                int virtualViewId, int fetchFlags, List<AccessibilityNodeInfo> outInfos) {
+            if (root != null) {
+                AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+                if (provider == null) {
                     if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                         prefetchPredecessorsOfRealNode(view, outInfos);
                     }
@@ -1097,16 +1119,7 @@
                     if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
                         prefetchDescendantsOfRealNode(view, outInfos);
                     }
-                }
-            } else {
-                final AccessibilityNodeInfo root =
-                        provider.createAccessibilityNodeInfo(virtualViewId);
-                if (root != null) {
-                    if (extraDataRequested != null) {
-                        provider.addExtraDataToAccessibilityNodeInfo(
-                                virtualViewId, root, extraDataRequested, arguments);
-                    }
-                    outInfos.add(root);
+                } else {
                     if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                         prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
                     }
@@ -1117,13 +1130,19 @@
                         prefetchDescendantsOfVirtualNode(root, provider, outInfos);
                     }
                 }
-            }
-            if (ENFORCE_NODE_TREE_CONSISTENT) {
-                enforceNodeTreeConsistent(outInfos);
+                if (ENFORCE_NODE_TREE_CONSISTENT) {
+                    enforceNodeTreeConsistent(root, outInfos);
+                }
             }
         }
 
-        private void enforceNodeTreeConsistent(List<AccessibilityNodeInfo> nodes) {
+        private boolean shouldStopPrefetching(List prefetchededInfos) {
+            return mHandler.hasUserInteractiveMessagesWaiting()
+                    || prefetchededInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE;
+        }
+
+        private void enforceNodeTreeConsistent(
+                AccessibilityNodeInfo root, List<AccessibilityNodeInfo> nodes) {
             LongSparseArray<AccessibilityNodeInfo> nodeMap =
                     new LongSparseArray<AccessibilityNodeInfo>();
             final int nodeCount = nodes.size();
@@ -1134,7 +1153,6 @@
 
             // If the nodes are a tree it does not matter from
             // which node we start to search for the root.
-            AccessibilityNodeInfo root = nodeMap.valueAt(0);
             AccessibilityNodeInfo parent = root;
             while (parent != null) {
                 root = parent;
@@ -1201,9 +1219,11 @@
 
         private void prefetchPredecessorsOfRealNode(View view,
                 List<AccessibilityNodeInfo> outInfos) {
+            if (shouldStopPrefetching(outInfos)) {
+                return;
+            }
             ViewParent parent = view.getParentForAccessibility();
-            while (parent instanceof View
-                    && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+            while (parent instanceof View && !shouldStopPrefetching(outInfos)) {
                 View parentView = (View) parent;
                 AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
                 if (info != null) {
@@ -1215,6 +1235,9 @@
 
         private void prefetchSiblingsOfRealNode(View current,
                 List<AccessibilityNodeInfo> outInfos) {
+            if (shouldStopPrefetching(outInfos)) {
+                return;
+            }
             ViewParent parent = current.getParentForAccessibility();
             if (parent instanceof ViewGroup) {
                 ViewGroup parentGroup = (ViewGroup) parent;
@@ -1224,7 +1247,7 @@
                     parentGroup.addChildrenForAccessibility(children);
                     final int childCount = children.size();
                     for (int i = 0; i < childCount; i++) {
-                        if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                        if (shouldStopPrefetching(outInfos)) {
                             return;
                         }
                         View child = children.get(i);
@@ -1252,7 +1275,7 @@
 
         private void prefetchDescendantsOfRealNode(View root,
                 List<AccessibilityNodeInfo> outInfos) {
-            if (!(root instanceof ViewGroup)) {
+            if (shouldStopPrefetching(outInfos) || !(root instanceof ViewGroup)) {
                 return;
             }
             HashMap<View, AccessibilityNodeInfo> addedChildren =
@@ -1263,7 +1286,7 @@
                 root.addChildrenForAccessibility(children);
                 final int childCount = children.size();
                 for (int i = 0; i < childCount; i++) {
-                    if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                    if (shouldStopPrefetching(outInfos)) {
                         return;
                     }
                     View child = children.get(i);
@@ -1288,7 +1311,7 @@
             } finally {
                 children.clear();
             }
-            if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+            if (!shouldStopPrefetching(outInfos)) {
                 for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
                     View addedChild = entry.getKey();
                     AccessibilityNodeInfo virtualRoot = entry.getValue();
@@ -1310,7 +1333,7 @@
             long parentNodeId = root.getParentNodeId();
             int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
             while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                if (shouldStopPrefetching(outInfos)) {
                     return;
                 }
                 final int virtualDescendantId =
@@ -1355,7 +1378,7 @@
                 if (parent != null) {
                     final int childCount = parent.getChildCount();
                     for (int i = 0; i < childCount; i++) {
-                        if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                        if (shouldStopPrefetching(outInfos)) {
                             return;
                         }
                         final long childNodeId = parent.getChildId(i);
@@ -1380,7 +1403,7 @@
             final int initialOutInfosSize = outInfos.size();
             final int childCount = root.getChildCount();
             for (int i = 0; i < childCount; i++) {
-                if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                if (shouldStopPrefetching(outInfos)) {
                     return;
                 }
                 final long childNodeId = root.getChildId(i);
@@ -1390,7 +1413,7 @@
                     outInfos.add(child);
                 }
             }
-            if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+            if (!shouldStopPrefetching(outInfos)) {
                 final int addedChildCount = outInfos.size() - initialOutInfosSize;
                 for (int i = 0; i < addedChildCount; i++) {
                     AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i);
@@ -1499,6 +1522,10 @@
         boolean hasAccessibilityCallback(Message message) {
             return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
         }
+
+        boolean hasUserInteractiveMessagesWaiting() {
+            return hasMessagesOrCallbacks();
+        }
     }
 
     private final class AddNodeInfosForViewId implements Predicate<View> {
diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java
index fcf699f..bc66ea1 100644
--- a/core/java/android/view/ContentInfo.java
+++ b/core/java/android/view/ContentInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.net.Uri;
@@ -222,7 +223,10 @@
      * content that matched the predicate, or null if none of the items matched. The pair's
      * second object will have the content that didn't match the predicate, or null if all of
      * the items matched.
+     *
+     * @hide
      */
+    @TestApi
     @NonNull
     public Pair<ContentInfo, ContentInfo> partition(
             @NonNull Predicate<ClipData.Item> itemPredicate) {
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 0201605..0ac0305 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -325,6 +325,7 @@
                 && rotation == other.rotation
                 && modeId == other.modeId
                 && defaultModeId == other.defaultModeId
+                && Arrays.equals(supportedModes, other.supportedModes)
                 && colorMode == other.colorMode
                 && Arrays.equals(supportedColorModes, other.supportedColorModes)
                 && Objects.equals(hdrCapabilities, other.hdrCapabilities)
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index 84dd8af..29c9c15 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -58,19 +58,6 @@
     void onActivityHidden(in ComponentName componentName);
 
     /**
-     * Called when the window manager has detected change on DisplayInfo,  or
-     * when the listener is first registered to allow the listener to synchronized its state with
-     * the controller.
-     */
-    void onDisplayInfoChanged(in DisplayInfo displayInfo);
-
-    /**
-     * Called by the window manager at the beginning of a configuration update cascade
-     * since the metrics from these resources are used for bounds calculations.
-     */
-    void onConfigurationChanged();
-
-    /**
      * Called by the window manager when the aspect ratio is reset.
      */
     void onAspectRatioChanged(float aspectRatio);
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index f209d88..afbd249 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -20,6 +20,7 @@
 import android.view.IRemoteAnimationFinishedCallback;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
+import android.window.TaskSnapshot;
 
 /**
  * Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the
@@ -34,8 +35,7 @@
      * Takes a screenshot of the task associated with the given {@param taskId}. Only valid for the
      * current set of task ids provided to the handler.
      */
-    @UnsupportedAppUsage
-    ActivityManager.TaskSnapshot screenshotTask(int taskId);
+    TaskSnapshot screenshotTask(int taskId);
 
     /**
      * Sets the final bounds on a Task. This is used by Launcher to notify the system that
@@ -136,4 +136,13 @@
      * @return {@code true} when target removed successfully, {@code false} otherwise.
      */
     boolean removeTask(int taskId);
+
+    /**
+     * Detach navigation bar from app.
+     *
+     * The system reparents the leash of navigation bar to the app when the recents animation starts
+     * and Launcher should call this method to let system restore the navigation bar to its
+     * original position when the quick switch gesture is finished.
+     */
+    void detachNavigationBarFromApp();
 }
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index f054b86..8111755 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
 import android.view.IRecentsAnimationController;
+import android.window.TaskSnapshot;
 
 /**
  * Interface that is used to callback from window manager to the process that runs a recents
@@ -42,8 +43,7 @@
      *
      * @see {@link RecentsAnimationController#cleanupScreenshot}
      */
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    void onAnimationCanceled(in @nullable ActivityManager.TaskSnapshot taskSnapshot) = 1;
+    void onAnimationCanceled(in @nullable TaskSnapshot taskSnapshot) = 1;
 
     /**
      * Called when the system is ready for the handler to start animating all the visible tasks.
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index e685b30..fb012eb 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -130,11 +130,6 @@
     void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId);
 
     /**
-     * Tell the window that it is either gaining or losing pointer capture.
-     */
-    void dispatchPointerCaptureChanged(boolean hasCapture);
-
-    /**
      * Called when Scroll Capture support is requested for a window.
      *
      * @param callbacks to receive responses
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8da833a..f4b90e1 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -17,10 +17,12 @@
 package android.view;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.hardware.SensorManager;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
 import android.os.Build;
@@ -28,7 +30,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Vibrator;
+import android.os.VibratorManager;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
@@ -68,10 +72,18 @@
     private final boolean mHasVibrator;
     private final boolean mHasMicrophone;
     private final boolean mHasButtonUnderPad;
+    private final boolean mHasSensor;
     private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
 
+    @GuardedBy("mMotionRanges")
     private Vibrator mVibrator; // guarded by mMotionRanges during initialization
 
+    @GuardedBy("mMotionRanges")
+    private VibratorManager mVibratorManager;
+
+    @GuardedBy("mMotionRanges")
+    private SensorManager mSensorManager;
+
     /**
      * A mask for input source classes.
      *
@@ -415,6 +427,8 @@
 
     private static final int MAX_RANGES = 1000;
 
+    private static final int VIBRATOR_ID_ALL = -1;
+
     public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR =
             new Parcelable.Creator<InputDevice>() {
         public InputDevice createFromParcel(Parcel in) {
@@ -434,7 +448,7 @@
     public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
             int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
             KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
-            boolean hasButtonUnderPad) {
+            boolean hasButtonUnderPad, boolean hasSensor) {
         mId = id;
         mGeneration = generation;
         mControllerNumber = controllerNumber;
@@ -449,10 +463,12 @@
         mHasVibrator = hasVibrator;
         mHasMicrophone = hasMicrophone;
         mHasButtonUnderPad = hasButtonUnderPad;
+        mHasSensor = hasSensor;
         mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
     }
 
     private InputDevice(Parcel in) {
+        mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
         mId = in.readInt();
         mGeneration = in.readInt();
         mControllerNumber = in.readInt();
@@ -463,10 +479,10 @@
         mIsExternal = in.readInt() != 0;
         mSources = in.readInt();
         mKeyboardType = in.readInt();
-        mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
         mHasVibrator = in.readInt() != 0;
         mHasMicrophone = in.readInt() != 0;
         mHasButtonUnderPad = in.readInt() != 0;
+        mHasSensor = in.readInt() != 0;
         mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
 
         int numRanges = in.readInt();
@@ -785,7 +801,8 @@
         synchronized (mMotionRanges) {
             if (mVibrator == null) {
                 if (mHasVibrator) {
-                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
+                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId,
+                            VIBRATOR_ID_ALL);
                 } else {
                     mVibrator = NullVibrator.getInstance();
                 }
@@ -795,6 +812,44 @@
     }
 
     /**
+     * Gets the vibrator manager associated with the device.
+     * Even if the device does not have a vibrator manager, the result is never null.
+     * Use {@link VibratorManager#getVibratorIds} to determine whether any vibrator is
+     * present.
+     *
+     * @return The vibrator manager associated with the device, never null.
+     */
+    @NonNull
+    public VibratorManager getVibratorManager() {
+        synchronized (mMotionRanges) {
+            if (mVibratorManager == null) {
+                mVibratorManager = InputManager.getInstance().getInputDeviceVibratorManager(mId);
+            }
+        }
+        return mVibratorManager;
+    }
+
+    /**
+     * Gets the sensor manager service associated with the input device.
+     * Even if the device does not have a sensor, the result is never null.
+     * Use {@link SensorManager#getSensorList} to get a full list of all supported sensors.
+     *
+     * Note that the sensors associated with the device may be different from
+     * the system sensors, as typically they are builtin sensors physically attached to
+     * input devices.
+     *
+     * @return The sensor manager service associated with the device, never null.
+     */
+    public @NonNull SensorManager getSensorManager() {
+        synchronized (mMotionRanges) {
+            if (mSensorManager == null) {
+                mSensorManager = InputManager.getInstance().getInputDeviceSensorManager(mId);
+            }
+        }
+        return mSensorManager;
+    }
+
+    /**
      * Returns true if input device is enabled.
      * @return Whether the input device is enabled.
      */
@@ -842,6 +897,15 @@
     }
 
     /**
+     * Reports whether the device has a sensor.
+     * @return Whether the device has a sensor.
+     * @hide
+     */
+    public boolean hasSensor() {
+        return mHasSensor;
+    }
+
+    /**
      * Sets the current pointer type.
      * @param pointerType the type of the pointer icon.
      * @hide
@@ -972,6 +1036,7 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
+        mKeyCharacterMap.writeToParcel(out, flags);
         out.writeInt(mId);
         out.writeInt(mGeneration);
         out.writeInt(mControllerNumber);
@@ -982,10 +1047,10 @@
         out.writeInt(mIsExternal ? 1 : 0);
         out.writeInt(mSources);
         out.writeInt(mKeyboardType);
-        mKeyCharacterMap.writeToParcel(out, flags);
         out.writeInt(mHasVibrator ? 1 : 0);
         out.writeInt(mHasMicrophone ? 1 : 0);
         out.writeInt(mHasButtonUnderPad ? 1 : 0);
+        out.writeInt(mHasSensor ? 1 : 0);
 
         final int numRanges = mMotionRanges.size();
         out.writeInt(numRanges);
@@ -1030,6 +1095,8 @@
 
         description.append("  Has Vibrator: ").append(mHasVibrator).append("\n");
 
+        description.append("  Has Sensor: ").append(mHasSensor).append("\n");
+
         description.append("  Has mic: ").append(mHasMicrophone).append("\n");
 
         description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 4a5fa0f..0939336 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -81,6 +81,7 @@
                 SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i];
                 applyParams(t, surfaceParams, mTmpFloat9);
             }
+            t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
             t.apply();
             t.close();
         }
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 41b2fb4..b66dd29 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/MagnificationSpec.java b/core/java/android/view/MagnificationSpec.java
index 034598a..50d3113 100644
--- a/core/java/android/view/MagnificationSpec.java
+++ b/core/java/android/view/MagnificationSpec.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Pools.SynchronizedPool;
 
 /**
  * This class represents spec for performing screen magnification.
@@ -27,9 +26,6 @@
  * @hide
  */
 public class MagnificationSpec implements Parcelable {
-    private static final int MAX_POOL_SIZE = 20;
-    private static final SynchronizedPool<MagnificationSpec> sPool =
-            new SynchronizedPool<>(MAX_POOL_SIZE);
 
     /** The magnification scaling factor. */
     public float scale = 1.0f;
@@ -46,10 +42,6 @@
      */
     public float offsetY;
 
-    private MagnificationSpec() {
-        /* do nothing - reducing visibility */
-    }
-
     public void initialize(float scale, float offsetX, float offsetY) {
         if (scale < 1) {
             throw new IllegalArgumentException("Scale must be greater than or equal to one!");
@@ -63,24 +55,6 @@
         return scale == 1.0f && offsetX == 0 && offsetY == 0;
     }
 
-    public static MagnificationSpec obtain(MagnificationSpec other) {
-        MagnificationSpec info = obtain();
-        info.scale = other.scale;
-        info.offsetX = other.offsetX;
-        info.offsetY = other.offsetY;
-        return info;
-    }
-
-    public static MagnificationSpec obtain() {
-        MagnificationSpec spec = sPool.acquire();
-        return (spec != null) ? spec : new MagnificationSpec();
-    }
-
-    public void recycle() {
-        clear();
-        sPool.release(this);
-    }
-
     public void clear() {
        scale = 1.0f;
        offsetX = 0.0f;
@@ -103,7 +77,6 @@
         parcel.writeFloat(scale);
         parcel.writeFloat(offsetX);
         parcel.writeFloat(offsetY);
-        recycle();
     }
 
     @Override
@@ -155,7 +128,7 @@
 
         @Override
         public MagnificationSpec createFromParcel(Parcel parcel) {
-            MagnificationSpec spec = MagnificationSpec.obtain();
+            MagnificationSpec spec = new MagnificationSpec();
             spec.initFromParcel(parcel);
             return spec;
         }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index a8d2615..52b7cff 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -477,6 +477,14 @@
     public static final int FLAG_IS_GENERATED_GESTURE = 0x8;
 
     /**
+     * This flag associated with {@link #ACTION_POINTER_UP}, this indicates that the pointer
+     * has been canceled. Typically this is used for palm event when the user has accidental
+     * touches.
+     * @hide
+     */
+    public static final int FLAG_CANCELED = 0x20;
+
+    /**
      * Private flag that indicates when the system has detected that this motion event
      * may be inconsistent with respect to the sequence of previously delivered motion events,
      * such as when a pointer move event is sent but the pointer is not down.
@@ -3477,7 +3485,8 @@
                 } else if (newPointerCount == 1) {
                     // The first/last pointer went down/up.
                     newAction = oldActionMasked == ACTION_POINTER_DOWN
-                            ? ACTION_DOWN : ACTION_UP;
+                            ? ACTION_DOWN
+                            : (getFlags() & FLAG_CANCELED) == 0 ? ACTION_UP : ACTION_CANCEL;
                 } else {
                     // A secondary pointer went down/up.
                     newAction = oldActionMasked
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 7b60f2e..bae6ee8 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -1,15 +1,76 @@
+# Bug component: 25700
+
+romainguy@google.com
+alanv@google.com
+adamp@google.com
+aurimas@google.com
+nduca@google.com
+sumir@google.com
+ogunwale@google.com
+jjaggi@google.com
+roosa@google.com
+
 # Display
-per-file Display.java = michaelwr@google.com, santoscordon@google.com
-per-file DisplayInfo.java = michaelwr@google.com, santoscordon@google.com
+per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
+per-file Display*.aidl = file:/services/core/java/com/android/server/display/OWNERS
 
 # Haptics
-per-file HapticFeedbackConstants.java = michaelwr@google.com, santoscordon@google.com
+per-file HapticFeedbackConstants.java = file:/services/core/java/com/android/server/input/OWNERS
+
+# Ime
+per-file Ime*.java = file:/core/java/android/view/inputmethod/OWNERS
 
 # Input
-per-file IInputMonitorHost.aidl = michaelwr@google.com, svv@google.com
-per-file Input*.java = michaelwr@google.com, svv@google.com
-per-file Input*.aidl = michaelwr@google.com, svv@google.com
-per-file KeyEvent.java = michaelwr@google.com, svv@google.com
-per-file MotionEvent.java = michaelwr@google.com, svv@google.com
-per-file PointerIcon.java = michaelwr@google.com, svv@google.com
-per-file SimulatedDpad.java = michaelwr@google.com, svv@google.com
+per-file IInput*.aidl = file:/services/core/java/com/android/server/input/OWNERS
+per-file Input*.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file Input*.aidl = file:/services/core/java/com/android/server/input/OWNERS
+per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS
+
+# InputWindowHandle
+per-file InputWindowHandle.java  = file:/services/core/java/com/android/server/input/OWNERS
+per-file InputWindowHandle.java  = file:/services/core/java/com/android/server/wm/OWNERS
+
+# Surface
+per-file Surface.java = file:/graphics/java/android/graphics/OWNERS
+per-file Surface.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SurfaceView.java = file:/graphics/java/android/graphics/OWNERS
+per-file SurfaceView.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SurfaceHolder.java = file:/graphics/java/android/graphics/OWNERS
+per-file SurfaceHolder.java = file:/services/core/java/com/android/server/wm/OWNERS
+
+# View
+per-file View.java = file:/services/accessibility/OWNERS
+per-file View.java = file:/core/java/android/service/autofill/OWNERS
+per-file View.java = file:/graphics/java/android/graphics/OWNERS
+per-file View.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file View.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file View.java = file:/core/java/android/view/inputmethod/OWNERS
+per-file ViewRootImpl.java = file:/services/accessibility/OWNERS
+per-file ViewRootImpl.java = file:/core/java/android/service/autofill/OWNERS
+per-file ViewRootImpl.java = file:/graphics/java/android/graphics/OWNERS
+per-file ViewRootImpl.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file ViewRootImpl.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file ViewRootImpl.java = file:/core/java/android/view/inputmethod/OWNERS
+
+# WindowManager
+per-file DisplayCutout.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file DisplayCutout.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file IDisplay*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Inset*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Inset*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file IPinnedStackListener.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file IRecents*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file IRemote*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file IWindow*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file RemoteAnimation*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file RemoteAnimation*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SurfaceControl*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SurfaceControl*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SurfaceSession.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file SyncRtSurfaceTransactionApplier.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file ViewRootInsetsControllerHost.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Window*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/view/OnReceiveContentListener.java b/core/java/android/view/OnReceiveContentListener.java
index 419f964..3d9968c 100644
--- a/core/java/android/view/OnReceiveContentListener.java
+++ b/core/java/android/view/OnReceiveContentListener.java
@@ -36,7 +36,7 @@
  *     &#64;Override
  *     public ContentInfo onReceiveContent(View view, ContentInfo payload) {
  *         Pair&lt;ContentInfo, ContentInfo&gt; split =
- *                 payload.partition(item -&gt; item.getUri() != null);
+ *                 ContentInfoCompat.partition(payload, item -&gt; item.getUri() != null);
  *         ContentInfo uriContent = split.first;
  *         ContentInfo remaining = split.second;
  *         if (uriContent != null) {
@@ -72,8 +72,7 @@
      * handling. For example, an implementation may provide handling for content URIs (to provide
      * support for inserting images, etc) and delegate the processing of text to the platform to
      * preserve the common behavior for inserting text. See the class javadoc for a sample
-     * implementation and see {@link ContentInfo#partition} for a convenient way to split the
-     * passed-in content.
+     * implementation.
      *
      * <p>If implementing handling for text: if the view has a selection, the selection should
      * be overwritten by the passed-in content; if there's no selection, the passed-in content
diff --git a/core/java/android/view/ScrollCaptureTargetResolver.java b/core/java/android/view/ScrollCaptureTargetResolver.java
index 5106534..e4316bb 100644
--- a/core/java/android/view/ScrollCaptureTargetResolver.java
+++ b/core/java/android/view/ScrollCaptureTargetResolver.java
@@ -182,9 +182,8 @@
         }
         mResult = chooseTarget(mResult, target);
         boolean finish = mPendingBoundsRequests == 0
-                || SystemClock.elapsedRealtime() >= mDeadlineMillis;
+                || SystemClock.uptimeMillis() >= mDeadlineMillis;
         if (finish) {
-            System.err.println("We think we're done, or timed out");
             mPendingBoundsRequests = 0;
             mWhenComplete.accept(mResult);
             synchronized (mLock) {
@@ -233,7 +232,7 @@
         for (ScrollCaptureTarget target : mTargets) {
             queryTarget(target);
         }
-        mDeadlineMillis = SystemClock.elapsedRealtime() + mTimeLimitMillis;
+        mDeadlineMillis = SystemClock.uptimeMillis() + mTimeLimitMillis;
         mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
     }
 
@@ -275,7 +274,7 @@
         mHandler.removeCallbacks(mTimeoutRunnable);
 
         boolean doneOrTimedOut = mPendingBoundsRequests == 0
-                || SystemClock.elapsedRealtime() >= mDeadlineMillis;
+                || SystemClock.uptimeMillis() >= mDeadlineMillis;
 
         final View containingView = target.getContainingView();
         if (!nullOrEmpty(scrollBounds) && containingView.isAggregatedVisible()) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d7ee6ad..f642d75 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -26,6 +26,7 @@
 import static android.view.SurfaceControlProto.NAME;
 
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -54,12 +55,15 @@
 import android.view.Surface.OutOfResourcesException;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.VirtualRefBasePtr;
 
 import dalvik.system.CloseGuard;
 
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.Closeable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -224,6 +228,11 @@
                                                       IBinder focusedToken, int displayId);
     private static native void nativeSetFrameTimelineVsync(long transactionObj,
             long frameTimelineVsyncId);
+    private static native void nativeAddJankDataListener(long nativeListener,
+            long nativeSurfaceControl);
+    private static native void nativeRemoveJankDataListener(long nativeListener);
+    private static native long nativeCreateJankDataListenerWrapper(OnJankDataListener listener);
+    private static native int nativeGetGPUContextPriority();
 
     @Nullable
     @GuardedBy("mLock")
@@ -249,6 +258,73 @@
         void onReparent(@NonNull Transaction transaction, @Nullable SurfaceControl parent);
     }
 
+    /**
+     * Jank information to be fed back via {@link OnJankDataListener}.
+     * @hide
+     */
+    public static class JankData {
+
+        /** @hide */
+        @IntDef(flag = true, value = {JANK_NONE,
+                JANK_DISPLAY,
+                JANK_SURFACEFLINGER_DEADLINE_MISSED,
+                JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED,
+                JANK_APP_DEADLINE_MISSED,
+                JANK_PREDICTION_EXPIRED,
+                JANK_SURFACEFLINGER_EARLY_LATCH})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface JankType {}
+
+        // Needs to be kept in sync with frameworks/native/libs/gui/include/gui/JankInfo.h
+
+        // No Jank
+        public static final int JANK_NONE = 0x0;
+
+        // Jank not related to SurfaceFlinger or the App
+        public static final int JANK_DISPLAY = 0x1;
+        // SF took too long on the CPU
+        public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2;
+        // SF took too long on the GPU
+        public static final int JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED = 0x4;
+        // Either App or GPU took too long on the frame
+        public static final int JANK_APP_DEADLINE_MISSED = 0x8;
+        // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a
+        // jank
+        // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame.
+        public static final int JANK_PREDICTION_EXPIRED = 0x10;
+        // Latching a buffer early might cause an early present of the frame
+        public static final int JANK_SURFACEFLINGER_EARLY_LATCH = 0x20;
+
+        public JankData(long frameVsyncId, @JankType int jankType) {
+            this.frameVsyncId = frameVsyncId;
+            this.jankType = jankType;
+        }
+
+        public final long frameVsyncId;
+        public final @JankType int jankType;
+    }
+
+    /**
+     * Listener interface to be informed about SurfaceFlinger's jank classification for a specific
+     * surface.
+     *
+     * @see JankData
+     * @see #addJankDataListener
+     * @hide
+     */
+    public static abstract class OnJankDataListener {
+        private final VirtualRefBasePtr mNativePtr;
+
+        public OnJankDataListener() {
+            mNativePtr = new VirtualRefBasePtr(nativeCreateJankDataListenerWrapper(this));
+        }
+
+        /**
+         * Called when new jank classifications are available.
+         */
+        public abstract void onJankDataAvailable(JankData[] jankStats);
+    }
+
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
 
@@ -1526,97 +1602,6 @@
     /**
      * @hide
      */
-    public void deferTransactionUntil(SurfaceControl barrier, long frame) {
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.deferTransactionUntil(this, barrier, frame);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void reparentChildren(SurfaceControl newParent) {
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.reparentChildren(this, newParent);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void detachChildren() {
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.detachChildren(this);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setLayer(int zorder) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setLayer(this, zorder);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setPosition(float x, float y) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setPosition(this, x, y);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setBufferSize(int w, int h) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setBufferSize(this, w, h);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void hide() {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.hide(this);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void show() {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.show(this);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setTransparentRegionHint(Region region) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setTransparentRegionHint(this, region);
-        }
-    }
-
-    /**
-     * @hide
-     */
     public boolean clearContentFrameStats() {
         checkNotReleased();
         return nativeClearContentFrameStats(mNativeObject);
@@ -1647,87 +1632,6 @@
     /**
      * @hide
      */
-    public void setAlpha(float alpha) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setAlpha(this, alpha);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setBackgroundBlurRadius(int blur) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setBackgroundBlurRadius(this, blur);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setMatrix(this, dsdx, dtdx, dtdy, dsdy);
-        }
-    }
-
-    /**
-     * Sets the Surface to be color space agnostic. If a surface is color space agnostic,
-     * the color can be interpreted in any color space.
-     * @param agnostic A boolean to indicate whether the surface is color space agnostic
-     * @hide
-     */
-    public void setColorSpaceAgnostic(boolean agnostic) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setColorSpaceAgnostic(this, agnostic);
-        }
-    }
-
-    /**
-     * Bounds the surface and its children to the bounds specified. Size of the surface will be
-     * ignored and only the crop and buffer size will be used to determine the bounds of the
-     * surface. If no crop is specified and the surface has no buffer, the surface bounds is only
-     * constrained by the size of its parent bounds.
-     *
-     * @param crop Bounds of the crop to apply.
-     * @hide
-     */
-    public void setWindowCrop(Rect crop) {
-        checkNotReleased();
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setWindowCrop(this, crop);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setOpaque(boolean isOpaque) {
-        checkNotReleased();
-
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setOpaque(this, isOpaque);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setSecure(boolean isSecure) {
-        checkNotReleased();
-
-        synchronized (SurfaceControl.class) {
-            sGlobalTransaction.setSecure(this, isSecure);
-        }
-    }
-
-    /**
-     * @hide
-     */
     public int getWidth() {
         synchronized (mLock) {
             return mWidth;
@@ -2519,7 +2423,31 @@
         nativeSetGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
     }
 
-     /**
+    /**
+     * Adds a callback to be informed about SF's jank classification for a specific surface.
+     * @hide
+     */
+    public static void addJankDataListener(OnJankDataListener listener, SurfaceControl surface) {
+        nativeAddJankDataListener(listener.mNativePtr.get(), surface.mNativeObject);
+    }
+
+    /**
+     * Removes a jank callback previously added with {@link #addJankDataListener}
+     * @hide
+     */
+    public static void removeJankDataListener(OnJankDataListener listener) {
+        nativeRemoveJankDataListener(listener.mNativePtr.get());
+    }
+
+    /**
+     * Return GPU Context priority that is set in SurfaceFlinger's Render Engine.
+     * @hide
+     */
+    public static int getGPUContextPriority() {
+        return nativeGetGPUContextPriority();
+    }
+
+    /**
      * An atomic set of changes to a set of SurfaceControl.
      */
     public static class Transaction implements Closeable, Parcelable {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 15adc5a..b5185ae 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -232,6 +232,7 @@
     private final Matrix mTmpMatrix = new Matrix();
 
     SurfaceControlViewHost.SurfacePackage mSurfacePackage;
+    private final boolean mUseBlastSync = false;
 
     /**
      * Returns {@code true} if buffers should be submitted via blast
@@ -239,7 +240,7 @@
     private static boolean useBlastAdapter(Context context) {
         ContentResolver contentResolver = context.getContentResolver();
         return Settings.Global.getInt(contentResolver,
-                Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 0 /* default */) == 1;
+                Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 1 /* default */) == 1;
     }
 
     private final boolean mUseBlastAdapter;
@@ -1922,6 +1923,6 @@
     }
 
     private boolean useBLASTSync(ViewRootImpl viewRoot) {
-        return viewRoot.useBLAST() && mUseBlastAdapter;
+        return viewRoot.useBLAST() && mUseBlastAdapter && mUseBlastSync;
     }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 29cc4b5..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
@@ -29023,6 +29040,33 @@
         boolean mUse32BitDrawingCache;
 
         /**
+         * For windows that are full-screen but using insets to layout inside
+         * of the screen decorations, these are the current insets for the
+         * content of the window.
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
+        final Rect mContentInsets = new Rect();
+
+        /**
+         * For windows that are full-screen but using insets to layout inside
+         * of the screen decorations, these are the current insets for the
+         * actual visible parts of the window.
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
+        final Rect mVisibleInsets = new Rect();
+
+        /**
+         * For windows that are full-screen but using insets to layout inside
+         * of the screen decorations, these are the current insets for the
+         * stable system windows.
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+                publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
+        final Rect mStableInsets = new Rect();
+
+        /**
          * Current caption insets to the display coordinate.
          */
         final Rect mCaptionInsets = new Rect();
@@ -29415,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 2d633cb..52ce5e7 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;
@@ -582,9 +581,6 @@
             = new ViewTreeObserver.InternalInsetsInfo();
 
     private WindowInsets mLastWindowInsets;
-    private final Rect mSystemInsetsCache = new Rect();
-    private final Rect mVisibleInsetsCache = new Rect();
-    private final Rect mStableInsetsCache = new Rect();
 
     // Insets types hidden by legacy window flags or system UI flags.
     private @InsetsType int mTypesHiddenByFlags = 0;
@@ -2341,9 +2337,9 @@
                     (mWindowAttributes.systemUiVisibility
                             | mWindowAttributes.subtreeSystemUiVisibility));
 
-            mSystemInsetsCache.set(mLastWindowInsets.getSystemWindowInsets().toRect());
-            mStableInsetsCache.set(mLastWindowInsets.getStableInsets().toRect());
-            mVisibleInsetsCache.set(mInsetsController.calculateVisibleInsets(
+            mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect());
+            mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect());
+            mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets(
                     mWindowAttributes.softInputMode));
         }
         return mLastWindowInsets;
@@ -2846,7 +2842,7 @@
                                         && mWinFrame.height() == mPendingBackDropFrame.height();
                         // TODO: Need cutout?
                         startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame,
-                                mSystemInsetsCache, mStableInsetsCache, mResizeMode);
+                                mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mResizeMode);
                     } else {
                         // We shouldn't come here, but if we come we should end the resize.
                         endDragResizing();
@@ -4478,8 +4474,8 @@
     }
 
     boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
-        final Rect ci = mSystemInsetsCache;
-        final Rect vi = mVisibleInsetsCache;
+        final Rect ci = mAttachInfo.mContentInsets;
+        final Rect vi = mAttachInfo.mVisibleInsets;
         int scrollY = 0;
         boolean handled = false;
 
@@ -4671,7 +4667,12 @@
         if (mPointerCapture == enabled) {
             return;
         }
-        InputManager.getInstance().requestPointerCapture(mAttachInfo.mWindowToken, enabled);
+        final IBinder inputToken = getInputToken();
+        if (inputToken == null) {
+            Log.e(mTag, "No input channel to request Pointer Capture.");
+            return;
+        }
+        InputManager.getInstance().requestPointerCapture(inputToken, enabled);
     }
 
     private void handlePointerCaptureChanged(boolean hasCapture) {
@@ -7575,7 +7576,7 @@
         // XXX This is really broken, and probably all needs to be done
         // in the window manager, and we need to know more about whether
         // we want the area behind or in front of the IME.
-        final Rect insets = mVisibleInsetsCache;
+        final Rect insets = mAttachInfo.mVisibleInsets;
         outFrame.left += insets.left;
         outFrame.top += insets.top;
         outFrame.right -= insets.right;
@@ -7690,12 +7691,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="
@@ -7710,6 +7717,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);
 
@@ -7913,7 +7926,7 @@
             synchronized (mWindowCallbacks) {
                 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
                     mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
-                            mVisibleInsetsCache, mStableInsetsCache);
+                            mAttachInfo.mVisibleInsets, mAttachInfo.mStableInsets);
                 }
             }
         }
@@ -8373,6 +8386,11 @@
         }
 
         @Override
+        public void onPointerCaptureEvent(boolean pointerCaptureEnabled) {
+            dispatchPointerCaptureChanged(pointerCaptureEnabled);
+        }
+
+        @Override
         public void dispose() {
             unscheduleConsumeBatchedInput();
             super.dispose();
@@ -8647,7 +8665,7 @@
                 MSG_REQUEST_KEYBOARD_SHORTCUTS, deviceId, 0, receiver).sendToTarget();
     }
 
-    public void dispatchPointerCaptureChanged(boolean on) {
+    private void dispatchPointerCaptureChanged(boolean on) {
         final int what = MSG_POINTER_CAPTURE_CHANGED;
         mHandler.removeMessages(what);
         Message msg = mHandler.obtainMessage(what);
@@ -9420,14 +9438,6 @@
         }
 
         @Override
-        public void dispatchPointerCaptureChanged(boolean hasCapture) {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.dispatchPointerCaptureChanged(hasCapture);
-            }
-        }
-
-        @Override
         public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 13d9eb9..af18293 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,7 +16,11 @@
 
 package android.view;
 
+import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
@@ -24,6 +28,7 @@
 import android.annotation.LayoutRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -991,6 +996,26 @@
     }
 
     /**
+     * Prevent non-system overlay windows from being drawn on top of this window.
+     *
+     * @param hide whether non-system overlay windows should be hidden.
+     */
+    @RequiresPermission(HIDE_OVERLAY_WINDOWS)
+    public final void setHideOverlayWindows(boolean hide) {
+        // This permission check is here to throw early and let the developer know that they need
+        // to hold HIDE_OVERLAY_WINDOWS for the flag to have any effect. The WM verifies that the
+        // owner of the window has the permission before applying the flag, but this is done
+        // asynchronously.
+        if (mContext.checkSelfPermission(HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != PERMISSION_GRANTED
+                && mContext.checkSelfPermission(HIDE_OVERLAY_WINDOWS) != PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Permission denial: setHideOverlayWindows: HIDE_OVERLAY_WINDOWS");
+        }
+        setPrivateFlags(hide ? SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS : 0,
+                SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+    }
+
+    /**
      * Take ownership of this window's surface.  The window's view hierarchy
      * will no longer draw into the surface, though it will otherwise continue
      * to operate (such as for receiving input events).  The given SurfaceHolder
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b9afbc9..6d88d63 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -343,23 +343,48 @@
 
     /** @hide */
     int TRANSIT_NONE = 0;
-    /** @hide */
+    /**
+     * A window that didn't exist before has been created and made visible.
+     * @hide
+     */
     int TRANSIT_OPEN = 1;
-    /** @hide */
+    /**
+     * A window that was visible no-longer exists (was finished or destroyed).
+     * @hide
+     */
     int TRANSIT_CLOSE = 2;
-    /** @hide */
+    /**
+     * A window that already existed but was not visible is made visible.
+     * @hide
+     */
     int TRANSIT_TO_FRONT = 3;
-    /** @hide */
+    /**
+     * A window that was visible is made invisible but still exists.
+     * @hide
+     */
     int TRANSIT_TO_BACK = 4;
     /** @hide */
     int TRANSIT_RELAUNCH = 5;
-    /** @hide */
-    int TRANSIT_CHANGE_WINDOWING_MODE = 6;
-    /** @hide */
+    /**
+     * A window is visible before and after but changes in some way (eg. it resizes or changes
+     * windowing-mode).
+     * @hide
+     */
+    int TRANSIT_CHANGE = 6;
+    /**
+     * The keyguard was visible and has been dismissed.
+     * @hide
+     */
     int TRANSIT_KEYGUARD_GOING_AWAY = 7;
-    /** @hide */
+    /**
+     * A window is appearing above a locked keyguard.
+     * @hide
+     */
     int TRANSIT_KEYGUARD_OCCLUDE = 8;
-    /** @hide */
+    /**
+     * A window is made invisible revealing a locked keyguard.
+     * @hide
+     */
     int TRANSIT_KEYGUARD_UNOCCLUDE = 9;
 
     /**
@@ -372,7 +397,7 @@
             TRANSIT_TO_FRONT,
             TRANSIT_TO_BACK,
             TRANSIT_RELAUNCH,
-            TRANSIT_CHANGE_WINDOWING_MODE,
+            TRANSIT_CHANGE,
             TRANSIT_KEYGUARD_GOING_AWAY,
             TRANSIT_KEYGUARD_OCCLUDE,
             TRANSIT_KEYGUARD_UNOCCLUDE,
@@ -418,6 +443,12 @@
     int TRANSIT_FLAG_OPEN_BEHIND = 0x20;
 
     /**
+     * Transition flag: The keyguard is locked throughout the whole transition.
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_LOCKED = 0x40;
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
@@ -426,7 +457,8 @@
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION,
             TRANSIT_FLAG_APP_CRASHED,
-            TRANSIT_FLAG_OPEN_BEHIND
+            TRANSIT_FLAG_OPEN_BEHIND,
+            TRANSIT_FLAG_KEYGUARD_LOCKED
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionFlags {}
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/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index f63749b..aff0b35 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -23,7 +23,9 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
@@ -123,6 +125,12 @@
 
     private Message mSameThreadMessage;
 
+    private int mInteractionIdWaitingForPrefetchResult;
+    private int mConnectionIdWaitingForPrefetchResult;
+    private String[] mPackageNamesForNextPrefetchResult;
+    private final Handler mMainHandler;
+    private Runnable mPrefetchResultRunnable;
+
     /**
      * @return The client for the current thread.
      */
@@ -197,6 +205,7 @@
 
     private AccessibilityInteractionClient() {
         /* reducing constructor visibility */
+        mMainHandler = new Handler(Looper.getMainLooper());
     }
 
     /**
@@ -451,16 +460,16 @@
                     Binder.restoreCallingIdentity(identityToken);
                 }
                 if (packageNames != null) {
-                    List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
-                            interactionId);
-                    finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
-                            bypassCache, packageNames);
-                    if (infos != null && !infos.isEmpty()) {
-                        for (int i = 1; i < infos.size(); i++) {
-                            infos.get(i).recycle();
-                        }
-                        return infos.get(0);
+                    AccessibilityNodeInfo info =
+                            getFindAccessibilityNodeInfoResultAndClear(interactionId);
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_MASK) != 0
+                            && info != null) {
+                        setInteractionWaitingForPrefetchResult(interactionId, connectionId,
+                                packageNames);
                     }
+                    finalizeAndCacheAccessibilityNodeInfo(info, connectionId,
+                            bypassCache, packageNames);
+                    return info;
                 }
             } else {
                 if (DEBUG) {
@@ -474,6 +483,15 @@
         return null;
     }
 
+    private void setInteractionWaitingForPrefetchResult(int interactionId, int connectionId,
+            String[] packageNames) {
+        synchronized (mInstanceLock) {
+            mInteractionIdWaitingForPrefetchResult = interactionId;
+            mConnectionIdWaitingForPrefetchResult = connectionId;
+            mPackageNamesForNextPrefetchResult = packageNames;
+        }
+    }
+
     private static String idToString(int accessibilityWindowId, long accessibilityNodeId) {
         return accessibilityWindowId + "/"
                 + AccessibilityNodeInfo.idToString(accessibilityNodeId);
@@ -829,6 +847,26 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos,
+                                                       int interactionId) {
+        synchronized (mInstanceLock) {
+            if (mPrefetchResultRunnable != null) {
+                mMainHandler.removeCallbacks(mPrefetchResultRunnable);
+                mPrefetchResultRunnable = null;
+            }
+            if (!infos.isEmpty() && mInteractionIdWaitingForPrefetchResult == interactionId) {
+                mPrefetchResultRunnable = () -> finalizeAndCacheAccessibilityNodeInfos(
+                        infos, mConnectionIdWaitingForPrefetchResult, false,
+                        mPackageNamesForNextPrefetchResult);
+                mMainHandler.post(mPrefetchResultRunnable);
+            }
+        }
+    }
+
+    /**
      * Gets the result of a request to perform an accessibility action.
      *
      * @param interactionId The interaction id to match the result with the request.
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index 049bb31..231e75a 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -47,6 +47,15 @@
         int interactionId);
 
     /**
+     * Sets the result of a prefetch request that returns {@link AccessibilityNodeInfo}s.
+     *
+     * @param root The {@link AccessibilityNodeInfo} for which the prefetching is based off of.
+     * @param infos The result {@link AccessibilityNodeInfo}s.
+     */
+    void setPrefetchAccessibilityNodeInfoResult(
+        in List<AccessibilityNodeInfo> infos, int interactionId);
+
+    /**
      * Sets the result of a request to perform an accessibility action.
      *
      * @param Whether the action was performed.
diff --git a/core/java/android/view/accessibility/OWNERS b/core/java/android/view/accessibility/OWNERS
index c6f42f7..93b5a2e 100644
--- a/core/java/android/view/accessibility/OWNERS
+++ b/core/java/android/view/accessibility/OWNERS
@@ -1,4 +1,11 @@
-svetoslavganov@google.com
+# Bug component: 44214
+
+romainguy@google.com
+alanv@google.com
+adamp@google.com
+aurimas@google.com
+nduca@google.com
+sumir@google.com
+ogunwale@google.com
+jjaggi@google.com
 pweaver@google.com
-rhedjao@google.com
-qasid@google.com
diff --git a/core/java/android/view/animation/OWNERS b/core/java/android/view/animation/OWNERS
new file mode 100644
index 0000000..9b8f4d9
--- /dev/null
+++ b/core/java/android/view/animation/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 25700
+
+romainguy@google.com
+tianliu@google.com
+alanv@google.com
+adamp@google.com
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
new file mode 100644
index 0000000..a088632
--- /dev/null
+++ b/core/java/android/view/autofill/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 351486
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 16fd383..3c18b6b 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -43,6 +43,7 @@
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
+import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.TimeUtils;
@@ -334,15 +335,22 @@
         if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) {
             final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
 
-            // TODO(b/121045053): check if flags match
+            // We merge two consecutive text change event, unless one of them clears the text.
             if (lastEvent.getType() == TYPE_VIEW_TEXT_CHANGED
                     && lastEvent.getId().equals(event.getId())) {
-                if (sVerbose) {
+                boolean bothNonEmpty = !TextUtils.isEmpty(lastEvent.getText())
+                        && !TextUtils.isEmpty(event.getText());
+                boolean equalContent = TextUtils.equals(lastEvent.getText(), event.getText());
+                if (equalContent) {
+                    addEvent = false;
+                } else if (bothNonEmpty) {
+                    lastEvent.mergeEvent(event);
+                    addEvent = false;
+                }
+                if (!addEvent && sVerbose) {
                     Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
                             + getSanitizedString(event.getText()));
                 }
-                lastEvent.mergeEvent(event);
-                addEvent = false;
             }
         }
 
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
new file mode 100644
index 0000000..6337327
--- /dev/null
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 544200
+
+joannechung@google.com
+adamhe@google.com
+tymtsai@google.com
+lpeter@google.com
+augale@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 7dbf693..1cf25a7 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -28,6 +28,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.content.res.Configuration;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.LocaleList;
@@ -293,6 +294,13 @@
     public static final int IME_FLAG_FORCE_ASCII = 0x80000000;
 
     /**
+     * Flag of {@link #internalImeOptions}: flag is set when app window containing this
+     * {@link EditorInfo} is using {@link Configuration#ORIENTATION_PORTRAIT} mode.
+     * @hide
+     */
+    public static final int IME_FLAG_APP_WINDOW_PORTRAIT = 0x80000000;
+
+    /**
      * Generic unspecified type for {@link #imeOptions}.
      */
     public static final int IME_NULL = 0x00000000;
@@ -312,6 +320,7 @@
      *                               1 1 IME_ACTION_NEXT
      *                               11  IME_ACTION_DONE
      *                               111 IME_ACTION_PREVIOUS
+     *          1                        IME_FLAG_APP_WINDOW_PORTRAIT
      *         1                         IME_FLAG_NO_PERSONALIZED_LEARNING
      *        1                          IME_FLAG_NO_FULLSCREEN
      *       1                           IME_FLAG_NAVIGATE_PREVIOUS
@@ -343,6 +352,20 @@
     public String privateImeOptions = null;
 
     /**
+     * Masks for {@link internalImeOptions}
+     *
+     * <pre>
+     *  1                                IME_FLAG_APP_WINDOW_PORTRAIT
+     * |-------|-------|-------|-------|</pre>
+     */
+
+    /**
+     * Same as {@link android.R.attr#imeOptions} but for framework's internal-use only.
+     * @hide
+     */
+    public int internalImeOptions = IME_NULL;
+
+    /**
      * In some cases an IME may be able to display an arbitrary label for
      * a command the user can perform, which you can specify here. This is
      * typically used as the label for the action to use in-line as a replacement
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 14b5d7c..8c81143 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -858,6 +858,20 @@
     boolean reportFullscreenMode(boolean enabled);
 
     /**
+     * Have the editor perform spell checking around the current selection.
+     *
+     * <p>The editor can ignore this method call if it does not support spell checking.
+     *
+     * @return For editor authors, the return value will always be ignored. For IME authors, this
+     *         method returns true if the spell check request was sent (whether or not the
+     *         associated editor supports spell checking), false if the input connection is no
+     *         longer valid.
+     */
+    default boolean performSpellCheck() {
+        return false;
+    }
+
+    /**
      * API to send private commands from an input method to its
      * connected editor. This can be used to provide domain-specific
      * features that are only known between certain input methods and
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 77956d1..ca85348 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -287,6 +287,15 @@
      * @throws NullPointerException if the target is {@code null}.
      */
     @Override
+    public boolean performSpellCheck() {
+        return mTarget.performSpellCheck();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
+    @Override
     public boolean performPrivateCommand(String action, Bundle data) {
         return mTarget.performPrivateCommand(action, data);
     }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index eaf72dc..6526b8c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1747,8 +1747,14 @@
 
             try {
                 Log.d(TAG, "showSoftInput() view=" + view + " flags=" + flags);
-                return mService.showSoftInput(
-                        mClient, view.getWindowToken(), flags, resultReceiver);
+                final Completable.Boolean value = Completable.createBoolean();
+                mService.showSoftInput(
+                        mClient,
+                        view.getWindowToken(),
+                        flags,
+                        resultReceiver,
+                        ResultCallbacks.of(value));
+                return Completable.getResult(value);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1775,8 +1781,14 @@
                     Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
                     return;
                 }
+                final Completable.Boolean value = Completable.createBoolean();
                 mService.showSoftInput(
-                        mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
+                        mClient,
+                        mCurRootView.getView().getWindowToken(),
+                        flags,
+                        resultReceiver,
+                        ResultCallbacks.of(value));
+                Completable.getResult(value); // ignore the result
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1849,7 +1861,10 @@
             }
 
             try {
-                return mService.hideSoftInput(mClient, windowToken, flags, resultReceiver);
+                final Completable.Boolean value = Completable.createBoolean();
+                mService.hideSoftInput(
+                        mClient, windowToken, flags, resultReceiver, ResultCallbacks.of(value));
+                return Completable.getResult(value);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -2184,8 +2199,14 @@
                 return;
             }
             try {
+                final Completable.Boolean value = Completable.createBoolean();
                 mService.hideSoftInput(
-                        mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null);
+                        mClient,
+                        mCurRootView.getView().getWindowToken(),
+                        HIDE_NOT_ALWAYS,
+                        null,
+                        ResultCallbacks.of(value));
+                Completable.getResult(value); // ignore the result
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -2920,7 +2941,9 @@
     @TestApi
     public boolean isInputMethodPickerShown() {
         try {
-            return mService.isInputMethodPickerShownForTest();
+            final Completable.Boolean value = Completable.createBoolean();
+            mService.isInputMethodPickerShownForTest(ResultCallbacks.of(value));
+            return Completable.getResult(value);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS
index 244cc30..e6a04da 100644
--- a/core/java/android/view/inputmethod/OWNERS
+++ b/core/java/android/view/inputmethod/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 34867
 set noparent
 
-include ../../../../../services/core/java/com/android/server/inputmethod/OWNERS
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index c2827cc..705f4b3 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -1,3 +1,6 @@
+romainguy@google.com
 alanv@google.com
+adamp@google.com
 aurimas@google.com
-emberrose@google.com
+nduca@google.com
+sumir@google.com
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index be4fbaa..ac80d9f 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -1,14 +1,8 @@
 # Bug component: 709498
 
+mns@google.com
 toki@google.com
-tonymak@google.com
-zilka@google.com
-jalt@google.com
-joannechung@google.com
+svetoslavganov@android.com
 svetoslavganov@google.com
-eugeniom@google.com
-samsellem@google.com
-adamhe@google.com
 augale@google.com
-lpeter@google.com
-tymtsai@google.com
\ No newline at end of file
+joannechung@google.com
diff --git a/core/java/android/view/textclassifier/intent/OWNERS b/core/java/android/view/textclassifier/intent/OWNERS
new file mode 100644
index 0000000..ac80d9f
--- /dev/null
+++ b/core/java/android/view/textclassifier/intent/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 709498
+
+mns@google.com
+toki@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+augale@google.com
+joannechung@google.com
diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS
new file mode 100644
index 0000000..ac80d9f
--- /dev/null
+++ b/core/java/android/view/textclassifier/logging/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 709498
+
+mns@google.com
+toki@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+augale@google.com
+joannechung@google.com
diff --git a/core/java/android/view/textservice/OWNERS b/core/java/android/view/textservice/OWNERS
new file mode 100644
index 0000000..582be8d
--- /dev/null
+++ b/core/java/android/view/textservice/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include ../inputmethod/OWNERS
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
index ca529f6..1301c49 100644
--- a/core/java/android/view/textservice/SuggestionsInfo.java
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -53,6 +53,16 @@
      */
     public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 0x0008;
 
+    /**
+     * Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that the text service has an alternative way to
+     * show UI for the list of correction suggestions to the user. When this flag is set, the
+     * receiver of the result suggestions should mark the erroneous part of the text with a text
+     * signifier (for example, underline), but should not show any UI for the list of correction
+     * suggestions to the user (for example, in a popup window).
+     */
+    public static final int RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS = 0x0010;
+
     private final int mSuggestionsAttributes;
     private final String[] mSuggestions;
     private final boolean mSuggestionsAvailable;
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 5c79d21..718076b 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1 +1,11 @@
+# Bug component: 25700
+
+romainguy@google.com
+alanv@google.com
+adamp@google.com
+aurimas@google.com
+siyamed@google.com
+
 per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
+
+per-file SpellChecker.java = file:../view/inputmethod/OWNERS
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 0611bea..b06fa1a 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -215,6 +215,27 @@
         spellCheck();
     }
 
+    void onPerformSpellCheck() {
+        final int selectionStart = mTextView.getSelectionStart();
+        final int selectionEnd = mTextView.getSelectionEnd();
+        final int selectionRangeStart;
+        final int selectionRangeEnd;
+        if (selectionStart < selectionEnd) {
+            selectionRangeStart = selectionStart;
+            selectionRangeEnd = selectionEnd;
+        } else {
+            selectionRangeStart = selectionEnd;
+            selectionRangeEnd = selectionStart;
+        }
+        // Expand the range so that it (hopefully) includes the current sentence.
+        final int start = Math.max(0, selectionRangeStart - MIN_SENTENCE_LENGTH);
+        final int end = Math.min(mTextView.length(), selectionRangeEnd + MIN_SENTENCE_LENGTH);
+        if (DBG) {
+            Log.d(TAG, "performSpellCheckAroundSelection: " + start + ", " + end);
+        }
+        spellCheck(start, end);
+    }
+
     public void spellCheck(int start, int end) {
         if (DBG) {
             Log.d(TAG, "Start spell-checking: " + start + ", " + end);
@@ -456,6 +477,8 @@
         mTextView.postDelayed(mSpellRunnable, SPELL_PAUSE_DURATION);
     }
 
+    // When calling this method, RESULT_ATTR_LOOKS_LIKE_TYPO or RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR
+    // (or both) should be set in suggestionsInfo.
     private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo,
             SpellCheckSpan spellCheckSpan, int offset, int length) {
         final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
@@ -485,7 +508,10 @@
         }
 
         final int suggestionsAttrs = suggestionsInfo.getSuggestionsAttributes();
-        int flags = SuggestionSpan.FLAG_EASY_CORRECT;
+        int flags = 0;
+        if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS) == 0) {
+            flags |= SuggestionSpan.FLAG_EASY_CORRECT;
+        }
         if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) != 0) {
             flags |= SuggestionSpan.FLAG_MISSPELLED;
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 02a9300..977a0e8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.ContentInfo.FLAG_CONVERT_TO_PLAIN_TEXT;
 import static android.view.ContentInfo.SOURCE_AUTOFILL;
 import static android.view.ContentInfo.SOURCE_CLIPBOARD;
@@ -8738,6 +8739,9 @@
                     outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
                 }
             }
+            if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
+                outAttrs.internalImeOptions |= EditorInfo.IME_FLAG_APP_WINDOW_PORTRAIT;
+            }
             if (isMultilineInputType(outAttrs.inputType)) {
                 // Multi-line text editors should always show an enter key.
                 outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
@@ -8913,6 +8917,13 @@
         // intentionally empty
     }
 
+    /** @hide */
+    public void onPerformSpellCheck() {
+        if (mEditor != null && mEditor.mSpellChecker != null) {
+            mEditor.mSpellChecker.onPerformSpellCheck();
+        }
+    }
+
     /**
      * Called by the framework in response to a private command from the
      * current method, provided by it calling
@@ -13736,8 +13747,12 @@
      * custom behavior should configure a listener via {@link #setOnReceiveContentListener}.
      *
      * <p>For non-editable TextViews the default behavior is a no-op (returns the passed-in
-     * content without acting on it). For editable TextViews the default behavior coerces all
-     * content to text and inserts into the view.
+     * content without acting on it).
+     *
+     * <p>For editable TextViews the default behavior is to insert text into the view, coercing
+     * non-text content to text as needed. The MIME types "text/plain" and "text/html" have
+     * well-defined behavior for this, while other MIME types have reasonable fallback behavior
+     * (see {@link ClipData.Item#coerceToStyledText}).
      *
      * @param payload The content to insert and related metadata.
      *
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 1ac188c..1254647 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.
@@ -145,15 +164,19 @@
     }
 
     /**
-     * Creates a persistent task display area. It will be added to be the top most task display area
-     * in the root.
+     * Creates a persistent {@link com.android.server.wm.TaskDisplayArea}.
      *
      * The new created TDA is organized by the organizer, and will be deleted on calling
      * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}.
      *
-     * @param displayId the display to create the new task display area in.
-     * @param rootFeatureId the root display area to create the new task display area in. Caller can
-     *                      use {@link #FEATURE_ROOT} as the root of the logical display.
+     * @param displayId the display to create the new TDA in.
+     * @param parentFeatureId the parent to create the new TDA in. If it is a
+     *                        {@link com.android.server.wm.RootDisplayArea}, the new TDA will be
+     *                        placed as the topmost TDA. If it is another TDA, the new TDA will be
+     *                        placed as the topmost child.
+     *                        Caller can use {@link #FEATURE_ROOT} as the root of the logical
+     *                        display, or {@link #FEATURE_DEFAULT_TASK_CONTAINER} as the default
+     *                        TDA.
      * @param name the name for the new task display area.
      * @return the new created task display area.
      * @throws IllegalArgumentException if failed to create a new task display area.
@@ -162,11 +185,11 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
     @CallSuper
     @NonNull
-    public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int rootFeatureId,
+    public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int parentFeatureId,
             @NonNull String name) {
         try {
             return getController().createTaskDisplayArea(
-                    mInterface, displayId, rootFeatureId, name);
+                    mInterface, displayId, parentFeatureId, name);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -208,17 +231,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/android/window/IDisplayAreaOrganizerController.aidl b/core/java/android/window/IDisplayAreaOrganizerController.aidl
index 26fa434..6c097bb 100644
--- a/core/java/android/window/IDisplayAreaOrganizerController.aidl
+++ b/core/java/android/window/IDisplayAreaOrganizerController.aidl
@@ -40,21 +40,25 @@
     void unregisterOrganizer(in IDisplayAreaOrganizer organizer);
 
     /**
-     * Creates a persistent task display area. It will be added to be the top most task display area
-     * in the root.
+     * Creates a persistent {@link com.android.server.wm.TaskDisplayArea}.
      *
      * The new created TDA is organized by the organizer, and will be deleted on calling
      * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}.
      *
-     * @param displayId the display to create the new task display area in.
-     * @param rootFeatureId the root display area to create the new task display area in. Caller can
-     *                      use {@link #FEATURE_ROOT} as the root of the logical display.
+     * @param displayId the display to create the new TDA in.
+     * @param parentFeatureId the parent to create the new TDA in. If it is a
+     *                        {@link com.android.server.wm.RootDisplayArea}, the new TDA will be
+     *                        placed as the topmost TDA. If it is another TDA, the new TDA will be
+     *                        placed as the topmost child.
+     *                        Caller can use {@link #FEATURE_ROOT} as the root of the logical
+     *                        display, or {@link #FEATURE_DEFAULT_TASK_CONTAINER} as the default
+     *                        TDA.
      * @param name the name for the new task display area.
      * @return the new created task display area.
      * @throws IllegalArgumentException if failed to create a new task display area.
      */
     DisplayAreaAppearedInfo createTaskDisplayArea(in IDisplayAreaOrganizer organizer, int displayId,
-        int rootFeatureId, in String name);
+        int parentFeatureId, in String name);
 
     /**
      * Deletes a persistent task display area. It can only be one that created by an organizer.
diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl
index b503184..88b2257 100644
--- a/core/java/android/window/ITaskOrganizer.aidl
+++ b/core/java/android/window/ITaskOrganizer.aidl
@@ -18,6 +18,7 @@
 
 import android.view.SurfaceControl;
 import android.app.ActivityManager;
+import android.window.StartingWindowInfo;
 import android.window.WindowContainerToken;
 
 /**
@@ -30,15 +31,15 @@
      * application is starting. The client is responsible to add/remove the starting window if it
      * has create a starting window for the Task.
      *
-     * @param taskInfo The information about the Task that's available
+     * @param info The information about the Task that's available
      * @param appToken Token of the application being started.
      */
-    void addStartingWindow(in ActivityManager.RunningTaskInfo taskInfo, IBinder appToken);
+    void addStartingWindow(in StartingWindowInfo info, IBinder appToken);
 
     /**
      * Called when the Task want to remove the starting window.
      */
-    void removeStartingWindow(in ActivityManager.RunningTaskInfo taskInfo);
+    void removeStartingWindow(int taskId);
 
     /**
      * A callback when the Task is available for the registered organizer. The client is responsible
diff --git a/core/java/android/window/OWNERS b/core/java/android/window/OWNERS
index d10fb31..2c61df9 100644
--- a/core/java/android/window/OWNERS
+++ b/core/java/android/window/OWNERS
@@ -1,3 +1,3 @@
 set noparent
 
-include ../../../../services/core/java/com/android/server/wm/OWNERS
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/window/StartingWindowInfo.aidl b/core/java/android/window/StartingWindowInfo.aidl
new file mode 100644
index 0000000..69b18f0
--- /dev/null
+++ b/core/java/android/window/StartingWindowInfo.aidl
@@ -0,0 +1,20 @@
+/**
+ * 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.window;
+
+/** @hide */
+parcelable StartingWindowInfo;
\ No newline at end of file
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
new file mode 100644
index 0000000..2282cc5
--- /dev/null
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -0,0 +1,150 @@
+/*
+ * 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.window;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.app.ActivityManager;
+import android.app.TaskInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InsetsState;
+import android.view.WindowManager;
+
+/**
+ * Information you can retrieve about a starting window of a particular task that is currently
+ * start in the system.
+ * @hide
+ */
+@TestApi
+public final class StartingWindowInfo implements Parcelable {
+    /**
+     * The {@link TaskInfo} from this task.
+     *  @hide
+     */
+    @NonNull
+    public ActivityManager.RunningTaskInfo taskInfo;
+
+    /**
+     * InsetsState of TopFullscreenOpaqueWindow
+     * @hide
+     */
+    @Nullable
+    public InsetsState topOpaqueWindowInsetsState;
+
+    /**
+     * LayoutParams of TopFullscreenOpaqueWindow
+     * @hide
+     */
+    @Nullable
+    public WindowManager.LayoutParams topOpaqueWindowLayoutParams;
+
+    /**
+     * LayoutParams of MainWindow
+     * @hide
+     */
+    @Nullable
+    public WindowManager.LayoutParams mainWindowLayoutParams;
+
+    /**
+     * @hide
+     */
+    @IntDef(flag = true, prefix = "TYPE_PARAMETER_", value = {
+            TYPE_PARAMETER_NEW_TASK,
+            TYPE_PARAMETER_TASK_SWITCH,
+            TYPE_PARAMETER_PROCESS_RUNNING,
+            TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
+            TYPE_PARAMETER_ACTIVITY_CREATED
+    })
+    public @interface StartingTypeParams {}
+
+    /**
+     * The parameters of the starting window...
+     * @hide
+     */
+    public static final int TYPE_PARAMETER_NEW_TASK = 0x00000001;
+    /** @hide */
+    public static final int TYPE_PARAMETER_TASK_SWITCH = 0x00000002;
+    /** @hide */
+    public static final int TYPE_PARAMETER_PROCESS_RUNNING = 0x00000004;
+    /** @hide */
+    public static final int TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT = 0x00000008;
+    /** @hide */
+    public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
+
+    /**
+     * The parameters which effect the starting window type.
+     * @see android.window.StartingWindowInfo.StartingTypeParams
+     * @hide
+     */
+    public int startingWindowTypeParameter;
+
+    public StartingWindowInfo() {
+
+    }
+
+    private StartingWindowInfo(@NonNull Parcel source) {
+        readFromParcel(source);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedObject(taskInfo, flags);
+        dest.writeInt(startingWindowTypeParameter);
+        dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
+        dest.writeTypedObject(topOpaqueWindowLayoutParams, flags);
+        dest.writeTypedObject(mainWindowLayoutParams, flags);
+    }
+
+    void readFromParcel(@NonNull Parcel source) {
+        taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+        startingWindowTypeParameter = source.readInt();
+        topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
+        topOpaqueWindowLayoutParams = source.readTypedObject(
+                WindowManager.LayoutParams.CREATOR);
+        mainWindowLayoutParams = source.readTypedObject(WindowManager.LayoutParams.CREATOR);
+    }
+
+    @Override
+    public String toString() {
+        return "StartingWindowInfo{taskId=" + taskInfo.taskId
+                + " displayId=" + taskInfo.displayId
+                + " topActivityType=" + taskInfo.topActivityType
+                + " preferredStartingWindowType="
+                + Integer.toHexString(startingWindowTypeParameter)
+                + " insetsState=" + topOpaqueWindowInsetsState
+                + " topWindowLayoutParams=" + topOpaqueWindowLayoutParams
+                + " mainWindowLayoutParams=" + mainWindowLayoutParams;
+    }
+
+    public static final @android.annotation.NonNull Creator<StartingWindowInfo> CREATOR =
+            new Creator<StartingWindowInfo>() {
+                public StartingWindowInfo createFromParcel(@NonNull Parcel source) {
+                    return new StartingWindowInfo(source);
+                }
+                public StartingWindowInfo[] newArray(int size) {
+                    return new StartingWindowInfo[size];
+                }
+            };
+}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index c4bdb5a..73b2fe1 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -89,19 +89,19 @@
      * application is starting. The client is responsible to add/remove the starting window if it
      * has create a starting window for the Task.
      *
-     * @param taskInfo The information about the Task that's available
+     * @param info The information about the Task that's available
      * @param appToken Token of the application being started.
      *        context to for resources
      */
     @BinderThread
-    public void addStartingWindow(@NonNull ActivityManager.RunningTaskInfo taskInfo,
+    public void addStartingWindow(@NonNull StartingWindowInfo info,
             @NonNull IBinder appToken) {}
 
     /**
      * Called when the Task want to remove the starting window.
      */
     @BinderThread
-    public void removeStartingWindow(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
+    public void removeStartingWindow(int taskId) {}
 
     /**
      * Called when a task with the registered windowing mode can be controlled by this task
@@ -210,15 +210,26 @@
         }
     }
 
+    /**
+     * Gets the executor to run callbacks on.
+     * @hide
+     */
+    @NonNull
+    public Executor getExecutor() {
+        return mExecutor;
+    }
+
     private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
         @Override
-        public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) {
-            mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(taskInfo, appToken));
+
+        public void addStartingWindow(StartingWindowInfo windowInfo,
+                IBinder appToken) {
+            mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken));
         }
 
         @Override
-        public void removeStartingWindow(ActivityManager.RunningTaskInfo taskInfo) {
-            mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(taskInfo));
+        public void removeStartingWindow(int taskId) {
+            mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(taskId));
         }
 
         @Override
diff --git a/core/java/android/window/TaskSnapshot.aidl b/core/java/android/window/TaskSnapshot.aidl
new file mode 100644
index 0000000..4f0eb7f
--- /dev/null
+++ b/core/java/android/window/TaskSnapshot.aidl
@@ -0,0 +1,4 @@
+package android.window;
+
+/** @hide */
+parcelable TaskSnapshot;
\ No newline at end of file
diff --git a/core/java/android/window/TaskSnapshot.java b/core/java/android/window/TaskSnapshot.java
new file mode 100644
index 0000000..9834aad
--- /dev/null
+++ b/core/java/android/window/TaskSnapshot.java
@@ -0,0 +1,385 @@
+/*
+ * 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.window;
+
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.content.res.Configuration;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Surface;
+import android.view.WindowInsetsController;
+
+/**
+ * Represents a task snapshot.
+ * @hide
+ */
+public class TaskSnapshot implements Parcelable {
+    // Identifier of this snapshot
+    private final long mId;
+    // Top activity in task when snapshot was taken
+    private final ComponentName mTopActivityComponent;
+    private final HardwareBuffer mSnapshot;
+    /** Indicates whether task was in landscape or portrait */
+    @Configuration.Orientation
+    private final int mOrientation;
+    /** See {@link android.view.Surface.Rotation} */
+    @Surface.Rotation
+    private int mRotation;
+    /** The size of the snapshot before scaling */
+    private final Point mTaskSize;
+    private final Rect mContentInsets;
+    // Whether this snapshot is a down-sampled version of the high resolution snapshot, used
+    // mainly for loading snapshots quickly from disk when user is flinging fast
+    private final boolean mIsLowResolution;
+    // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to
+    // the task having a secure window or having previews disabled
+    private final boolean mIsRealSnapshot;
+    private final int mWindowingMode;
+    private final @WindowInsetsController.Appearance
+    int mAppearance;
+    private final boolean mIsTranslucent;
+    // Must be one of the named color spaces, otherwise, always use SRGB color space.
+    private final ColorSpace mColorSpace;
+
+    public TaskSnapshot(long id,
+            @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot,
+            @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize,
+            Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot,
+            int windowingMode, @WindowInsetsController.Appearance int appearance,
+            boolean isTranslucent) {
+        mId = id;
+        mTopActivityComponent = topActivityComponent;
+        mSnapshot = snapshot;
+        mColorSpace = colorSpace.getId() < 0
+                ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
+        mOrientation = orientation;
+        mRotation = rotation;
+        mTaskSize = new Point(taskSize);
+        mContentInsets = new Rect(contentInsets);
+        mIsLowResolution = isLowResolution;
+        mIsRealSnapshot = isRealSnapshot;
+        mWindowingMode = windowingMode;
+        mAppearance = appearance;
+        mIsTranslucent = isTranslucent;
+    }
+
+    private TaskSnapshot(Parcel source) {
+        mId = source.readLong();
+        mTopActivityComponent = ComponentName.readFromParcel(source);
+        mSnapshot = source.readParcelable(null /* classLoader */);
+        int colorSpaceId = source.readInt();
+        mColorSpace = colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length
+                ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
+                : ColorSpace.get(ColorSpace.Named.SRGB);
+        mOrientation = source.readInt();
+        mRotation = source.readInt();
+        mTaskSize = source.readParcelable(null /* classLoader */);
+        mContentInsets = source.readParcelable(null /* classLoader */);
+        mIsLowResolution = source.readBoolean();
+        mIsRealSnapshot = source.readBoolean();
+        mWindowingMode = source.readInt();
+        mAppearance = source.readInt();
+        mIsTranslucent = source.readBoolean();
+    }
+
+    /**
+     * @return Identifier of this snapshot.
+     */
+    public long getId() {
+        return mId;
+    }
+
+    /**
+     * @return The top activity component for the task at the point this snapshot was taken.
+     */
+    public ComponentName getTopActivityComponent() {
+        return mTopActivityComponent;
+    }
+
+    /**
+     * @return The graphic buffer representing the screenshot.
+     *
+     * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version
+     * creates a new object.
+     */
+    @UnsupportedAppUsage
+    public GraphicBuffer getSnapshot() {
+        return GraphicBuffer.createFromHardwareBuffer(mSnapshot);
+    }
+
+    /**
+     * @return The hardware buffer representing the screenshot.
+     */
+    public HardwareBuffer getHardwareBuffer() {
+        return mSnapshot;
+    }
+
+    /**
+     * @return The color space of hardware buffer representing the screenshot.
+     */
+    public ColorSpace getColorSpace() {
+        return mColorSpace;
+    }
+
+    /**
+     * @return The screen orientation the screenshot was taken in.
+     */
+    @UnsupportedAppUsage
+    public int getOrientation() {
+        return mOrientation;
+    }
+
+    /**
+     * @return The screen rotation the screenshot was taken in.
+     */
+    public int getRotation() {
+        return mRotation;
+    }
+
+    /**
+     * @return The size of the task at the point this snapshot was taken.
+     */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    public Point getTaskSize() {
+        return mTaskSize;
+    }
+
+    /**
+     * @return The system/content insets on the snapshot. These can be clipped off in order to
+     *         remove any areas behind system bars in the snapshot.
+     */
+    @UnsupportedAppUsage
+    public Rect getContentInsets() {
+        return mContentInsets;
+    }
+
+    /**
+     * @return Whether this snapshot is a down-sampled version of the full resolution.
+     */
+    @UnsupportedAppUsage
+    public boolean isLowResolution() {
+        return mIsLowResolution;
+    }
+
+    /**
+     * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
+     * due to the task having a secure window or having previews disabled.
+     */
+    @UnsupportedAppUsage
+    public boolean isRealSnapshot() {
+        return mIsRealSnapshot;
+    }
+
+    /**
+     * @return Whether or not the snapshot is of a translucent app window (non-fullscreen or has
+     * a non-opaque pixel format).
+     */
+    public boolean isTranslucent() {
+        return mIsTranslucent;
+    }
+
+    /**
+     * @return The windowing mode of the task when this snapshot was taken.
+     */
+    public int getWindowingMode() {
+        return mWindowingMode;
+    }
+
+    /**
+     * @return The {@link WindowInsetsController.Appearance} flags for the top most visible
+     *         fullscreen window at the time that the snapshot was taken.
+     */
+    public @WindowInsetsController.Appearance
+    int getAppearance() {
+        return mAppearance;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(mId);
+        ComponentName.writeToParcel(mTopActivityComponent, dest);
+        dest.writeParcelable(mSnapshot != null && !mSnapshot.isClosed() ? mSnapshot : null,
+                0);
+        dest.writeInt(mColorSpace.getId());
+        dest.writeInt(mOrientation);
+        dest.writeInt(mRotation);
+        dest.writeParcelable(mTaskSize, 0);
+        dest.writeParcelable(mContentInsets, 0);
+        dest.writeBoolean(mIsLowResolution);
+        dest.writeBoolean(mIsRealSnapshot);
+        dest.writeInt(mWindowingMode);
+        dest.writeInt(mAppearance);
+        dest.writeBoolean(mIsTranslucent);
+    }
+
+    @Override
+    public String toString() {
+        final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
+        final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
+        return "TaskSnapshot{"
+                + " mId=" + mId
+                + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
+                + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+                + " mColorSpace=" + mColorSpace.toString()
+                + " mOrientation=" + mOrientation
+                + " mRotation=" + mRotation
+                + " mTaskSize=" + mTaskSize.toString()
+                + " mContentInsets=" + mContentInsets.toShortString()
+                + " mIsLowResolution=" + mIsLowResolution
+                + " mIsRealSnapshot=" + mIsRealSnapshot
+                + " mWindowingMode=" + mWindowingMode
+                + " mAppearance=" + mAppearance
+                + " mIsTranslucent=" + mIsTranslucent;
+    }
+
+    public static final @NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
+        public TaskSnapshot createFromParcel(Parcel source) {
+            return new TaskSnapshot(source);
+        }
+        public TaskSnapshot[] newArray(int size) {
+            return new TaskSnapshot[size];
+        }
+    };
+
+    /** Builder for a {@link TaskSnapshot} object */
+    public static final class Builder {
+        private long mId;
+        private ComponentName mTopActivity;
+        private HardwareBuffer mSnapshot;
+        private ColorSpace mColorSpace;
+        private int mOrientation;
+        private int mRotation;
+        private Point mTaskSize;
+        private Rect mContentInsets;
+        private boolean mIsRealSnapshot;
+        private int mWindowingMode;
+        private @WindowInsetsController.Appearance
+        int mAppearance;
+        private boolean mIsTranslucent;
+        private int mPixelFormat;
+
+        public Builder setId(long id) {
+            mId = id;
+            return this;
+        }
+
+        public Builder setTopActivityComponent(
+                ComponentName name) {
+            mTopActivity = name;
+            return this;
+        }
+
+        public Builder setSnapshot(HardwareBuffer buffer) {
+            mSnapshot = buffer;
+            return this;
+        }
+
+        public Builder setColorSpace(ColorSpace colorSpace) {
+            mColorSpace = colorSpace;
+            return this;
+        }
+
+        public Builder setOrientation(int orientation) {
+            mOrientation = orientation;
+            return this;
+        }
+
+        public Builder setRotation(int rotation) {
+            mRotation = rotation;
+            return this;
+        }
+
+        /**
+         * Sets the original size of the task
+         */
+        public Builder setTaskSize(Point size) {
+            mTaskSize = size;
+            return this;
+        }
+
+        public Builder setContentInsets(Rect contentInsets) {
+            mContentInsets = contentInsets;
+            return this;
+        }
+
+        public Builder setIsRealSnapshot(
+                boolean realSnapshot) {
+            mIsRealSnapshot = realSnapshot;
+            return this;
+        }
+
+        public Builder setWindowingMode(int windowingMode) {
+            mWindowingMode = windowingMode;
+            return this;
+        }
+
+        public Builder setAppearance(
+                @WindowInsetsController.Appearance int appearance) {
+            mAppearance = appearance;
+            return this;
+        }
+
+        public Builder setIsTranslucent(
+                boolean isTranslucent) {
+            mIsTranslucent = isTranslucent;
+            return this;
+        }
+
+        public int getPixelFormat() {
+            return mPixelFormat;
+        }
+
+        public Builder setPixelFormat(int pixelFormat) {
+            mPixelFormat = pixelFormat;
+            return this;
+        }
+
+        public TaskSnapshot build() {
+            return new TaskSnapshot(
+                    mId,
+                    mTopActivity,
+                    mSnapshot,
+                    mColorSpace,
+                    mOrientation,
+                    mRotation,
+                    mTaskSize,
+                    mContentInsets,
+                    // When building a TaskSnapshot with the Builder class, isLowResolution
+                    // is always false. Low-res snapshots are only created when loading from
+                    // disk.
+                    false /* isLowResolution */,
+                    mIsRealSnapshot,
+                    mWindowingMode,
+                    mAppearance,
+                    mIsTranslucent);
+
+        }
+    }
+}
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index b4e7d6a..52ab38f 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -16,6 +16,13 @@
 
 package android.window;
 
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -35,48 +42,38 @@
  */
 public final class TransitionInfo implements Parcelable {
 
-    /** No transition mode. This is a placeholder, don't use this as an actual mode. */
-    public static final int TRANSIT_NONE = 0;
-
-    /** The container didn't exist before but will exist and be visible after. */
-    public static final int TRANSIT_OPEN = 1;
-
-    /** The container existed and was visible before but won't exist after. */
-    public static final int TRANSIT_CLOSE = 2;
-
-    /** The container existed before but was invisible and will be visible after. */
-    public static final int TRANSIT_SHOW = 3;
-
-    /** The container is going from visible to invisible but it will still exist after. */
-    public static final int TRANSIT_HIDE = 4;
-
-    /** The container exists and is visible before and after but it changes. */
-    public static final int TRANSIT_CHANGE = 5;
-
-    /** @hide */
+    /**
+     * Modes are only a sub-set of all the transit-types since they are per-container
+     * @hide
+     */
     @IntDef(prefix = { "TRANSIT_" }, value = {
             TRANSIT_NONE,
             TRANSIT_OPEN,
             TRANSIT_CLOSE,
-            TRANSIT_SHOW,
-            TRANSIT_HIDE,
+            // Note: to_front/to_back really mean show/hide respectively at the container level.
+            TRANSIT_TO_FRONT,
+            TRANSIT_TO_BACK,
             TRANSIT_CHANGE
     })
     public @interface TransitionMode {}
 
     private final @WindowManager.TransitionOldType int mType;
+    private final @WindowManager.TransitionFlags int mFlags;
     private final ArrayList<Change> mChanges = new ArrayList<>();
 
     private SurfaceControl mRootLeash;
     private final Point mRootOffset = new Point();
 
     /** @hide */
-    public TransitionInfo(@WindowManager.TransitionOldType int type) {
+    public TransitionInfo(@WindowManager.TransitionOldType int type,
+            @WindowManager.TransitionFlags int flags) {
         mType = type;
+        mFlags = flags;
     }
 
     private TransitionInfo(Parcel in) {
         mType = in.readInt();
+        mFlags = in.readInt();
         in.readList(mChanges, null /* classLoader */);
         mRootLeash = new SurfaceControl();
         mRootLeash.readFromParcel(in);
@@ -87,6 +84,7 @@
     /** @hide */
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mType);
+        dest.writeInt(mFlags);
         dest.writeList(mChanges);
         mRootLeash.writeToParcel(dest, flags);
         mRootOffset.writeToParcel(dest, flags);
@@ -122,6 +120,10 @@
         return mType;
     }
 
+    public int getFlags() {
+        return mFlags;
+    }
+
     /**
      * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing
      * participants to animate within. This will generally be placed at the highest-z-order
@@ -170,7 +172,8 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("{t=" + mType + " ro=" + mRootOffset + " c=[");
+        sb.append("{t=" + mType + " f=" + Integer.toHexString(mFlags)
+                + " ro=" + mRootOffset + " c=[");
         for (int i = 0; i < mChanges.size(); ++i) {
             if (i > 0) {
                 sb.append(',');
@@ -188,8 +191,8 @@
             case TRANSIT_NONE: return "NONE";
             case TRANSIT_OPEN: return "OPEN";
             case TRANSIT_CLOSE: return "CLOSE";
-            case TRANSIT_SHOW: return "SHOW";
-            case TRANSIT_HIDE: return "HIDE";
+            case TRANSIT_TO_FRONT: return "SHOW";
+            case TRANSIT_TO_BACK: return "HIDE";
             case TRANSIT_CHANGE: return "CHANGE";
             default: return "<unknown:" + mode + ">";
         }
@@ -200,7 +203,7 @@
         private final WindowContainerToken mContainer;
         private WindowContainerToken mParent;
         private final SurfaceControl mLeash;
-        private int mMode = TRANSIT_NONE;
+        private @TransitionMode int mMode = TRANSIT_NONE;
         private final Rect mStartAbsBounds = new Rect();
         private final Rect mEndAbsBounds = new Rect();
         private final Point mEndRelOffset = new Point();
diff --git a/core/java/com/android/ims/OWNERS b/core/java/com/android/ims/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/core/java/com/android/ims/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
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..e064137 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -28,6 +28,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.SharedElementCallback;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionManager;
 import android.app.prediction.AppPredictor;
@@ -176,6 +177,13 @@
     public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
             = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
 
+    /**
+     * Transition name for the first image preview.
+     * To be used for shared element transition into this activity.
+     * @hide
+     */
+    public static final String FIRST_IMAGE_PREVIEW_TRANSITION_NAME = "chooser_preview_image_1";
+
     private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
 
     private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
@@ -307,6 +315,8 @@
     @VisibleForTesting
     protected ChooserMultiProfilePagerAdapter mChooserMultiProfilePagerAdapter;
 
+    private boolean mRemoveSharedElements = false;
+
     private class ContentPreviewCoordinator {
         private static final int IMAGE_FADE_IN_MILLIS = 150;
         private static final int IMAGE_LOAD_TIMEOUT = 1;
@@ -370,10 +380,29 @@
                         if (task.mExtraCount > 0) {
                             imageView.setExtraImageCount(task.mExtraCount);
                         }
+
+                        setupPreDrawForSharedElementTransition(imageView);
                 }
             }
         };
 
+        private void setupPreDrawForSharedElementTransition(View v) {
+            v.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                @Override
+                public boolean onPreDraw() {
+                    v.getViewTreeObserver().removeOnPreDrawListener(this);
+
+                    if (!mRemoveSharedElements && isActivityTransitionRunning()) {
+                        // Disable the window animations as it interferes with the
+                        // transition animation.
+                        getWindow().setWindowAnimations(0);
+                    }
+                    startPostponedEnterTransition();
+                    return true;
+                }
+            });
+        }
+
         ContentPreviewCoordinator(View parentView, boolean hideParentOnFail) {
             super();
 
@@ -413,6 +442,8 @@
                 }
                 mHideParentOnFail = false;
             }
+            mRemoveSharedElements = true;
+            startPostponedEnterTransition();
         }
 
         private void collapseParentView() {
@@ -794,6 +825,19 @@
         );
         mDirectShareShortcutInfoCache = new HashMap<>();
         mChooserTargetComponentNameCache = new HashMap<>();
+
+        setEnterSharedElementCallback(new SharedElementCallback() {
+            @Override
+            public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
+                if (mRemoveSharedElements) {
+                    names.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+                    sharedElements.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+                }
+                super.onMapSharedElements(names, sharedElements);
+                mRemoveSharedElements = false;
+            }
+        });
+        postponeEnterTransition();
     }
 
     @Override
@@ -827,8 +871,6 @@
                 queryDirectShareTargets(chooserListAdapter, true);
                 return;
             }
-            final List<DisplayResolveInfo> driList =
-                    getDisplayResolveInfos(chooserListAdapter);
             final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
                     new ArrayList<>();
 
@@ -856,7 +898,7 @@
                         new ComponentName(
                                 appTarget.getPackageName(), appTarget.getClassName())));
             }
-            sendShareShortcutInfoList(shareShortcutInfos, driList, resultList,
+            sendShareShortcutInfoList(shareShortcutInfos, chooserListAdapter, resultList,
                     chooserListAdapter.getUserHandle());
         };
     }
@@ -1339,6 +1381,8 @@
         String action = targetIntent.getAction();
         if (Intent.ACTION_SEND.equals(action)) {
             Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+            imagePreview.findViewById(R.id.content_preview_image_1_large)
+                    .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
             mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
         } else {
             ContentResolver resolver = getContentResolver();
@@ -1358,6 +1402,8 @@
                 return contentPreviewLayout;
             }
 
+            imagePreview.findViewById(R.id.content_preview_image_1_large)
+                    .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
             mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), 0);
 
             if (imageUris.size() == 2) {
@@ -1995,32 +2041,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 +2058,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 +2101,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 +2127,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 +2145,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/IAppOpsNotedCallback.aidl b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
index fa5c30a..cb280cd 100644
--- a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
@@ -18,5 +18,5 @@
 
 // Iterface to observe op note/checks of ops
 oneway interface IAppOpsNotedCallback {
-    void opNoted(int op, int uid, String packageName, int mode);
+    void opNoted(int op, int uid, String packageName, int flags, int mode);
 }
diff --git a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
index ed521e6..b0cb2a8 100644
--- a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
@@ -18,5 +18,5 @@
 
 // Iterface to observe op starts
 oneway interface IAppOpsStartedCallback {
-    void opStarted(int op, int uid, String packageName, int mode);
+    void opStarted(int op, int uid, String packageName, int flags, int mode);
 }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 0b047a2..7a30ee2 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -20,6 +20,7 @@
 
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
 import android.os.connectivity.CellularBatteryStats;
@@ -51,7 +52,7 @@
 
     // Remaining methods are only used in Java.
 
-    BatteryUsageStats getBatteryUsageStats();
+    BatteryUsageStats getBatteryUsageStats(in BatteryUsageStatsQuery query);
 
     @UnsupportedAppUsage
     byte[] getStatistics();
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 3e1fa1d..0f37dc5 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -24,7 +24,6 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
-import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
@@ -199,18 +198,8 @@
                     /* ignoreTargetSecurity= */ false,
                     userId);
         } catch (RuntimeException e) {
-            int launchedFromUid = -1;
-            String launchedFromPackage = "?";
-            try {
-                launchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid(
-                        getActivityToken());
-                launchedFromPackage = ActivityTaskManager.getService()
-                        .getLaunchedFromPackage(getActivityToken());
-            } catch (RemoteException ignored) {
-            }
-
-            Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package "
-                    + launchedFromPackage + ", while running in "
+            Slog.wtf(TAG, "Unable to launch as UID " + getLaunchedFromUid() + " package "
+                    + getLaunchedFromPackage() + ", while running in "
                     + ActivityThread.currentProcessName(), e);
         }
     }
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
new file mode 100644
index 0000000..382b49e
--- /dev/null
+++ b/core/java/com/android/internal/app/OWNERS
@@ -0,0 +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/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 2dbcbb5..6f9da6f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -350,13 +350,7 @@
         // from managed profile to owner or other way around.
         setProfileSwitchMessageId(intent.getContentUserHint());
 
-        try {
-            mLaunchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid(
-                    getActivityToken());
-        } catch (RemoteException e) {
-            mLaunchedFromUid = -1;
-        }
-
+        mLaunchedFromUid = getLaunchedFromUid();
         if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
             // Gulp!
             finish();
@@ -1085,7 +1079,7 @@
         }
     }
 
-    protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+    protected boolean onTargetSelected(TargetInfo target, boolean always) {
         final ResolveInfo ri = target.getResolveInfo();
         final Intent intent = target != null ? target.getResolvedIntent() : null;
 
@@ -1207,7 +1201,7 @@
                     if (otherProfileMatch > bestMatch) bestMatch = otherProfileMatch;
                 }
 
-                if (alwaysCheck) {
+                if (always) {
                     final int userId = getUserId();
                     final PackageManager pm = getPackageManager();
 
@@ -1300,15 +1294,8 @@
                 maybeLogCrossProfileTargetLaunch(cti, currentUserHandle);
             }
         } catch (RuntimeException e) {
-            String launchedFromPackage;
-            try {
-                launchedFromPackage = ActivityTaskManager.getService().getLaunchedFromPackage(
-                        getActivityToken());
-            } catch (RemoteException e2) {
-                launchedFromPackage = "??";
-            }
             Slog.wtf(TAG, "Unable to launch as uid " + mLaunchedFromUid
-                    + " package " + launchedFromPackage + ", while running in "
+                    + " package " + getLaunchedFromPackage() + ", while running in "
                     + ActivityThread.currentProcessName(), e);
         }
     }
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/OWNERS b/core/java/com/android/internal/config/sysui/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/java/com/android/internal/config/sysui/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
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/graphics/drawable/BackgroundBlurDrawable.java b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
index 9eab621..96dac56 100644
--- a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
+++ b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.graphics.drawable;
 
+import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -92,9 +93,11 @@
         canvas.drawRenderNode(mRenderNode);
     }
 
-    @Override
-    public void setTint(int tintColor) {
-        mPaint.setColor(tintColor);
+    /**
+     * Color that will be alpha blended on top of the blur.
+     */
+    public void setColor(@ColorInt int color) {
+        mPaint.setColor(color);
     }
 
     @Override
diff --git a/core/java/com/android/internal/inputmethod/CallbackUtils.java b/core/java/com/android/internal/inputmethod/CallbackUtils.java
index ec67792..a77583f 100644
--- a/core/java/com/android/internal/inputmethod/CallbackUtils.java
+++ b/core/java/com/android/internal/inputmethod/CallbackUtils.java
@@ -22,6 +22,7 @@
 
 import com.android.internal.view.InputBindResult;
 
+import java.util.function.BooleanSupplier;
 import java.util.function.Supplier;
 
 /**
@@ -45,8 +46,47 @@
     @AnyThread
     public static void onResult(@NonNull IInputBindResultResultCallback callback,
             @NonNull Supplier<InputBindResult> resultSupplier) {
+        InputBindResult result = null;
+        Throwable exception = null;
+
         try {
-            callback.onResult(resultSupplier.get());
+            result = resultSupplier.get();
+        } catch (Throwable throwable) {
+            exception = throwable;
+        }
+
+        try {
+            if (exception != null) {
+                callback.onError(ThrowableHolder.of(exception));
+                return;
+            }
+            callback.onResult(result);
+        } catch (RemoteException ignored) { }
+    }
+
+    /**
+     * A utility method using given {@link IBooleanResultCallback} to callback the result.
+     *
+     * @param callback {@link IInputBindResultResultCallback} to be called back.
+     * @param resultSupplier the supplier from which the result is provided.
+     */
+    public static void onResult(@NonNull IBooleanResultCallback callback,
+            @NonNull BooleanSupplier resultSupplier) {
+        boolean result = false;
+        Throwable exception = null;
+
+        try {
+            result = resultSupplier.getAsBoolean();
+        } catch (Throwable throwable) {
+            exception = throwable;
+        }
+
+        try {
+            if (exception != null) {
+                callback.onError(ThrowableHolder.of(exception));
+                return;
+            }
+            callback.onResult(result);
         } catch (RemoteException ignored) { }
     }
 }
diff --git a/core/java/com/android/internal/inputmethod/Completable.java b/core/java/com/android/internal/inputmethod/Completable.java
index b9e1cf0..bd8c23e 100644
--- a/core/java/com/android/internal/inputmethod/Completable.java
+++ b/core/java/com/android/internal/inputmethod/Completable.java
@@ -16,13 +16,17 @@
 
 package com.android.internal.inputmethod;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.annotation.AnyThread;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.lang.annotation.Retention;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -51,21 +55,100 @@
         /**
          * Lock {@link Object} to guard complete operations within this class.
          */
-        protected final Object mValueLock = new Object();
+        protected final Object mStateLock = new Object();
 
         /**
-         * {@code true} after {@link #onComplete()} gets called.
+         * Indicates the completion state of this object.
          */
-        @GuardedBy("mValueLock")
-        protected boolean mHasValue = false;
+        @GuardedBy("mStateLock")
+        @CompletionState
+        protected int mState = CompletionState.NOT_COMPLETED;
 
         /**
-         * @return {@link true} if {@link #onComplete()} gets called already.
+         * {@link Throwable} message passed to {@link #onError(ThrowableHolder)}.
+         *
+         * <p>This is not {@code null} only when {@link #mState} is
+         * {@link CompletionState#COMPLETED_WITH_ERROR}.</p>
+         */
+        @GuardedBy("mStateLock")
+        @Nullable
+        protected String mMessage = null;
+
+        @Retention(SOURCE)
+        @IntDef({
+                CompletionState.NOT_COMPLETED,
+                CompletionState.COMPLETED_WITH_VALUE,
+                CompletionState.COMPLETED_WITH_ERROR})
+        protected @interface CompletionState {
+            /**
+             * This object is not completed yet.
+             */
+            int NOT_COMPLETED = 0;
+            /**
+             * This object is already completed with a value.
+             */
+            int COMPLETED_WITH_VALUE = 1;
+            /**
+             * This object is already completed with an error.
+             */
+            int COMPLETED_WITH_ERROR = 2;
+        }
+
+        /**
+         * Converts the given {@link CompletionState} into a human-readable string.
+         *
+         * @param state {@link CompletionState} to be converted.
+         * @return a human-readable {@link String} for the given {@code state}.
+         */
+        @AnyThread
+        protected static String stateToString(@CompletionState int state) {
+            switch (state) {
+                case CompletionState.NOT_COMPLETED:
+                    return "NOT_COMPLETED";
+                case CompletionState.COMPLETED_WITH_VALUE:
+                    return "COMPLETED_WITH_VALUE";
+                case CompletionState.COMPLETED_WITH_ERROR:
+                    return "COMPLETED_WITH_ERROR";
+                default:
+                    return "Unknown(value=" + state + ")";
+            }
+        }
+
+        /**
+         * @return {@link true} if {@link #onComplete()} gets called and {@link #mState} is
+         *         {@link CompletionState#COMPLETED_WITH_VALUE} .
          */
         @AnyThread
         public boolean hasValue() {
-            synchronized (mValueLock) {
-                return mHasValue;
+            synchronized (mStateLock) {
+                return mState == CompletionState.COMPLETED_WITH_VALUE;
+            }
+        }
+
+        /**
+         * Provides the base implementation of {@code getValue()} for derived classes.
+         *
+         * <p>Must be called after acquiring {@link #mStateLock}.</p>
+         *
+         * @throws RuntimeException when {@link #mState} is
+         *                          {@link CompletionState#COMPLETED_WITH_ERROR}.
+         * @throws UnsupportedOperationException when {@link #mState} is not
+         *                                       {@link CompletionState#COMPLETED_WITH_VALUE} and
+         *                                       {@link CompletionState#COMPLETED_WITH_ERROR}.
+         */
+        @GuardedBy("mStateLock")
+        protected void enforceGetValueLocked() {
+            switch (mState) {
+                case CompletionState.NOT_COMPLETED:
+                    throw new UnsupportedOperationException(
+                            "getValue() is allowed only if hasValue() returns true");
+                case CompletionState.COMPLETED_WITH_VALUE:
+                    return;
+                case CompletionState.COMPLETED_WITH_ERROR:
+                    throw new RuntimeException(mMessage);
+                default:
+                    throw new UnsupportedOperationException(
+                            "getValue() is not allowed on state=" + stateToString(mState));
             }
         }
 
@@ -78,6 +161,27 @@
         }
 
         /**
+         * Notify when exception happened.
+         *
+         * @param throwableHolder contains the {@link Throwable} object when exception happened.
+         */
+        @AnyThread
+        protected void onError(ThrowableHolder throwableHolder) {
+            synchronized (mStateLock) {
+                switch (mState) {
+                    case CompletionState.NOT_COMPLETED:
+                        mMessage = throwableHolder.getMessage();
+                        mState = CompletionState.COMPLETED_WITH_ERROR;
+                        break;
+                    default:
+                        throw new UnsupportedOperationException(
+                                "onError() is not allowed on state=" + stateToString(mState));
+                }
+            }
+            onComplete();
+        }
+
+        /**
          * Blocks the calling thread until at least one of the following conditions is met.
          *
          * <p>
@@ -140,7 +244,7 @@
      * Completable object of integer primitive.
      */
     public static final class Int extends ValueBase {
-        @GuardedBy("mValueLock")
+        @GuardedBy("mStateLock")
         private int mValue = 0;
 
         /**
@@ -150,29 +254,30 @@
          */
         @AnyThread
         void onComplete(int value) {
-            synchronized (mValueLock) {
-                if (mHasValue) {
-                    throw new UnsupportedOperationException(
-                            "onComplete() cannot be called multiple times");
+            synchronized (mStateLock) {
+                switch (mState) {
+                    case CompletionState.NOT_COMPLETED:
+                        mValue = value;
+                        mState = CompletionState.COMPLETED_WITH_VALUE;
+                        break;
+                    default:
+                        throw new UnsupportedOperationException(
+                                "onComplete() is not allowed on state=" + stateToString(mState));
                 }
-                mValue = value;
-                mHasValue = true;
             }
             onComplete();
         }
 
         /**
          * @return value associated with this object.
+         * @throws RuntimeException when called while {@link #onError} happened.
          * @throws UnsupportedOperationException when called while {@link #hasValue()} returns
          *                                       {@code false}.
          */
         @AnyThread
         public int getValue() {
-            synchronized (mValueLock) {
-                if (!mHasValue) {
-                    throw new UnsupportedOperationException(
-                            "getValue() is allowed only if hasValue() returns true");
-                }
+            synchronized (mStateLock) {
+                enforceGetValueLocked();
                 return mValue;
             }
         }
@@ -184,7 +289,7 @@
      * @param <T> type associated with this completable object.
      */
     public static class Values<T> extends ValueBase {
-        @GuardedBy("mValueLock")
+        @GuardedBy("mStateLock")
         @Nullable
         private T mValue = null;
 
@@ -195,30 +300,31 @@
          */
         @AnyThread
         void onComplete(@Nullable T value) {
-            synchronized (mValueLock) {
-                if (mHasValue) {
-                    throw new UnsupportedOperationException(
-                            "onComplete() cannot be called multiple times");
+            synchronized (mStateLock) {
+                switch (mState) {
+                    case CompletionState.NOT_COMPLETED:
+                        mValue = value;
+                        mState = CompletionState.COMPLETED_WITH_VALUE;
+                        break;
+                    default:
+                        throw new UnsupportedOperationException(
+                                "onComplete() is not allowed on state=" + stateToString(mState));
                 }
-                mValue = value;
-                mHasValue = true;
             }
             onComplete();
         }
 
         /**
          * @return value associated with this object.
+         * @throws RuntimeException when called while {@link #onError} happened
          * @throws UnsupportedOperationException when called while {@link #hasValue()} returns
          *                                       {@code false}.
          */
         @AnyThread
         @Nullable
         public T getValue() {
-            synchronized (mValueLock) {
-                if (!mHasValue) {
-                    throw new UnsupportedOperationException(
-                            "getValue() is allowed only if hasValue() returns true");
-                }
+            synchronized (mStateLock) {
+                enforceGetValueLocked();
                 return mValue;
             }
         }
diff --git a/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl b/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl
new file mode 100644
index 0000000..6daeb3f
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl
@@ -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.
+ */
+
+package com.android.internal.inputmethod;
+
+import com.android.internal.inputmethod.ThrowableHolder;
+
+oneway interface IBooleanResultCallback {
+    void onResult(boolean result);
+    void onError(in ThrowableHolder exception);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl b/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl
index b52b3b1..2691984 100644
--- a/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl
@@ -17,7 +17,9 @@
 package com.android.internal.inputmethod;
 
 import com.android.internal.view.InputBindResult;
+import com.android.internal.inputmethod.ThrowableHolder;
 
 oneway interface IInputBindResultResultCallback {
     void onResult(in InputBindResult result);
+    void onError(in ThrowableHolder exception);
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/inputmethod/ResultCallbacks.java b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
index c59dcf4..b07c5f8 100644
--- a/core/java/com/android/internal/inputmethod/ResultCallbacks.java
+++ b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
@@ -181,6 +181,51 @@
                 }
                 value.onComplete(result);
             }
+
+            @BinderThread
+            @Override
+            public void onError(ThrowableHolder throwableHolder) {
+                final Completable.InputBindResult value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onError(throwableHolder);
+            }
+        };
+    }
+
+    /**
+     * Creates {@link IBooleanResultCallback.Stub} that is to set {@link Completable.Boolean} when
+     * receiving the result.
+     *
+     * @param value {@link Completable.Boolean} to be set when receiving the result.
+     * @return {@link IBooleanResultCallback.Stub} that can be passed as a binder IPC parameter.
+     */
+    @AnyThread
+    public static IBooleanResultCallback.Stub of(@NonNull Completable.Boolean value) {
+        final AtomicReference<WeakReference<Completable.Boolean>>
+                atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+        return new IBooleanResultCallback.Stub() {
+            @BinderThread
+            @Override
+            public void onResult(boolean result) {
+                final Completable.Boolean value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onComplete(result);
+            }
+
+            @BinderThread
+            @Override
+            public void onError(ThrowableHolder throwableHolder) {
+                final Completable.Boolean value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onError(throwableHolder);
+            }
         };
     }
 }
diff --git a/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl b/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl
new file mode 100644
index 0000000..ed11293
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+parcelable ThrowableHolder;
\ No newline at end of file
diff --git a/core/java/com/android/internal/inputmethod/ThrowableHolder.java b/core/java/com/android/internal/inputmethod/ThrowableHolder.java
new file mode 100644
index 0000000..b6f4498
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ThrowableHolder.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A {@link Parcelable} helper class to encapsulate the exception information.
+ */
+public final class ThrowableHolder implements Parcelable {
+
+    @Nullable
+    private final String mMessage;
+
+    ThrowableHolder(@NonNull Throwable throwable) {
+        mMessage = throwable.getMessage();
+    }
+
+    ThrowableHolder(Parcel source) {
+        mMessage = source.readString();
+    }
+
+    /**
+     * Returns a {@link ThrowableHolder} with given {@link Throwable}.
+     */
+    @NonNull
+    @AnyThread
+    public static ThrowableHolder of(@NonNull Throwable throwable) {
+        return new ThrowableHolder(throwable);
+    }
+
+    /**
+     * Gets the message in this {@link ThrowableHolder}.
+     */
+    @Nullable
+    @AnyThread
+    String getMessage() {
+        return mMessage;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mMessage);
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<ThrowableHolder> CREATOR =
+            new Parcelable.Creator<ThrowableHolder>() {
+
+        @Override
+        public ThrowableHolder createFromParcel(Parcel source) {
+            return new ThrowableHolder(source);
+        }
+
+        @Override
+        public ThrowableHolder[] newArray(int size) {
+            return new ThrowableHolder[size];
+        }
+    };
+}
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/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS
new file mode 100644
index 0000000..352c132
--- /dev/null
+++ b/core/java/com/android/internal/jank/OWNERS
@@ -0,0 +1,6 @@
+include /services/core/java/com/android/server/wm/OWNERS
+
+# Jank people
+ahanwu@google.com
+vadimt@google.com
+marcinoc@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/notification/OWNERS b/core/java/com/android/internal/notification/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/core/java/com/android/internal/notification/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fb6eb97..0fa0df6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -19,6 +19,7 @@
 import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
 import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -32,6 +33,7 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.hardware.usb.UsbManager;
+import android.location.GnssSignalQuality;
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsService;
 import android.net.NetworkStats;
@@ -97,16 +99,15 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.power.MeasuredEnergyArray;
 import com.android.internal.power.MeasuredEnergyStats;
+import com.android.internal.power.MeasuredEnergyStats.EnergyBucket;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
-import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.XmlUtils;
 
@@ -122,7 +123,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -168,7 +170,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    static final int VERSION = 190 + (USE_OLD_HISTORY ? 1000 : 0);
+    static final int VERSION = 191 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -646,9 +648,22 @@
         int UPDATE_RADIO = 0x04;
         int UPDATE_BT = 0x08;
         int UPDATE_RPM = 0x10;
-        int UPDATE_ENERGY = 0x20;
+        int UPDATE_DISPLAY = 0x20;
         int UPDATE_ALL =
-                UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_ENERGY;
+                UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
+
+        @IntDef(flag = true, prefix = "UPDATE_", value = {
+                UPDATE_CPU,
+                UPDATE_WIFI,
+                UPDATE_RADIO,
+                UPDATE_BT,
+                UPDATE_RPM,
+                UPDATE_DISPLAY,
+                UPDATE_ALL,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ExternalUpdateFlag {
+        }
 
         Future<?> scheduleSync(String reason, int flags);
         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
@@ -829,6 +844,13 @@
 
     int mStartCount;
 
+    /**
+     * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
+     * gives us data, we mustn't process it since this data includes pre-reset-period data.
+     */
+    @GuardedBy("this")
+    boolean mIgnoreNextExternalStats = false;
+
     long mStartClockTimeMs;
     String mStartPlatformVersion;
     String mEndPlatformVersion;
@@ -897,7 +919,7 @@
     int mGpsSignalQualityBin = -1;
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected final StopwatchTimer[] mGpsSignalQualityTimer =
-        new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+        new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
 
     int mPhoneSignalStrengthBin = -1;
     int mPhoneSignalStrengthBinRaw = -1;
@@ -931,7 +953,8 @@
     /**
      * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
      */
-    ControllerActivityCounterImpl mBluetoothActivity;
+    @VisibleForTesting
+    protected ControllerActivityCounterImpl mBluetoothActivity;
 
     /**
      * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
@@ -989,11 +1012,15 @@
     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
 
     /**
-     * Accumulated energy consumption of various consumers while on battery.
-     * If energy consumer data is unavailable this will be null.
+     * Accumulated energy consumption, that is not attributed to individual uids, of various
+     * consumers while on battery.
+     * If energy consumer data is completely unavailable this will be null.
      */
     @GuardedBy("this")
-    MeasuredEnergyStats mBatteryMeasuredEnergyStats;
+    @VisibleForTesting
+    protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
+    /** Last known screen state. Needed for apportioning display energy. */
+    int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
 
     /**
      * These provide time bases that discount the time the device is plugged
@@ -5061,7 +5088,7 @@
         if (mGpsNesting == 0) {
             return;
         }
-        if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+        if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
             stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
             return;
         }
@@ -5157,14 +5184,11 @@
                         + Display.stateToString(state));
                 addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
             }
-            int updateFlag = ExternalStatsSync.UPDATE_CPU;
-            if (mBatteryMeasuredEnergyStats != null && mBatteryMeasuredEnergyStats.hasSubsystem(
-                    MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
-                updateFlag |= ExternalStatsSync.UPDATE_ENERGY;
-            }
+            // TODO: (Probably overkill) Have mGlobalMeasuredEnergyStats store supported flags and
+            //       only update DISPLAY if it is. Currently overkill since CPU is scheduled anyway.
+            final int updateFlag = ExternalStatsSync.UPDATE_CPU | ExternalStatsSync.UPDATE_DISPLAY;
             mExternalSync.scheduleSyncDueToScreenStateChange(updateFlag,
-                    mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning(),
-                    mScreenState);
+                    mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning(), state);
             if (Display.isOnState(state)) {
                 updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
                         uptimeMs * 1000, elapsedRealtimeMs * 1000);
@@ -5472,7 +5496,7 @@
     }
 
     void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
-        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
             if (i == except) {
                 continue;
             }
@@ -6923,7 +6947,7 @@
 
     @Override public long getGpsSignalQualityTime(int strengthBin,
             long elapsedRealtimeUs, int which) {
-        if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+        if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
             return 0;
         }
         return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
@@ -6939,7 +6963,7 @@
         double energyUsedMaMs = 0.0;
         final int which = STATS_SINCE_CHARGED;
         final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
-        for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
             energyUsedMaMs
                     += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
                     * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
@@ -7157,21 +7181,19 @@
 
     @Override
     public long getScreenOnEnergy() {
-        if (mBatteryMeasuredEnergyStats == null || !mBatteryMeasuredEnergyStats.hasSubsystem(
-                MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
+        if (mGlobalMeasuredEnergyStats == null) {
             return ENERGY_DATA_UNAVAILABLE;
         }
-        return mBatteryMeasuredEnergyStats.getAccumulatedBucketEnergy(
+        return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
                 MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
     }
 
     @Override
     public long getScreenDozeEnergy() {
-        if (mBatteryMeasuredEnergyStats == null || !mBatteryMeasuredEnergyStats.hasSubsystem(
-                MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
+        if (mGlobalMeasuredEnergyStats == null) {
             return ENERGY_DATA_UNAVAILABLE;
         }
-        return mBatteryMeasuredEnergyStats.getAccumulatedBucketEnergy(
+        return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
                 MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
     }
 
@@ -7521,6 +7543,11 @@
          */
         private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
 
+        /** Measured energies attributed to this uid while on battery. */
+        // We do not use a SparseArray<LongSamplingCounters> since it would cause lots of
+        // unnecessary timebase references, and we're just going to use on-battery anyway...
+        private MeasuredEnergyStats mUidMeasuredEnergyStats;
+
         /**
          * Estimated total time spent by the system server handling requests from this uid.
          */
@@ -7923,6 +7950,66 @@
             return mModemControllerActivity;
         }
 
+        private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
+            if (mUidMeasuredEnergyStats == null) {
+                mUidMeasuredEnergyStats =
+                        MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats);
+            }
+            return mUidMeasuredEnergyStats;
+        }
+
+        /** Adds the given energy to the given energy bucket for this uid. */
+        private void addEnergyToEnergyBucketLocked(long energyDeltaUJ,
+                @MeasuredEnergyStats.EnergyBucket int energyBucket, boolean accumulate) {
+            getOrCreateMeasuredEnergyStatsLocked()
+                    .updateBucket(energyBucket, energyDeltaUJ, accumulate);
+        }
+
+        /**
+         * Returns the energy used by this uid for an energy bucket of interest.
+         * @param bucket energy bucket of interest
+         * @return energy (in microjoules) used by this uid for this energy bucket
+         */
+        public long getMeasuredEnergyMicroJoules(@MeasuredEnergyStats.EnergyBucket int bucket) {
+            if (mBsi.mGlobalMeasuredEnergyStats == null
+                    || !mBsi.mGlobalMeasuredEnergyStats.isEnergyBucketSupported(bucket)) {
+                return ENERGY_DATA_UNAVAILABLE;
+            }
+            if (mUidMeasuredEnergyStats == null) {
+                return 0L; // It is supported, but was never filled, so it must be 0
+            }
+            return mUidMeasuredEnergyStats.getAccumulatedBucketEnergy(bucket);
+        }
+
+        /**
+         * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
+         * since last marked. Also sets the mark time for both these timers.
+         *
+         * @see BatteryStatsHelper#getProcessForegroundTimeMs
+         *
+         * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
+         *               way, the mark is set.
+         */
+        private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
+                boolean doCalc) {
+            long fgTimeUs = 0;
+            final StopwatchTimer fgTimer = mForegroundActivityTimer;
+            if (fgTimer != null) {
+                if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
+                fgTimer.setMark(elapsedRealtimeMs);
+            }
+
+            long topTimeUs = 0;
+            final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
+            if (topTimer != null) {
+                if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
+                topTimer.setMark(elapsedRealtimeMs);
+            }
+
+            // Return the min of the two
+            return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
+        }
+
         public StopwatchTimer createAudioTurnedOnTimerLocked() {
             if (mAudioTurnedOnTimer == null) {
                 mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
@@ -8651,6 +8738,8 @@
             resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
             resetIfNotNull(mModemControllerActivity, false, realtimeUs);
 
+            MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats);
+
             resetIfNotNull(mUserCpuTime, false, realtimeUs);
             resetIfNotNull(mSystemCpuTime, false, realtimeUs);
 
@@ -9090,6 +9179,13 @@
                 out.writeInt(0);
             }
 
+            if (mUidMeasuredEnergyStats != null) {
+                out.writeInt(1);
+                mUidMeasuredEnergyStats.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
+
             mUserCpuTime.writeToParcel(out);
             mSystemCpuTime.writeToParcel(out);
 
@@ -9389,6 +9485,10 @@
                 mModemControllerActivity = null;
             }
 
+            if (in.readInt() != 0) {
+                mUidMeasuredEnergyStats = new MeasuredEnergyStats(in);
+            }
+
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
 
@@ -10593,13 +10693,15 @@
     }
 
     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
-            MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
-        this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider);
+            MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets,
+            UserInfoProvider userInfoProvider) {
+        this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, supportedEnergyBuckets,
+                userInfoProvider);
     }
 
     private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
             PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb,
-            UserInfoProvider userInfoProvider) {
+            boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) {
         init(clocks);
 
         if (systemDir == null) {
@@ -10671,7 +10773,7 @@
                     mOnBatteryTimeBase);
         }
         mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
-        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
                 mOnBatteryTimeBase);
         }
@@ -10706,12 +10808,9 @@
         mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
         FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
 
-        final MeasuredEnergyArray energyStats = mMeasuredEnergyRetriever.getEnergyConsumptionData();
-        // If measured energy is not available, it is not supported and
-        // mBatteryMeasuredEnergyStats should be left null.
-        if (energyStats != null) {
-            mBatteryMeasuredEnergyStats = new MeasuredEnergyStats(energyStats, mScreenState);
-        }
+        mGlobalMeasuredEnergyStats = supportedEnergyBuckets == null ? null :
+                new MeasuredEnergyStats(supportedEnergyBuckets);
+        mScreenStateAtLastEnergyMeasurement = mScreenState;
     }
 
     @UnsupportedAppUsage
@@ -11355,7 +11454,7 @@
         mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
         mWifiActiveTimer.reset(false, elapsedRealtimeUs);
         mWifiActivity.reset(false, elapsedRealtimeUs);
-        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
         }
         mBluetoothActivity.reset(false, elapsedRealtimeUs);
@@ -11406,10 +11505,7 @@
 
         mTmpRailStats.reset();
 
-        if (mBatteryMeasuredEnergyStats != null) {
-            mBatteryMeasuredEnergyStats.reset();
-            mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ENERGY);
-        }
+        MeasuredEnergyStats.resetIfNotNull(mGlobalMeasuredEnergyStats);
 
         resetIfNotNull(mSystemServerCpuTimesUs, false, elapsedRealtimeUs);
         resetIfNotNull(mSystemServerThreadCpuTimesUs, false, elapsedRealtimeUs);
@@ -11435,6 +11531,10 @@
         clearHistoryLocked();
         mBatteryStatsHistory.resetAllFiles();
 
+        // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
+        mIgnoreNextExternalStats = true;
+        mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ALL);
+
         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
     }
 
@@ -11565,7 +11665,7 @@
         }
 
         synchronized (this) {
-            if (!mOnBatteryInternal) {
+            if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
                 if (delta != null) {
                     mNetworkStatsPool.release(delta);
                 }
@@ -11849,7 +11949,7 @@
         }
 
         synchronized (this) {
-            if (!mOnBatteryInternal) {
+            if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
                 if (delta != null) {
                     mNetworkStatsPool.release(delta);
                 }
@@ -12063,7 +12163,14 @@
             Slog.d(TAG, "Updating bluetooth stats: " + info);
         }
 
-        if (info == null || !mOnBatteryInternal) {
+        if (info == null) {
+            return;
+        }
+        if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
+            // TODO(174818545): mLastBluetoothActivityInfo is actually extremely suspicious.
+            //  Firstly, the following line was originally missing. But even more so, BESW says that
+            //  info is a delta, not a total, so this entire algorithm requires review.
+            mLastBluetoothActivityInfo.set(info);
             return;
         }
 
@@ -12285,6 +12392,88 @@
     }
 
     /**
+     * Accumulate Display energy and distribute it to the correct state and the apps.
+     *
+     * NOTE: The algorithm used makes the strong assumption that app foreground activity time
+     * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
+     * To the extent that those assumptions are violated, the algorithm will err.
+     *
+     * @param energyUJ amount of energy (microjoules) used by Display since this was last called.
+     * @param screenState screen state at the time this data collection was scheduled
+     */
+    @GuardedBy("this")
+    public void updateDisplayEnergyLocked(long energyUJ, int screenState, long elapsedRealtimeMs) {
+        if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + energyUJ);
+        if (mGlobalMeasuredEnergyStats == null) {
+            return;
+        }
+
+        final @EnergyBucket int energyBucket =
+                MeasuredEnergyStats.getDisplayEnergyBucket(mScreenStateAtLastEnergyMeasurement);
+        mScreenStateAtLastEnergyMeasurement = screenState;
+
+        if (!mOnBatteryInternal || energyUJ <= 0) {
+            // There's nothing further to update.
+            return;
+        }
+        if (mIgnoreNextExternalStats) {
+            // Although under ordinary resets we won't get here, and typically a new sync will
+            // happen right after the reset, strictly speaking we need to set all mark times to now.
+            final int uidStatsSize = mUidStats.size();
+            for (int i = 0; i < uidStatsSize; i++) {
+                final Uid uid = mUidStats.valueAt(i);
+                uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
+            }
+            return;
+        }
+
+        mGlobalMeasuredEnergyStats.updateBucket(energyBucket, energyUJ, true);
+
+        // Now we blame individual apps, but only if the display was ON.
+        if (energyBucket != MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON) {
+            return;
+        }
+        // TODO(b/175726779): Consider unifying the code with the non-rail display energy blaming.
+
+        // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
+        // 'double counted' and will simply exceed the realtime that elapsed.
+        // If multidisplay becomes a reality, this is probably more reasonable than pooling.
+
+        // On the first pass, collect total time since mark so that we can normalize power.
+        long totalFgTimeMs = 0L;
+        final ArrayMap<Uid, Long> fgTimeMsArray = new ArrayMap<>();
+        final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
+        // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
+        final int uidStatsSize = mUidStats.size();
+        for (int i = 0; i < uidStatsSize; i++) {
+            final Uid uid = mUidStats.valueAt(i);
+            final long fgTimeMs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true) / 1000;
+            if (fgTimeMs == 0) continue;
+            fgTimeMsArray.put(uid, fgTimeMs);
+            totalFgTimeMs += fgTimeMs;
+        }
+        long totalDisplayEnergyMJ = energyUJ / 1000; // not final
+
+        // Actually assign and distribute power usage to apps based on their fg time since mark.
+        // TODO(b/175726326): Decide on 'energy' units and make sure algorithm won't overflow.
+        final long fgTimeArraySize = fgTimeMsArray.size();
+        for (int i = 0; i < fgTimeArraySize; i++) {
+            final Uid uid = fgTimeMsArray.keyAt(i);
+            final long fgTimeMs = fgTimeMsArray.valueAt(i);
+
+            // Using long division: "appEnergy = totalEnergy * appFg/totalFg + 0.5" with rounding
+            final long appDisplayEnergyMJ =
+                    (totalDisplayEnergyMJ * fgTimeMs + (totalFgTimeMs / 2))
+                    / totalFgTimeMs;
+            uid.addEnergyToEnergyBucketLocked(appDisplayEnergyMJ * 1000, energyBucket, true);
+
+            // To mitigate round-off errors, remove this app from numerator & denominator totals
+            totalDisplayEnergyMJ -= appDisplayEnergyMJ;
+            totalFgTimeMs -= fgTimeMs;
+        }
+    }
+
+    /**
      * Read and record Rail Energy data.
      */
     public void updateRailStatsLocked() {
@@ -12294,6 +12483,14 @@
         mMeasuredEnergyRetriever.fillRailDataStats(mTmpRailStats);
     }
 
+    /** Informs that external stats data has been completely flushed. */
+    public void informThatAllExternalStatsAreFlushed() {
+        synchronized (this) {
+            // Any data from the pre-reset era is flushed, so we can henceforth process future data.
+            mIgnoreNextExternalStats = false;
+        }
+    }
+
     /**
      * Get energy consumed (in microjoules) by a set of subsystems from the {@link
      * MeasuredEnergyRetriever}, if available.
@@ -12568,21 +12765,6 @@
     }
 
     /**
-     * Update energy consumption data with a new snapshot of energy data.
-     * Generally this should only be called from BatteryExternalStatsWorker.
-     *
-     * @param energyStats latest energy data to update with.
-     */
-    @GuardedBy("this")
-    public void updateMeasuredEnergyStatsLocked(@NonNull MeasuredEnergyArray energyStats,
-            int screenState) {
-        if (mBatteryMeasuredEnergyStats != null) {
-            mBatteryMeasuredEnergyStats.update(energyStats, screenState,
-                    mOnBatteryTimeBase.isRunning());
-        }
-    }
-
-    /**
      * Mark the current partial timers as gone through a collection so that they will be
      * considered in the next cpu times distribution to wakelock holders.
      */
@@ -13670,7 +13852,7 @@
         final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
         s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
         s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
-        long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+        long[] time = new long[mGpsSignalQualityTimer.length];
         for (int i=0; i<time.length; i++) {
             time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
         }
@@ -13935,10 +14117,6 @@
         return u;
     }
 
-    public void onCleanupUserLocked(int userId) {
-        onCleanupUserLocked(userId, mClocks.elapsedRealtime());
-    }
-
     public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) {
         final int firstUidForUser = UserHandle.getUid(userId, 0);
         final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
@@ -14331,11 +14509,27 @@
      */
     @GuardedBy("this")
     public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
-        if (mBatteryMeasuredEnergyStats == null) return;
+        if (mGlobalMeasuredEnergyStats == null) return;
+        dumpMeasuredEnergyStatsLocked(pw, "non-uid usage", mGlobalMeasuredEnergyStats);
+
+        int size = mUidStats.size();
+        for (int i = 0; i < size; i++) {
+            final int u = mUidStats.keyAt(i);
+            final Uid uid = mUidStats.get(u);
+            final String name = "uid " + uid.mUid;
+            dumpMeasuredEnergyStatsLocked(pw, name, uid.mUidMeasuredEnergyStats);
+        }
+    }
+
+    /** Dump measured energy stats for the given uid */
+    @GuardedBy("this")
+    private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name,
+            MeasuredEnergyStats stats) {
+        if (stats == null) return;
         final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
-        iPw.println("On battery measured energy stats:");
+        iPw.printf("On battery measured energy stats for %s:\n", name);
         iPw.increaseIndent();
-        mBatteryMeasuredEnergyStats.dump(iPw);
+        stats.dump(iPw);
         iPw.decreaseIndent();
     }
 
@@ -14714,7 +14908,7 @@
         mNextMaxDailyDeadlineMs = in.readLong();
         mBatteryTimeToFullSeconds = in.readLong();
 
-        MeasuredEnergyStats.readSummaryFromParcel(mBatteryMeasuredEnergyStats, in);
+        MeasuredEnergyStats.readSummaryFromParcel(mGlobalMeasuredEnergyStats, in);
 
         mStartCount++;
 
@@ -14769,7 +14963,7 @@
         }
         mWifiActiveTimer.readSummaryFromParcelLocked(in);
         mWifiActivity.readSummaryFromParcel(in);
-        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
         }
         mBluetoothActivity.readSummaryFromParcel(in);
@@ -15030,6 +15224,9 @@
                 u.mWifiRadioApWakeupCount = null;
             }
 
+            u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in,
+                    /* template */ mGlobalMeasuredEnergyStats);
+
             int NW = in.readInt();
             if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
@@ -15209,7 +15406,7 @@
         out.writeLong(mNextMaxDailyDeadlineMs);
         out.writeLong(mBatteryTimeToFullSeconds);
 
-        MeasuredEnergyStats.writeSummaryToParcel(mBatteryMeasuredEnergyStats, out);
+        MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out);
 
         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -15255,7 +15452,7 @@
         }
         mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mWifiActivity.writeSummaryToParcel(out);
-        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
         mBluetoothActivity.writeSummaryToParcel(out);
@@ -15534,6 +15731,8 @@
                 out.writeInt(0);
             }
 
+            MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out);
+
             final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
             int NW = wakeStats.size();
             out.writeInt(NW);
@@ -15749,7 +15948,7 @@
             mOnBatteryTimeBase, in);
         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_WIFI_TX_LEVELS, in);
-        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
                 null, mOnBatteryTimeBase, in);
         }
@@ -15796,7 +15995,7 @@
         mBatteryTimeToFullSeconds = in.readLong();
 
         if (in.readInt() != 0) {
-            mBatteryMeasuredEnergyStats = new MeasuredEnergyStats(in);
+            mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in);
         }
 
         mRpmStats.clear();
@@ -15966,7 +16165,7 @@
         }
         mWifiActiveTimer.writeToParcel(out, uSecRealtime);
         mWifiActivity.writeToParcel(out, 0);
-        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
             mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
         }
         mBluetoothActivity.writeToParcel(out, 0);
@@ -16001,9 +16200,9 @@
         out.writeLong(mLastWriteTimeMs);
         out.writeLong(mBatteryTimeToFullSeconds);
 
-        if (mBatteryMeasuredEnergyStats != null) {
+        if (mGlobalMeasuredEnergyStats != null) {
             out.writeInt(1);
-            mBatteryMeasuredEnergyStats.writeToParcel(out);
+            mGlobalMeasuredEnergyStats.writeToParcel(out);
         } else {
             out.writeInt(0);
         }
@@ -16279,7 +16478,7 @@
                 pr.println("*** Wifi signal strength #" + i + ":");
                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
             }
-            for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
                 pr.println("*** GPS signal quality #" + i + ":");
                 mGpsSignalQualityTimer[i].logState(pr, "  ");
             }
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 62e9f98..9904d30 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -17,13 +17,18 @@
 package com.android.internal.os;
 
 import android.content.Context;
-import android.os.BatteryConsumer;
+import android.hardware.SensorManager;
+import android.net.ConnectivityManager;
 import android.os.BatteryStats;
 import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
 import android.os.Bundle;
-import android.os.UidBatteryConsumer;
+import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.SparseArray;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -33,44 +38,108 @@
 public class BatteryUsageStatsProvider {
     private final Context mContext;
     private final BatteryStatsImpl mStats;
+    private final PowerProfile mPowerProfile;
+    private final Object mLock = new Object();
+    private List<PowerCalculator> mPowerCalculators;
 
     public BatteryUsageStatsProvider(Context context, BatteryStatsImpl stats) {
         mContext = context;
         mStats = stats;
+        mPowerProfile = new PowerProfile(mContext);
+    }
+
+    private List<PowerCalculator> getPowerCalculators() {
+        synchronized (mLock) {
+            if (mPowerCalculators == null) {
+                mPowerCalculators = new ArrayList<>();
+
+                // Power calculators are applied in the order of registration
+                mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
+                if (!isWifiOnlyDevice(mContext)) {
+                    mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
+                }
+                mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile,
+                        mContext.getSystemService(SensorManager.class)));
+                mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile));
+                mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
+
+                mPowerCalculators.add(new UserPowerCalculator());
+            }
+        }
+        return mPowerCalculators;
+    }
+
+    private static boolean isWifiOnlyDevice(Context context) {
+        ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
+        if (cm == null) {
+            return false;
+        }
+        return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
     }
 
     /**
      * Returns a snapshot of battery attribution data.
      */
-    public BatteryUsageStats getBatteryUsageStats() {
+    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
 
         // TODO(b/174186345): instead of BatteryStatsHelper, use PowerCalculators directly.
         final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(mContext,
                 false /* collectBatteryBroadcast */);
         batteryStatsHelper.create((Bundle) null);
         final UserManager userManager = mContext.getSystemService(UserManager.class);
-        batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
-                userManager.getUserProfiles());
+        final List<UserHandle> asUsers = userManager.getUserProfiles();
+        final int n = asUsers.size();
+        SparseArray<UserHandle> users = new SparseArray<>(n);
+        for (int i = 0; i < n; ++i) {
+            UserHandle userHandle = asUsers.get(i);
+            users.put(userHandle.getIdentifier(), userHandle);
+        }
+
+        batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, users);
 
         // TODO(b/174186358): read extra power component number from configuration
         final int customPowerComponentCount = 0;
-        final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder()
-                .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
-                .setConsumedPower(batteryStatsHelper.getTotalPower());
+        final int customTimeComponentCount = 0;
+        final boolean includeModeledComponents =
+                (query.getFlags() & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED)
+                        != 0;
+
+
+        final BatteryUsageStats.Builder batteryUsageStatsBuilder =
+                new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount,
+                        includeModeledComponents)
+                        .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.addUidBatteryConsumer(
-                        new UidBatteryConsumer.Builder(customPowerComponentCount, sipper.getUid())
-                                .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
-                                .setConsumedPower(sipper.sumPower())
-                                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU,
-                                        sipper.cpuPowerMah)
-                                .build());
+                batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(sipper.uidObj)
+                        .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
+                        .setConsumedPower(sipper.sumPower());
             }
         }
+
+        final long realtimeUs = SystemClock.elapsedRealtime() * 1000;
+        final long uptimeUs = SystemClock.uptimeMillis() * 1000;
+
+        final List<PowerCalculator> powerCalculators = getPowerCalculators();
+        for (PowerCalculator powerCalculator : powerCalculators) {
+            powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs, query,
+                    users);
+        }
+
         return batteryUsageStatsBuilder.build();
     }
 }
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 11099be..f5690e0 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -15,8 +15,13 @@
  */
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
 import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.SparseArray;
@@ -30,8 +35,16 @@
     private final double mRxMa;
     private final double mTxMa;
     private final boolean mHasBluetoothPowerController;
-    private double mAppTotalPowerMah = 0;
-    private long mAppTotalTimeMs = 0;
+
+    private static class PowerAndDuration {
+        public long durationMs;
+        public double powerMah;
+    }
+
+    // Objects used for passing calculation results. Fields are used to avoid allocations.
+    private final PowerAndDuration mUidPowerAndDuration = new PowerAndDuration();
+    private final PowerAndDuration mTotalPowerAndDuration = new PowerAndDuration();
+    private final PowerAndDuration mSystemPowerAndDuration = new PowerAndDuration();
 
     public BluetoothPowerCalculator(PowerProfile profile) {
         mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
@@ -41,16 +54,90 @@
     }
 
     @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+            SparseArray<UserHandle> asUsers) {
+        if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
+            return;
+        }
+
+        mTotalPowerAndDuration.durationMs = 0;
+        mTotalPowerAndDuration.powerMah = 0;
+
+        SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+                builder.getOrCreateSystemBatteryConsumerBuilder(
+                        SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH);
+
+        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+                builder.getUidBatteryConsumerBuilders();
+        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+            calculateApp(app);
+            if (app.getUid() == Process.BLUETOOTH_UID) {
+                app.setSystemComponent(true);
+                systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
+            }
+        }
+
+        final BatteryStats.ControllerActivityCounter counter =
+                batteryStats.getBluetoothControllerActivity();
+
+        calculatePowerAndDuration(counter, mSystemPowerAndDuration);
+
+        // Subtract what the apps used, but clamp to 0.
+        final long systemComponentDurationMs = Math.max(0,
+                mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
+        final double systemComponentPowerMah = Math.max(0,
+                mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
+
+        systemBatteryConsumerBuilder
+                .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
+                        systemComponentDurationMs)
+                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+                        systemComponentPowerMah);
+    }
+
+    private void calculateApp(UidBatteryConsumer.Builder app) {
+        calculatePowerAndDuration(app.getBatteryStatsUid().getBluetoothControllerActivity(),
+                mUidPowerAndDuration);
+
+        app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
+                mUidPowerAndDuration.durationMs)
+                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+                        mUidPowerAndDuration.powerMah);
+
+        mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
+        mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
+    }
+
+    @Override
     public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
             long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
         if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
             return;
         }
 
+        mTotalPowerAndDuration.durationMs = 0;
+        mTotalPowerAndDuration.powerMah = 0;
+
         super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
 
         BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
-        calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
+        calculatePowerAndDuration(batteryStats.getBluetoothControllerActivity(),
+                mSystemPowerAndDuration);
+
+        // Subtract what the apps used, but clamp to 0.
+        double powerMah =
+                Math.max(0, mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
+        final long durationMs =
+                Math.max(0, mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
+        if (DEBUG && powerMah != 0) {
+            Log.d(TAG, "Bluetooth active: time=" + (durationMs)
+                    + " power=" + formatCharge(powerMah));
+        }
+
+        bs.bluetoothPowerMah = powerMah;
+        bs.bluetoothRunningTimeMs = durationMs;
 
         for (int i = sippers.size() - 1; i >= 0; i--) {
             BatterySipper app = sippers.get(i);
@@ -69,65 +156,42 @@
     protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
                              long rawUptimeUs, int statsType) {
 
-        final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
-        if (counter == null) {
-            return;
-        }
+        calculatePowerAndDuration(u.getBluetoothControllerActivity(), mUidPowerAndDuration);
 
-        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
-        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
-        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
-        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
-        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
-                / (double)(1000*60*60);
-
-        if (powerMah == 0) {
-            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
-                    / (1000*60*60);
-        }
-
-        app.bluetoothPowerMah = powerMah;
-        app.bluetoothRunningTimeMs = totalTimeMs;
+        app.bluetoothPowerMah = mUidPowerAndDuration.powerMah;
+        app.bluetoothRunningTimeMs = mUidPowerAndDuration.durationMs;
         app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
         app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
 
-        mAppTotalPowerMah += powerMah;
-        mAppTotalTimeMs += totalTimeMs;
+        mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
+        mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
     }
 
-    private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
-                                   long rawUptimeUs, int statsType) {
-        final BatteryStats.ControllerActivityCounter counter =
-                stats.getBluetoothControllerActivity();
+    private void calculatePowerAndDuration(BatteryStats.ControllerActivityCounter counter,
+            PowerAndDuration powerAndDuration) {
+        if (counter == null) {
+            powerAndDuration.durationMs = 0;
+            powerAndDuration.powerMah = 0;
+            return;
+        }
 
-        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
-        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
-        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
+        final long idleTimeMs =
+                counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
+        final long rxTimeMs =
+                counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
+        final long txTimeMs =
+                counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
         final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
-        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
-                 / (double)(1000*60*60);
+        double powerMah =
+                counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
+                        / (double) (1000 * 60 * 60);
 
         if (powerMah == 0) {
-            // Some devices do not report the power, so calculate it.
             powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
-                    / (1000*60*60);
+                    / (1000 * 60 * 60);
         }
 
-        // Subtract what the apps used, but clamp to 0.
-        powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
-
-        if (DEBUG && powerMah != 0) {
-            Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
-                    + " power=" + formatCharge(powerMah));
-        }
-
-        app.bluetoothPowerMah = powerMah;
-        app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
-    }
-
-    @Override
-    public void reset() {
-        mAppTotalPowerMah = 0;
-        mAppTotalTimeMs = 0;
+        powerAndDuration.durationMs = totalTimeMs;
+        powerAndDuration.powerMah = powerMah;
     }
 }
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index dac62a6..7972924 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -15,7 +15,10 @@
  */
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.UidBatteryConsumer;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -30,9 +33,11 @@
     }
 
     @Override
-    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-            long rawUptimeUs, int statsType) {
-        app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
+    protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+        final int statsType = BatteryStats.STATS_SINCE_CHARGED;
+
+        long cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
         final int numClusters = mProfile.getNumCpuClusters();
 
         double cpuPowerMaUs = 0;
@@ -70,47 +75,58 @@
                         + numClusters + " actual # " + cpuClusterTimes.length);
             }
         }
-        app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
+        final double cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
 
-        if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
-            Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
-                    + formatCharge(app.cpuPowerMah));
+        if (DEBUG && (cpuTimeMs != 0 || cpuPowerMah != 0)) {
+            Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + cpuTimeMs + " ms power="
+                    + formatCharge(cpuPowerMah));
         }
 
         // Keep track of the package with highest drain.
         double highestDrain = 0;
-
-        app.cpuFgTimeMs = 0;
+        String packageWithHighestDrain = null;
+        long cpuFgTimeMs = 0;
         final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
         final int processStatsCount = processStats.size();
         for (int i = 0; i < processStatsCount; i++) {
             final BatteryStats.Uid.Proc ps = processStats.valueAt(i);
             final String processName = processStats.keyAt(i);
-            app.cpuFgTimeMs += ps.getForegroundTime(statsType);
+            cpuFgTimeMs += ps.getForegroundTime(statsType);
 
             final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType)
                     + ps.getForegroundTime(statsType);
 
             // Each App can have multiple packages and with multiple running processes.
             // Keep track of the package who's process has the highest drain.
-            if (app.packageWithHighestDrain == null ||
-                    app.packageWithHighestDrain.startsWith("*")) {
+            if (packageWithHighestDrain == null || packageWithHighestDrain.startsWith("*")) {
                 highestDrain = costValue;
-                app.packageWithHighestDrain = processName;
+                packageWithHighestDrain = processName;
             } else if (highestDrain < costValue && !processName.startsWith("*")) {
                 highestDrain = costValue;
-                app.packageWithHighestDrain = processName;
+                packageWithHighestDrain = processName;
             }
         }
 
+
         // Ensure that the CPU times make sense.
-        if (app.cpuFgTimeMs > app.cpuTimeMs) {
-            if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) {
+        if (cpuFgTimeMs > cpuTimeMs) {
+            if (DEBUG && cpuFgTimeMs > cpuTimeMs + 10000) {
                 Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
             }
 
             // Statistics may not have been gathered yet.
-            app.cpuTimeMs = app.cpuFgTimeMs;
+            cpuTimeMs = cpuFgTimeMs;
+        }
+
+        app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah)
+                .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs)
+                .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, cpuFgTimeMs)
+                .setPackageWithHighestDrain(packageWithHighestDrain);
+
+        if ((query.getFlags()
+                & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED) != 0) {
+            app.setConsumedPowerForCustomComponent(BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                    + BatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah);
         }
     }
 }
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index afc9432..8f78b2a 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -1 +1,8 @@
-per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
+per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS
+per-file *Zygote* = file:/ZYGOTE_OWNERS
+
+# BatteryStats
+per-file BatterySipper.java = file:/BATTERY_STATS_OWNERS
+per-file BatteryStats* = file:/BATTERY_STATS_OWNERS
+per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS
+per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS
diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java
index b68899e..992c487 100644
--- a/core/java/com/android/internal/os/PhonePowerCalculator.java
+++ b/core/java/com/android/internal/os/PhonePowerCalculator.java
@@ -16,7 +16,11 @@
 
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.SystemBatteryConsumer;
 import android.os.UserHandle;
 import android.util.SparseArray;
 
@@ -33,6 +37,21 @@
     }
 
     @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+            SparseArray<UserHandle> asUsers) {
+        long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
+                BatteryStats.STATS_SINCE_CHARGED) / 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 f171b0d..974894f 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -16,6 +16,9 @@
 package com.android.internal.os;
 
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 import android.util.SparseArray;
 
@@ -55,6 +58,35 @@
     }
 
     /**
+     * Attributes the total amount of power used by this subsystem to various consumers such
+     * as apps.
+     *
+     * @param builder       {@link BatteryUsageStats.Builder that contains a list of
+     *                      per-UID battery consumer builders for attribution data.
+     *                      The calculator may modify the builder and its constituent parts.
+     * @param batteryStats  The recorded battery stats.
+     * @param rawRealtimeUs The raw system realtime in microseconds.
+     * @param rawUptimeUs   The raw system uptime in microseconds.
+     * @param statsType     The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this
+     *                      can only be {@link BatteryStats#STATS_SINCE_CHARGED}, since
+     *                      {@link BatteryStats#STATS_CURRENT} and
+     *                      {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
+     * @param asUsers       An array of users for which the attribution is requested.  It may
+     *                      contain {@link UserHandle#USER_ALL} to indicate that the attribution
+     *                      should be performed for all users.
+     */
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+            SparseArray<UserHandle> asUsers) {
+        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+                builder.getUidBatteryConsumerBuilders();
+        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+            calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query);
+        }
+    }
+
+    /**
      * Calculate the amount of power an app used for this subsystem.
      * @param app The BatterySipper that represents the power use of an app.
      * @param u The recorded stats for the app.
@@ -66,7 +98,33 @@
      *                  {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
      */
     protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-                                      long rawUptimeUs, int statsType) {}
+                                      long rawUptimeUs, int statsType) {
+
+        // TODO(b/175156498): Temporary code during the transition from BatterySippers to
+        //  BatteryConsumers.
+        UidBatteryConsumer.Builder builder = new UidBatteryConsumer.Builder(0, 0, false, u);
+        calculateApp(builder, u, rawRealtimeUs, rawUptimeUs, BatteryUsageStatsQuery.DEFAULT);
+        final UidBatteryConsumer uidBatteryConsumer = builder.build();
+        app.cpuPowerMah = uidBatteryConsumer.getConsumedPower(
+                UidBatteryConsumer.POWER_COMPONENT_CPU);
+        app.cpuTimeMs = uidBatteryConsumer.getUsageDurationMillis(
+                UidBatteryConsumer.TIME_COMPONENT_CPU);
+        app.cpuFgTimeMs = uidBatteryConsumer.getUsageDurationMillis(
+                UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND);
+        app.packageWithHighestDrain = uidBatteryConsumer.getPackageWithHighestDrain();
+    }
+
+    /**
+     * Calculate the amount of power an app used for this subsystem.
+     * @param app The UidBatteryConsumer.Builder that represents the power use of an app.
+     * @param u The recorded stats for the app.
+     * @param rawRealtimeUs The raw system realtime in microseconds.
+     * @param rawUptimeUs The raw system uptime in microseconds.
+     * @param query Power calculation parameters.
+     */
+    protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
+            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+    }
 
     /**
      * Reset any state maintained in this calculator.
diff --git a/core/java/com/android/internal/os/SensorPowerCalculator.java b/core/java/com/android/internal/os/SensorPowerCalculator.java
index 5002daf..9c8aafb 100644
--- a/core/java/com/android/internal/os/SensorPowerCalculator.java
+++ b/core/java/com/android/internal/os/SensorPowerCalculator.java
@@ -17,12 +17,11 @@
 
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
+import android.location.GnssSignalQuality;
 import android.os.BatteryStats;
 import android.os.UserHandle;
 import android.util.SparseArray;
 
-import com.android.internal.location.gnssmetrics.GnssMetrics;
-
 import java.util.List;
 
 public class SensorPowerCalculator extends PowerCalculator {
@@ -83,7 +82,7 @@
         averagePower = 0;
         long totalTime = 0;
         double totalPower = 0;
-        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
             long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType);
             totalTime += timePerLevel;
             totalPower +=
diff --git a/core/java/com/android/internal/policy/OWNERS b/core/java/com/android/internal/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/java/com/android/internal/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index f89e52d..141dc79 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3140,6 +3140,7 @@
             // On TVs, if the app doesn't implement search, we want to launch assist.
             Bundle args = new Bundle();
             args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
+            args.putLong(Intent.EXTRA_TIME, event.getEventTime());
             ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE))
                     .launchAssist(args);
             return true;
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 7b6e079..b644df4 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -17,9 +17,12 @@
 package com.android.internal.power;
 
 
+import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
+
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.util.Slog;
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -28,16 +31,19 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 
 /**
- * MeasuredEnergyStats adds up the measured energy usage of various subsystems
+ * Tracks the measured energy usage of various subsystems according to their {@link EnergyBucket}.
+ *
+ * This class doesn't use a TimeBase, and instead requires manually decisions about when to
+ * accumulate since it is trivial. However, in the future, a TimeBase could be used instead.
  */
 @VisibleForTesting
 public class MeasuredEnergyStats {
-    private static final long UNAVAILABLE = -1;
-    private static final long RESET = -2;
+    private static final String TAG = "MeasuredEnergyStats";
 
+    // Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if energy
+    // bucket integers are modified.
     public static final int ENERGY_BUCKET_UNKNOWN = -1;
     public static final int ENERGY_BUCKET_SCREEN_ON = 0;
     public static final int ENERGY_BUCKET_SCREEN_DOZE = 1;
@@ -57,45 +63,59 @@
     }
 
     /**
-     * Energy snapshots from the last time each {@link MeasuredEnergySubsystem} was updated.
-     * An energy snapshot will be set to {@link #UNAVAILABLE} if the subsystem has never been
-     * updated.
-     * An energy snapshot will be set to {@link #RESET} on a reset. A subsystems energy will
-     * need to be updated at least twice to start accumulating energy again.
-     */
-    private final long[] mMeasuredEnergySnapshots =
-            new long[MeasuredEnergyArray.NUMBER_SUBSYSTEMS];
-
-    /**
-     * Total energy in microjoules since the last reset that an {@link EnergyBucket} has
-     * accumulated.
+     * Total energy (in microjoules) that an {@link EnergyBucket} has accumulated since the last
+     * reset. Values MUST be non-zero or ENERGY_DATA_UNAVAILABLE. Accumulation only occurs
+     * while the necessary conditions are satisfied (e.g. on battery).
      *
      * Warning: Long array is used for access speed. If the number of supported subsystems
-     * becomes too large, consider using an alternate data structure.
+     * becomes large, consider using an alternate data structure such as a SparseLongArray.
      */
     private final long[] mAccumulatedEnergiesMicroJoules = new long[NUMBER_ENERGY_BUCKETS];
 
     /**
-     * Last known screen state.
+     * Creates a MeasuredEnergyStats set to support the provided energy buckets.
+     * supportedEnergyBuckets should generally be of size {@link #NUMBER_ENERGY_BUCKETS}.
      */
-    private int mLastScreenState;
-
-    public MeasuredEnergyStats(MeasuredEnergyArray energyArray, int screenState) {
-        Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
-
-        update(energyArray, screenState, false);
-    }
-
-    public MeasuredEnergyStats(Parcel in) {
-        in.readLongArray(mAccumulatedEnergiesMicroJoules);
+    public MeasuredEnergyStats(boolean[] supportedEnergyBuckets) {
+        // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
+        for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+            if (!supportedEnergyBuckets[bucket]) {
+                mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
+            }
+        }
     }
 
     /**
-     * Constructor for creating a temp MeasuredEnergyStats
-     * See {@link #readSummaryFromParcel(MeasuredEnergyStats, Parcel)}
+     * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
+     * supported. This certainly does NOT produce an exact clone of the template.
+     */
+    private MeasuredEnergyStats(MeasuredEnergyStats template) {
+        // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
+        for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+            if (!template.isEnergyBucketSupported(bucket)) {
+                mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
+            }
+        }
+    }
+
+    /**
+     * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
+     * supported.
+     */
+    public static MeasuredEnergyStats createFromTemplate(MeasuredEnergyStats template) {
+        return new MeasuredEnergyStats(template);
+    }
+
+    /**
+     * Constructor for creating a temp MeasuredEnergyStats.
+     * See {@link #readSummaryFromParcel(MeasuredEnergyStats, Parcel)}.
      */
     private MeasuredEnergyStats() {
-        Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
+    }
+
+    /** Construct from parcel. */
+    public MeasuredEnergyStats(Parcel in) {
+        in.readLongArray(mAccumulatedEnergiesMicroJoules);
     }
 
     /** Write to parcel */
@@ -105,38 +125,32 @@
 
     /**
      * Read from summary parcel.
-     * Note: Measured subsystem availability may be different from when the summary parcel was
-     * written.
+     * Note: Measured subsystem (and therefore bucket) availability may be different from when the
+     * summary parcel was written. Availability has already been correctly set in the constructor.
+     * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
+     *       parceling changes.
      */
     private void readSummaryFromParcel(Parcel in) {
         final int size = in.readInt();
         for (int i = 0; i < size; i++) {
             final int bucket = in.readInt();
             final long energyUJ = in.readLong();
-
-            final int subsystem = getSubsystem(bucket);
-            // Only accept the summary energy if subsystem is currently available
-            if (subsystem != MeasuredEnergyArray.SUBSYSTEM_UNKNOWN
-                    && mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE) {
-                mAccumulatedEnergiesMicroJoules[bucket] = energyUJ;
-            }
+            setValueIfSupported(bucket, energyUJ);
         }
     }
 
     /**
      * Write to summary parcel.
      * Note: Measured subsystem availability may be different when the summary parcel is read.
-     * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
-     *       parceling changes.
      */
     private void writeSummaryToParcel(Parcel out) {
         final int sizePos = out.dataPosition();
         out.writeInt(0);
         int size = 0;
-        // Write only the buckets with reported energy
+        // Write only the supported buckets with non-zero energy.
         for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            final int subsystem = getSubsystem(i);
-            if (mMeasuredEnergySnapshots[subsystem] == UNAVAILABLE) continue;
+            final long energy = mAccumulatedEnergiesMicroJoules[i];
+            if (energy <= 0) continue;
 
             out.writeInt(i);
             out.writeLong(mAccumulatedEnergiesMicroJoules[i]);
@@ -148,91 +162,41 @@
         out.setDataPosition(currPos);
     }
 
-    /**
-     * Update with the latest measured energies and device state.
-     *
-     * @param energyArray measured energy array for some subsystems.
-     * @param screenState screen state to attribute disaply energy to after this update.
-     * @param accumulate whether or not to accumulate the latest energy
-     */
-    public void update(MeasuredEnergyArray energyArray, int screenState, boolean accumulate) {
-        final int size = energyArray.size();
-        if (!accumulate) {
-            for (int i = 0; i < size; i++) {
-                final int subsystem = energyArray.getSubsystem(i);
-                mMeasuredEnergySnapshots[subsystem] = energyArray.getEnergy(i);
-            }
-        } else {
-            for (int i = 0; i < size; i++) {
-                final int subsystem = energyArray.getSubsystem(i);
-                final long newEnergyUJ = energyArray.getEnergy(i);
-                final long oldEnergyUJ = mMeasuredEnergySnapshots[subsystem];
-                mMeasuredEnergySnapshots[subsystem] = newEnergyUJ;
-
-                // This is the first valid energy, skip accumulating the delta
-                if (oldEnergyUJ < 0) continue;
-                final long deltaUJ = newEnergyUJ - oldEnergyUJ;
-
-                final int bucket = getEnergyBucket(subsystem, mLastScreenState);
-                mAccumulatedEnergiesMicroJoules[bucket] += deltaUJ;
+    /** Updates the given bucket with the given energy iff accumulate is true. */
+    public void updateBucket(@EnergyBucket int bucket, long energyDeltaUJ, boolean accumulate) {
+        if (accumulate) {
+            if (mAccumulatedEnergiesMicroJoules[bucket] >= 0L) {
+                mAccumulatedEnergiesMicroJoules[bucket] += energyDeltaUJ;
+            } else {
+                Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket "
+                        + ENERGY_BUCKET_NAMES[bucket] + " whose value was "
+                        + mAccumulatedEnergiesMicroJoules[bucket]);
             }
         }
-        mLastScreenState = screenState;
     }
 
     /**
-     * Map {@link MeasuredEnergySubsystem} and device state to an {@link EnergyBucket}.
-     * Keep in sync with {@link #getSubsystem}
-     */
-    @EnergyBucket
-    private int getEnergyBucket(@MeasuredEnergySubsystem int subsystem, int screenState) {
-        switch (subsystem) {
-            case MeasuredEnergyArray.SUBSYSTEM_DISPLAY:
-                if (Display.isOnState(screenState)) {
-                    return ENERGY_BUCKET_SCREEN_ON;
-                } else if (Display.isDozeState(screenState)) {
-                    return ENERGY_BUCKET_SCREEN_DOZE;
-                } else {
-                    return ENERGY_BUCKET_SCREEN_OTHER;
-                }
-            default:
-                return ENERGY_BUCKET_UNKNOWN;
-        }
-    }
-
-    /**
-     * Map {@link EnergyBucket} to a {@link MeasuredEnergySubsystem}.
-     * Keep in sync with {@link #getEnergyBucket}
-     */
-    @MeasuredEnergySubsystem
-    private int getSubsystem(@EnergyBucket int bucket) {
-        switch (bucket) {
-            case ENERGY_BUCKET_SCREEN_ON: //fallthrough
-            case ENERGY_BUCKET_SCREEN_DOZE: //fallthrough
-            case ENERGY_BUCKET_SCREEN_OTHER:
-                return MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
-            default:
-                return MeasuredEnergyArray.SUBSYSTEM_UNKNOWN;
-        }
-    }
-
-    /**
-     * Check if a subsystem's measured energy is available.
-     * @param subsystem which subsystem.
-     * @return true if subsystem is avaiable.
-     */
-    public boolean hasSubsystem(@MeasuredEnergySubsystem int subsystem) {
-        return mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE;
-    }
-
-    /**
-     * Return accumulated energy (in microjoules) since last reset.
+     * Return accumulated energy (in microjoules) for the given energy bucket since last reset.
+     * Returns {@link BatteryStats#ENERGY_DATA_UNAVAILABLE} if this energy data is unavailable.
      */
     public long getAccumulatedBucketEnergy(@EnergyBucket int bucket) {
         return mAccumulatedEnergiesMicroJoules[bucket];
     }
 
     /**
+     * Map {@link MeasuredEnergySubsystem} and device state to a Display {@link EnergyBucket}.
+     */
+    public static @EnergyBucket int getDisplayEnergyBucket(int screenState) {
+        if (Display.isOnState(screenState)) {
+            return ENERGY_BUCKET_SCREEN_ON;
+        }
+        if (Display.isDozeState(screenState)) {
+            return ENERGY_BUCKET_SCREEN_DOZE;
+        }
+        return ENERGY_BUCKET_SCREEN_OTHER;
+    }
+
+    /**
      * Populate a MeasuredEnergyStats from a parcel. If the stats is null, consume and
      * ignore the parcelled data.
      */
@@ -246,6 +210,46 @@
     }
 
     /**
+     * Create a MeasuredEnergyStats using the template to determine which buckets are supported,
+     * and populate this new object from the given parcel.
+     *
+     * @return a new MeasuredEnergyStats object as described.
+     *         Returns null if the stats contain no non-0 information (such as if template is null
+     *         or if the parcel indicates there is no data to populate).
+     *
+     * @see #createFromTemplate
+     */
+    public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in,
+            @Nullable MeasuredEnergyStats template) {
+        // Check if any MeasuredEnergyStats exists on the parcel
+        if (in.readInt() == 0) return null;
+
+        if (template == null) {
+            // Nothing supported now. Create placeholder object just to consume the parcel data.
+            final MeasuredEnergyStats mes = new MeasuredEnergyStats();
+            mes.readSummaryFromParcel(in);
+            return null;
+        }
+
+        final MeasuredEnergyStats stats = createFromTemplate(template);
+        stats.readSummaryFromParcel(in);
+        if (stats.containsInterestingData()) {
+            return stats;
+        } else {
+            // Don't waste RAM on it (and make sure not to persist it in the next writeSummary)
+            return null;
+        }
+    }
+
+    /** Returns true iff any of the buckets are supported and non-zero. */
+    private boolean containsInterestingData() {
+        for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+            if (mAccumulatedEnergiesMicroJoules[bucket] > 0) return true;
+        }
+        return false;
+    }
+
+    /**
      * Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0.
      */
     public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats,
@@ -258,47 +262,42 @@
         stats.writeSummaryToParcel(dest);
     }
 
-    /**
-     * Reset accumulated energy.
-     */
-    public void reset() {
-        for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
-            // Leave subsystems marked as unavailable alone.
-            if (mMeasuredEnergySnapshots[i] == UNAVAILABLE) continue;
-            mMeasuredEnergySnapshots[i] = RESET;
+    /** Reset accumulated energy. */
+    private void reset() {
+        for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+            setValueIfSupported(bucket, 0L);
         }
-        Arrays.fill(mAccumulatedEnergiesMicroJoules, 0);
     }
 
-    /**
-     * Dump debug data.
-     */
-    public void dump(PrintWriter pw) {
-        pw.println("Measured energy snapshot (microjoules):");
-        pw.print("   ");
-        for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
-            final long energyUJ = mMeasuredEnergySnapshots[i];
-            if (energyUJ == UNAVAILABLE) continue;
-            pw.print(MeasuredEnergyArray.SUBSYSTEM_NAMES[i]);
-            pw.print(" : ");
-            if (energyUJ == RESET) {
-                pw.print("reset");
-            } else {
-                pw.print(energyUJ);
-            }
-            if (i != MeasuredEnergyArray.NUMBER_SUBSYSTEMS - 1) {
-                pw.print(", ");
-            }
-        }
-        pw.println();
+    /** Reset accumulated energy of the given stats. */
+    public static void resetIfNotNull(@Nullable MeasuredEnergyStats stats) {
+        if (stats != null) stats.reset();
+    }
 
+    /** If the bucket is AVAILABLE, overwrite its value; otherwise leave it as UNAVAILABLE. */
+    private void setValueIfSupported(@EnergyBucket int bucket, long value) {
+        if (mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE) {
+            mAccumulatedEnergiesMicroJoules[bucket] = value;
+        }
+    }
+
+    /** Check if measuring the energy of the given bucket is supported by this device. */
+    public boolean isEnergyBucketSupported(@EnergyBucket int bucket) {
+        return mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE;
+    }
+
+    /** Dump debug data. */
+    public void dump(PrintWriter pw) {
         pw.println("Accumulated energy since last reset (microjoules):");
         pw.print("   ");
-        for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            pw.print(ENERGY_BUCKET_NAMES[i]);
+        for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+            pw.print(ENERGY_BUCKET_NAMES[bucket]);
             pw.print(" : ");
-            pw.print(mAccumulatedEnergiesMicroJoules[i]);
-            if (i != NUMBER_ENERGY_BUCKETS - 1) {
+            pw.print(mAccumulatedEnergiesMicroJoules[bucket]);
+            if (!isEnergyBucketSupported(bucket)) {
+                pw.print(" (unsupported)");
+            }
+            if (bucket != NUMBER_ENERGY_BUCKETS - 1) {
                 pw.print(", ");
             }
         }
diff --git a/core/java/com/android/internal/power/OWNERS b/core/java/com/android/internal/power/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/core/java/com/android/internal/power/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/core/java/com/android/internal/statusbar/OWNERS b/core/java/com/android/internal/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index c2cbc04..303365b 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -94,4 +94,5 @@
     void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
     void notifyPhysicalChannelConfigForSubscriber(in int subId,
             in List<PhysicalChannelConfig> configs);
+    void notifyDataEnabled(boolean enabled, int reason);
 }
diff --git a/core/java/com/android/internal/telephony/OWNERS b/core/java/com/android/internal/telephony/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/core/java/com/android/internal/telephony/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
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/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 5388235..3cf00ae 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -745,6 +745,25 @@
     }
 
     /**
+     * Throws {@link ArrayIndexOutOfBoundsException} if the range is out of bounds.
+     * @param len length of the array. Must be non-negative
+     * @param offset start index of the range. Must be non-negative
+     * @param count length of the range. Must be non-negative
+     * @throws ArrayIndexOutOfBoundsException if the range from {@code offset} with length
+     * {@code count} is out of bounds of the array
+     */
+    public static void throwsIfOutOfBounds(int len, int offset, int count) {
+        if (len < 0) {
+            throw new ArrayIndexOutOfBoundsException("Negative length: " + len);
+        }
+
+        if ((offset | count) < 0 || offset > len - count) {
+            throw new ArrayIndexOutOfBoundsException(
+                    "length=" + len + "; regionStart=" + offset + "; regionLength=" + count);
+        }
+    }
+
+    /**
      * Returns an array with values from {@code val} minus {@code null} values
      *
      * @param arrayConstructor typically {@code T[]::new} e.g. {@code String[]::new}
diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java
index ff7743f..57552f3 100644
--- a/core/java/com/android/internal/util/BinaryXmlPullParser.java
+++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java
@@ -95,8 +95,8 @@
     private Attribute[] mAttributes;
 
     @Override
-    public void setInput(InputStream is, String inputEncoding) throws XmlPullParserException {
-        if (inputEncoding != null && !StandardCharsets.UTF_8.name().equals(inputEncoding)) {
+    public void setInput(InputStream is, String encoding) throws XmlPullParserException {
+        if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
             throw new UnsupportedOperationException();
         }
 
@@ -262,19 +262,27 @@
                 break;
             }
             case XmlPullParser.START_DOCUMENT: {
+                mCurrentName = null;
+                mCurrentText = null;
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             case XmlPullParser.END_DOCUMENT: {
+                mCurrentName = null;
+                mCurrentText = null;
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             case XmlPullParser.START_TAG: {
                 mCurrentName = mIn.readInternedUTF();
-                resetAttributes();
+                mCurrentText = null;
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             case XmlPullParser.END_TAG: {
                 mCurrentName = mIn.readInternedUTF();
-                resetAttributes();
+                mCurrentText = null;
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             case XmlPullParser.TEXT:
@@ -283,12 +291,15 @@
             case XmlPullParser.COMMENT:
             case XmlPullParser.DOCDECL:
             case XmlPullParser.IGNORABLE_WHITESPACE: {
+                mCurrentName = null;
                 mCurrentText = mIn.readUTF();
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             case XmlPullParser.ENTITY_REF: {
                 mCurrentName = mIn.readUTF();
                 mCurrentText = resolveEntity(mCurrentName);
+                if (mAttributeCount > 0) resetAttributes();
                 break;
             }
             default: {
@@ -414,27 +425,23 @@
         mAttributeCount = 0;
     }
 
-    /**
-     * Search through the pool of currently allocated {@link Attribute}
-     * instances for one that matches the given name.
-     */
-    private @NonNull Attribute findAttribute(@NonNull String name)
-            throws XmlPullParserException {
+    @Override
+    public int getAttributeIndex(String namespace, String name) {
+        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
         for (int i = 0; i < mAttributeCount; i++) {
             if (Objects.equals(mAttributes[i].name, name)) {
-                return mAttributes[i];
+                return i;
             }
         }
-        throw new XmlPullParserException("Missing attribute " + name);
+        return -1;
     }
 
     @Override
     public String getAttributeValue(String namespace, String name) {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        try {
-            return findAttribute(name).getValueString();
-        } catch (XmlPullParserException e) {
-            // Missing attributes default to null
+        final int index = getAttributeIndex(namespace, name);
+        if (index != -1) {
+            return mAttributes[index].getValueString();
+        } else {
             return null;
         }
     }
@@ -445,66 +452,48 @@
     }
 
     @Override
-    public byte[] getAttributeBytesHex(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueBytesHex();
+    public byte[] getAttributeBytesHex(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueBytesHex();
     }
 
     @Override
-    public byte[] getAttributeBytesBase64(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueBytesBase64();
+    public byte[] getAttributeBytesBase64(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueBytesBase64();
     }
 
     @Override
-    public int getAttributeInt(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueInt();
+    public int getAttributeInt(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueInt();
     }
 
     @Override
-    public int getAttributeIntHex(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueIntHex();
+    public int getAttributeIntHex(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueIntHex();
     }
 
     @Override
-    public long getAttributeLong(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueLong();
+    public long getAttributeLong(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueLong();
     }
 
     @Override
-    public long getAttributeLongHex(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueLongHex();
+    public long getAttributeLongHex(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueLongHex();
     }
 
     @Override
-    public float getAttributeFloat(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueFloat();
+    public float getAttributeFloat(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueFloat();
     }
 
     @Override
-    public double getAttributeDouble(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueDouble();
+    public double getAttributeDouble(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueDouble();
     }
 
     @Override
-    public boolean getAttributeBoolean(String namespace, String name)
-            throws XmlPullParserException {
-        if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
-        return findAttribute(name).getValueBoolean();
+    public boolean getAttributeBoolean(int index) throws XmlPullParserException {
+        return mAttributes[index].getValueBoolean();
     }
 
     @Override
diff --git a/core/java/com/android/internal/util/BinaryXmlSerializer.java b/core/java/com/android/internal/util/BinaryXmlSerializer.java
index bc3b1f8..9df4bdb 100644
--- a/core/java/com/android/internal/util/BinaryXmlSerializer.java
+++ b/core/java/com/android/internal/util/BinaryXmlSerializer.java
@@ -120,7 +120,7 @@
 
     @Override
     public void setOutput(@NonNull OutputStream os, @Nullable String encoding) throws IOException {
-        if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
+        if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
             throw new UnsupportedOperationException();
         }
 
@@ -144,7 +144,10 @@
     @Override
     public void startDocument(@Nullable String encoding, @Nullable Boolean standalone)
             throws IOException {
-        if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
+        if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
+            throw new UnsupportedOperationException();
+        }
+        if (standalone != null && !standalone) {
             throw new UnsupportedOperationException();
         }
         mOut.writeByte(START_DOCUMENT | TYPE_NULL);
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 8012540..254c299 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -86,6 +86,11 @@
      */
     public static final int ACTION_FACE_WAKE_AND_UNLOCK = 7;
 
+    /**
+     * Time between the swipe-up gesture and window drawn of recents activity.
+     */
+    public static final int ACTION_START_RECENTS_ANIMATION = 8;
+
     private static final String[] NAMES = new String[]{
             "expand panel",
             "toggle recents",
@@ -94,7 +99,9 @@
             "check credential unlocked",
             "turn on screen",
             "rotate the screen",
-            "face wake-and-unlock"};
+            "face wake-and-unlock",
+            "start recents-animation",
+    };
 
     private static final int[] STATSD_ACTION = new int[]{
             FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL,
@@ -105,6 +112,7 @@
             FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TURN_ON_SCREEN,
             FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN,
             FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK,
+            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_START_RECENTS_ANIMATION,
     };
 
     private static LatencyTracker sLatencyTracker;
@@ -170,6 +178,8 @@
                 return "ACTION_ROTATE_SCREEN";
             case 8:
                 return "ACTION_FACE_WAKE_AND_UNLOCK";
+            case 9:
+                return "ACTION_START_RECENTS_ANIMATION";
             default:
                 throw new IllegalArgumentException("Invalid action");
         }
diff --git a/core/java/com/android/internal/util/XmlSerializerWrapper.java b/core/java/com/android/internal/util/XmlSerializerWrapper.java
index 2131db0..9f28d90a 100644
--- a/core/java/com/android/internal/util/XmlSerializerWrapper.java
+++ b/core/java/com/android/internal/util/XmlSerializerWrapper.java
@@ -28,7 +28,7 @@
 /**
  * Wrapper which delegates all calls through to the given {@link XmlSerializer}.
  */
-public class XmlSerializerWrapper {
+public class XmlSerializerWrapper implements XmlSerializer {
     private final XmlSerializer mWrapped;
 
     public XmlSerializerWrapper(@NonNull XmlSerializer wrapped) {
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 244efc5..de6b65f3 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -142,95 +142,104 @@
         }
 
         @Override
-        public byte[] getAttributeBytesHex(String namespace, String name)
+        public byte[] getAttributeBytesHex(int index)
                 throws XmlPullParserException {
             try {
-                return HexDump.hexStringToByteArray(getAttributeValue(namespace, name));
+                return HexDump.hexStringToByteArray(getAttributeValue(index));
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public byte[] getAttributeBytesBase64(String namespace, String name)
+        public byte[] getAttributeBytesBase64(int index)
                 throws XmlPullParserException {
             try {
-                return Base64.decode(getAttributeValue(namespace, name), Base64.NO_WRAP);
+                return Base64.decode(getAttributeValue(index), Base64.NO_WRAP);
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public int getAttributeInt(String namespace, String name)
+        public int getAttributeInt(int index)
                 throws XmlPullParserException {
             try {
-                return Integer.parseInt(getAttributeValue(namespace, name));
+                return Integer.parseInt(getAttributeValue(index));
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public int getAttributeIntHex(String namespace, String name)
+        public int getAttributeIntHex(int index)
                 throws XmlPullParserException {
             try {
-                return Integer.parseInt(getAttributeValue(namespace, name), 16);
+                return Integer.parseInt(getAttributeValue(index), 16);
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public long getAttributeLong(String namespace, String name)
+        public long getAttributeLong(int index)
                 throws XmlPullParserException {
             try {
-                return Long.parseLong(getAttributeValue(namespace, name));
+                return Long.parseLong(getAttributeValue(index));
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public long getAttributeLongHex(String namespace, String name)
+        public long getAttributeLongHex(int index)
                 throws XmlPullParserException {
             try {
-                return Long.parseLong(getAttributeValue(namespace, name), 16);
+                return Long.parseLong(getAttributeValue(index), 16);
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public float getAttributeFloat(String namespace, String name)
+        public float getAttributeFloat(int index)
                 throws XmlPullParserException {
             try {
-                return Float.parseFloat(getAttributeValue(namespace, name));
+                return Float.parseFloat(getAttributeValue(index));
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public double getAttributeDouble(String namespace, String name)
+        public double getAttributeDouble(int index)
                 throws XmlPullParserException {
             try {
-                return Double.parseDouble(getAttributeValue(namespace, name));
+                return Double.parseDouble(getAttributeValue(index));
             } catch (Exception e) {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + e);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + e);
             }
         }
 
         @Override
-        public boolean getAttributeBoolean(String namespace, String name)
+        public boolean getAttributeBoolean(int index)
                 throws XmlPullParserException {
-            final String value = getAttributeValue(namespace, name);
+            final String value = getAttributeValue(index);
             if ("true".equalsIgnoreCase(value)) {
                 return true;
             } else if ("false".equalsIgnoreCase(value)) {
                 return false;
             } else {
-                throw new XmlPullParserException("Invalid attribute " + name + ": " + value);
+                throw new XmlPullParserException(
+                        "Invalid attribute " + getAttributeName(index) + ": " + value);
             }
         }
     }
diff --git a/core/java/com/android/internal/util/dump/DualDumpOutputStream.java b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java
index 3ac38ed..20419db 100644
--- a/core/java/com/android/internal/util/dump/DualDumpOutputStream.java
+++ b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java
@@ -18,11 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.util.IndentingPrintWriter;
-
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 8962dc3..ef2275d 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -158,10 +158,6 @@
     }
 
     @Override
-    public void dispatchPointerCaptureChanged(boolean hasCapture) {
-    }
-
-    @Override
     public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
         try {
             callbacks.onUnavailable();
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 1d5935d..3a7e66c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -72,6 +72,7 @@
     private static final int DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 81;
     private static final int DO_BEGIN_BATCH_EDIT = 90;
     private static final int DO_END_BATCH_EDIT = 95;
+    private static final int DO_PERFORM_SPELL_CHECK = 110;
     private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
     private static final int DO_CLEAR_META_KEY_STATES = 130;
     private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
@@ -234,6 +235,15 @@
         dispatchMessage(obtainMessage(DO_END_BATCH_EDIT));
     }
 
+    /**
+     * Dispatches the request for performing spell check.
+     *
+     * @see InputConnection#performSpellCheck()
+     */
+    public void performSpellCheck() {
+        dispatchMessage(obtainMessage(DO_PERFORM_SPELL_CHECK));
+    }
+
     public void performPrivateCommand(String action, Bundle data) {
         dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
     }
@@ -681,6 +691,20 @@
                 }
                 return;
             }
+            case DO_PERFORM_SPELL_CHECK: {
+                Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performSpellCheck");
+                try {
+                    InputConnection ic = getInputConnection();
+                    if (ic == null || !isActive()) {
+                        Log.w(TAG, "performSpellCheck on inactive InputConnection");
+                        return;
+                    }
+                    ic.performSpellCheck();
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+                }
+                return;
+            }
             case DO_PERFORM_PRIVATE_COMMAND: {
                 final SomeArgs args = (SomeArgs) msg.obj;
                 Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand");
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 074908a..53cbf961 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -70,6 +70,8 @@
     
     void clearMetaKeyStates(int states);
     
+    void performSpellCheck();
+
     void performPrivateCommand(String action, in Bundle data);
 
     void setComposingRegion(int start, int end);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index e78ed4e..455e489 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -24,6 +24,7 @@
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
+import com.android.internal.inputmethod.IBooleanResultCallback;
 import com.android.internal.inputmethod.IInputBindResultResultCallback;
 
 /**
@@ -42,10 +43,10 @@
             boolean allowsImplicitlySelectedSubtypes);
     InputMethodSubtype getLastInputMethodSubtype();
 
-    boolean showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
-            in ResultReceiver resultReceiver);
-    boolean hideSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
-            in ResultReceiver resultReceiver);
+    void showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
+            in ResultReceiver resultReceiver, in IBooleanResultCallback resultCallback);
+    void hideSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
+            in ResultReceiver resultReceiver, in IBooleanResultCallback resultCallback);
     // If windowToken is null, this just does startInput().  Otherwise this reports that a window
     // has gained focus, and if 'attribute' is non-null then also does startInput.
     // @NonNull
@@ -64,7 +65,7 @@
     void showInputMethodPickerFromSystem(in IInputMethodClient client, int auxiliarySubtypeMode,
             int displayId);
     void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
-    boolean isInputMethodPickerShownForTest();
+    void isInputMethodPickerShownForTest(in IBooleanResultCallback resultCallback);
     InputMethodSubtype getCurrentInputMethodSubtype();
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
     // This is kept due to @UnsupportedAppUsage.
@@ -80,7 +81,7 @@
     /** Remove the IME surface. Requires passing the currently focused window. */
     void removeImeSurfaceFromWindow(in IBinder windowToken);
     void startProtoDump(in byte[] protoDump, int source, String where);
-    boolean isImeTraceEnabled();
+    void isImeTraceEnabled(in IBooleanResultCallback resultCallback);
 
     // Starts an ime trace.
     void startImeTrace();
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index b70348a..af9c012 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -442,6 +442,17 @@
     }
 
     @AnyThread
+    @Override
+    public boolean performSpellCheck() {
+        try {
+            mIInputContext.performSpellCheck();
+            return true;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    @AnyThread
     public boolean performPrivateCommand(String action, Bundle data) {
         try {
             mIInputContext.performPrivateCommand(action, data);
diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS
new file mode 100644
index 0000000..851d1f3
--- /dev/null
+++ b/core/java/com/android/internal/view/OWNERS
@@ -0,0 +1,20 @@
+# Bug component: 25700
+
+file:/core/java/android/view/OWNERS
+
+# 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/java/com/android/internal/view/RecyclerViewCaptureHelper.java b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
index 461e116..934241a 100644
--- a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
@@ -189,7 +189,7 @@
     @Override
     public void onPrepareForEnd(@NonNull ViewGroup view) {
         // Restore original position and state
-        view.scrollBy(0, mScrollDelta);
+        view.scrollBy(0, -mScrollDelta);
         view.setOverScrollMode(mOverScrollMode);
         view.setVerticalScrollBarEnabled(mScrollBarWasEnabled);
         if (DISABLE_ANIMATORS) {
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 6cdf0df..767ad42 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -178,6 +178,12 @@
     }
 
     @Override
+    public boolean performSpellCheck() {
+        mTextView.onPerformSpellCheck();
+        return true;
+    }
+
+    @Override
     public boolean performPrivateCommand(String action, Bundle data) {
         mTextView.onPrivateIMECommand(action, data);
         return true;
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 7d80993..54b0340 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -6,15 +6,41 @@
 per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
 
 # Display
-per-file android_hardware_display_* = michaelwr@google.com, santoscordon@google.com
+per-file android_hardware_display_* = file:/services/core/java/com/android/server/display/OWNERS
 
 # Input
-per-file android_hardware_input* = michaelwr@google.com, svv@google.com
-per-file android_view_Input* = michaelwr@google.com, svv@google.com
-per-file android_view_KeyCharacterMap.* = michaelwr@google.com, svv@google.com
-per-file android_view_*KeyEvent.* = michaelwr@google.com, svv@google.com
-per-file android_view_*MotionEvent.* = michaelwr@google.com, svv@google.com
-per-file android_view_PointerIcon.* = michaelwr@google.com, svv@google.com
+per-file android_hardware_input* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_Input* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_KeyCharacterMap.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_*KeyEvent.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_*MotionEvent.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_PointerIcon.* = file:/services/core/java/com/android/server/input/OWNERS
 
-# Zygote
-per-file com_android_internal_os_Zygote.*,fd_utils.* = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
+# WindowManager
+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_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
+per-file android_hardware_input_* = file:/core/java/android/hardware/input/OWNERS
+per-file android_hardware_location_* = file:/core/java/android/hardware/location/OWNERS
+per-file android_media_* = file:/media/java/android/media/OWNERS
+per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS
+per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS
+per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
+per-file android_se_* = file:/core/java/android/se/OWNERS
+per-file android_security_* = file:/core/java/android/security/OWNERS
+per-file android_view_* = file:/core/java/android/view/OWNERS
+per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 444bb66..66753e4 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -315,10 +315,14 @@
   return reinterpret_cast<jlong>(apk_assets.release());
 }
 
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+static void NativeDestroy(void* ptr) {
   delete reinterpret_cast<ApkAssets*>(ptr);
 }
 
+static jlong NativeGetFinalizer(JNIEnv* /*env*/, jclass /*clazz*/) {
+  return reinterpret_cast<jlong>(&NativeDestroy);
+}
+
 static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
   const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
   return env->NewStringUTF(apk_assets->GetPath().c_str());
@@ -427,7 +431,7 @@
     {"nativeLoadFdOffsets",
      "(ILjava/io/FileDescriptor;Ljava/lang/String;JJILandroid/content/res/loader/AssetsProvider;)J",
      (void*)NativeLoadFromFdOffset},
-    {"nativeDestroy", "(J)V", (void*)NativeDestroy},
+    {"nativeGetFinalizer", "()J", (void*)NativeGetFinalizer},
     {"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath},
     {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
     {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 1ca45fe..5cffbef 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -48,8 +48,9 @@
 
 static jclass gArrayListClass;
 static struct {
-    jmethodID    add;
-    jmethodID    toArray;
+    jmethodID cstor;
+    jmethodID add;
+    jmethodID toArray;
 } gArrayListMethods;
 
 static jclass gBooleanClass;
@@ -185,6 +186,9 @@
 jclass gClsAudioTrackRoutingProxy;
 jclass gClsAudioRecordRoutingProxy;
 
+jclass gAudioProfileClass;
+jmethodID gAudioProfileCstor;
+
 static Mutex gLock;
 
 enum AudioError {
@@ -294,20 +298,25 @@
     return old;
 }
 
-#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status))
+#define check_AudioSystem_Command(...) _check_AudioSystem_Command(__func__, __VA_ARGS__)
 
-static int _check_AudioSystem_Command(const char* caller, status_t status)
-{
-    ALOGE_IF(status, "Command failed for %s: %d", caller, status);
+static int _check_AudioSystem_Command(const char *caller, status_t status,
+                                      std::vector<status_t> ignoredErrors = {}) {
+    int jniStatus = kAudioStatusOk;
     switch (status) {
     case DEAD_OBJECT:
-        return kAudioStatusMediaServerDied;
+        jniStatus = kAudioStatusMediaServerDied;
+        break;
     case NO_ERROR:
-        return kAudioStatusOk;
+        break;
     default:
+        if (std::find(begin(ignoredErrors), end(ignoredErrors), status) == end(ignoredErrors)) {
+            jniStatus = kAudioStatusError;
+        }
         break;
     }
-    return kAudioStatusError;
+    ALOGE_IF(jniStatus != kAudioStatusOk, "Command failed for %s: %d", caller, status);
+    return jniStatus;
 }
 
 static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
@@ -807,13 +816,6 @@
     return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
 }
 
-
-static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
-{
-    return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
-                ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
-}
-
 static void convertAudioGainConfigToNative(JNIEnv *env,
                                                struct audio_gain_config *nAudioGainConfig,
                                                const jobject jAudioGainConfig,
@@ -873,7 +875,7 @@
         configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
     }
 
-    bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
+    bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig);
     audio_channel_mask_t nMask;
     jint jMask = env->GetIntField(jAudioPortConfig,
                                    gAudioPortConfigFields.mChannelMask);
@@ -1000,7 +1002,7 @@
         audioportCreated = true;
     }
 
-    bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
+    bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig);
 
     audio_channel_mask_t nMask;
     jint jMask;
@@ -1137,15 +1139,6 @@
     return jStatus;
 }
 
-static bool hasFormat(int* formats, size_t size, int format) {
-    for (size_t index = 0; index < size; index++) {
-        if (formats[index] == format) {
-            return true; // found
-        }
-    }
-    return false; // not found
-}
-
 // TODO: pull out to separate file
 template <typename T, size_t N>
 static constexpr size_t array_size(const T (&)[N]) {
@@ -1167,43 +1160,46 @@
     return result;
 }
 
-static jint convertAudioPortFromNative(JNIEnv *env,
-                                           jobject *jAudioPort, const struct audio_port *nAudioPort)
-{
+static bool isAudioPortArrayCountOutOfBounds(const struct audio_port_v7 *nAudioPort,
+                                             std::stringstream &ss) {
+    ss << " num_audio_profiles " << nAudioPort->num_audio_profiles << " num_gains "
+       << nAudioPort->num_gains;
+    if (nAudioPort->num_audio_profiles > array_size(nAudioPort->audio_profiles) ||
+        nAudioPort->num_gains > array_size(nAudioPort->gains)) {
+        return true;
+    }
+    for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
+        ss << " (" << i << ") audio profile,"
+           << " num_sample_rates " << nAudioPort->audio_profiles[i].num_sample_rates
+           << " num_channel_masks " << nAudioPort->audio_profiles[i].num_channel_masks;
+        if (nAudioPort->audio_profiles[i].num_sample_rates >
+                    array_size(nAudioPort->audio_profiles[i].sample_rates) ||
+            nAudioPort->audio_profiles[i].num_channel_masks >
+                    array_size(nAudioPort->audio_profiles[i].channel_masks)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort,
+                                       const struct audio_port_v7 *nAudioPort) {
     jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
-    jintArray jSamplingRates = NULL;
-    jintArray jChannelMasks = NULL;
-    jintArray jChannelIndexMasks = NULL;
     jintArray jEncapsulationModes = NULL;
     jintArray jEncapsulationMetadataTypes = NULL;
-    int* cFormats = NULL;
-    jintArray jFormats = NULL;
     jobjectArray jGains = NULL;
     jobject jHandle = NULL;
     jobject jAudioPortConfig = NULL;
     jstring jDeviceName = NULL;
+    jobject jAudioProfiles = NULL;
     bool useInMask;
-    size_t numPositionMasks = 0;
-    size_t numIndexMasks = 0;
-    size_t numUniqueFormats = 0;
 
     ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
         nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
 
     // Verify audio port array count info.
-    if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates)
-            || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks)
-            || nAudioPort->num_formats > array_size(nAudioPort->formats)
-            || nAudioPort->num_gains > array_size(nAudioPort->gains)) {
-
-        std::stringstream ss;
-        ss << "convertAudioPortFromNative array count out of bounds:"
-                << " num_sample_rates " << nAudioPort->num_sample_rates
-                << " num_channel_masks " << nAudioPort->num_channel_masks
-                << " num_formats " << nAudioPort->num_formats
-                << " num_gains " << nAudioPort->num_gains
-                ;
-        std::string s = ss.str();
+    if (std::stringstream ss; isAudioPortArrayCountOutOfBounds(nAudioPort, ss)) {
+        std::string s = "convertAudioPortFromNative array count out of bounds:" + ss.str();
 
         // Prefer to log through Java wtf instead of native ALOGE.
         ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log"));
@@ -1222,69 +1218,68 @@
         goto exit;
     }
 
-    jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
-    if (jSamplingRates == NULL) {
+    useInMask = audio_has_input_direction(nAudioPort->type, nAudioPort->role);
+    jAudioProfiles = env->NewObject(gArrayListClass, gArrayListMethods.cstor);
+    if (jAudioProfiles == nullptr) {
         jStatus = (jint)AUDIO_JAVA_ERROR;
         goto exit;
     }
-    if (nAudioPort->num_sample_rates) {
-        env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
-                               (jint *)nAudioPort->sample_rates);
-    }
-
-    // count up how many masks are positional and indexed
-    for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
-        const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
-        if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
-            numIndexMasks++;
-        } else {
-            numPositionMasks++;
-        }
-    }
-
-    jChannelMasks = env->NewIntArray(numPositionMasks);
-    if (jChannelMasks == NULL) {
-        jStatus = (jint)AUDIO_JAVA_ERROR;
-        goto exit;
-    }
-    jChannelIndexMasks = env->NewIntArray(numIndexMasks);
-    if (jChannelIndexMasks == NULL) {
-        jStatus = (jint)AUDIO_JAVA_ERROR;
-        goto exit;
-    }
-    useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
-
-    // put the masks in the output arrays
-    for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
-         maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
-        const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
-        if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
-            jint jMask = audio_channel_mask_get_bits(mask);
-            env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
-        } else {
-            jint jMask = useInMask ? inChannelMaskFromNative(mask)
-                                   : outChannelMaskFromNative(mask);
-            env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
-        }
-    }
-
-    // formats
-    if (nAudioPort->num_formats != 0) {
-        cFormats = new int[nAudioPort->num_formats];
-        for (size_t index = 0; index < nAudioPort->num_formats; index++) {
-            int format = audioFormatFromNative(nAudioPort->formats[index]);
-            if (!hasFormat(cFormats, numUniqueFormats, format)) {
-                cFormats[numUniqueFormats++] = format;
+    for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
+        size_t numPositionMasks = 0;
+        size_t numIndexMasks = 0;
+        // count up how many masks are positional and indexed
+        for (size_t index = 0; index < nAudioPort->audio_profiles[i].num_channel_masks; index++) {
+            const audio_channel_mask_t mask = nAudioPort->audio_profiles[i].channel_masks[index];
+            if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+                numIndexMasks++;
+            } else {
+                numPositionMasks++;
             }
         }
-    }
-    jFormats = env->NewIntArray(numUniqueFormats);
-    if (jFormats == NULL) {
-        jStatus = (jint)AUDIO_JAVA_ERROR;
-        goto exit;
-    }
-    if (numUniqueFormats != 0) {
-        env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
+
+        ScopedLocalRef<jintArray> jSamplingRates(env,
+                                                 env->NewIntArray(nAudioPort->audio_profiles[i]
+                                                                          .num_sample_rates));
+        ScopedLocalRef<jintArray> jChannelMasks(env, env->NewIntArray(numPositionMasks));
+        ScopedLocalRef<jintArray> jChannelIndexMasks(env, env->NewIntArray(numIndexMasks));
+        if (!jSamplingRates.get() || !jChannelMasks.get() || !jChannelIndexMasks.get()) {
+            jStatus = (jint)AUDIO_JAVA_ERROR;
+            goto exit;
+        }
+
+        if (nAudioPort->audio_profiles[i].num_sample_rates) {
+            env->SetIntArrayRegion(jSamplingRates.get(), 0 /*start*/,
+                                   nAudioPort->audio_profiles[i].num_sample_rates,
+                                   (jint *)nAudioPort->audio_profiles[i].sample_rates);
+        }
+
+        // put the masks in the output arrays
+        for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
+             maskIndex < nAudioPort->audio_profiles[i].num_channel_masks; maskIndex++) {
+            const audio_channel_mask_t mask =
+                    nAudioPort->audio_profiles[i].channel_masks[maskIndex];
+            if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+                jint jMask = audio_channel_mask_get_bits(mask);
+                env->SetIntArrayRegion(jChannelIndexMasks.get(), indexedMaskIndex++, 1, &jMask);
+            } else {
+                jint jMask =
+                        useInMask ? inChannelMaskFromNative(mask) : outChannelMaskFromNative(mask);
+                env->SetIntArrayRegion(jChannelMasks.get(), posMaskIndex++, 1, &jMask);
+            }
+        }
+
+        ScopedLocalRef<jobject>
+                jAudioProfile(env,
+                              env->NewObject(gAudioProfileClass, gAudioProfileCstor,
+                                             audioFormatFromNative(
+                                                     nAudioPort->audio_profiles[i].format),
+                                             jSamplingRates.get(), jChannelMasks.get(),
+                                             jChannelIndexMasks.get()));
+        if (jAudioProfile == nullptr) {
+            jStatus = (jint)AUDIO_JAVA_ERROR;
+            goto exit;
+        }
+        env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile.get());
     }
 
     // gains
@@ -1342,18 +1337,16 @@
                 convertEncapsulationInfoFromNative(env,
                                                    nAudioPort->ext.device
                                                            .encapsulation_metadata_types);
-        *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle,
-                                     jDeviceName, jSamplingRates, jChannelMasks, jChannelIndexMasks,
-                                     jFormats, jGains, nAudioPort->ext.device.type, jAddress,
-                                     jEncapsulationModes, jEncapsulationMetadataTypes);
+        *jAudioPort =
+                env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, jDeviceName,
+                               jAudioProfiles, jGains, nAudioPort->ext.device.type, jAddress,
+                               jEncapsulationModes, jEncapsulationMetadataTypes);
         env->DeleteLocalRef(jAddress);
     } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
         ALOGV("convertAudioPortFromNative is a mix");
-        *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
-                                     jHandle, nAudioPort->ext.mix.handle,
-                                     nAudioPort->role, jDeviceName,
-                                     jSamplingRates, jChannelMasks, jChannelIndexMasks,
-                                     jFormats, jGains);
+        *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle,
+                                     nAudioPort->ext.mix.handle, nAudioPort->role, jDeviceName,
+                                     jAudioProfiles, jGains);
     } else {
         ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
         jStatus = (jint)AUDIO_JAVA_ERROR;
@@ -1378,26 +1371,14 @@
     if (jDeviceName != NULL) {
         env->DeleteLocalRef(jDeviceName);
     }
-    if (jSamplingRates != NULL) {
-        env->DeleteLocalRef(jSamplingRates);
-    }
-    if (jChannelMasks != NULL) {
-        env->DeleteLocalRef(jChannelMasks);
-    }
-    if (jChannelIndexMasks != NULL) {
-        env->DeleteLocalRef(jChannelIndexMasks);
-    }
     if (jEncapsulationModes != NULL) {
         env->DeleteLocalRef(jEncapsulationModes);
     }
     if (jEncapsulationMetadataTypes != NULL) {
         env->DeleteLocalRef(jEncapsulationMetadataTypes);
     }
-    if (cFormats != NULL) {
-        delete[] cFormats;
-    }
-    if (jFormats != NULL) {
-        env->DeleteLocalRef(jFormats);
+    if (jAudioProfiles != NULL) {
+        env->DeleteLocalRef(jAudioProfiles);
     }
     if (jGains != NULL) {
         env->DeleteLocalRef(jGains);
@@ -1436,7 +1417,7 @@
     unsigned int generation;
     unsigned int numPorts;
     jint *nGeneration;
-    struct audio_port *nPorts = NULL;
+    struct audio_port_v7 *nPorts = nullptr;
     int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
     jint jStatus;
 
@@ -1448,11 +1429,8 @@
         }
 
         numPorts = 0;
-        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
-                                             AUDIO_PORT_TYPE_NONE,
-                                                      &numPorts,
-                                                      NULL,
-                                                      &generation1);
+        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+                                             nullptr, &generation1);
         if (status != NO_ERROR) {
             ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
             break;
@@ -1461,13 +1439,10 @@
             jStatus = (jint)AUDIO_JAVA_SUCCESS;
             goto exit;
         }
-        nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
+        nPorts = (struct audio_port_v7 *)realloc(nPorts, numPorts * sizeof(struct audio_port_v7));
 
-        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
-                                             AUDIO_PORT_TYPE_NONE,
-                                                      &numPorts,
-                                                      nPorts,
-                                                      &generation);
+        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+                                             nPorts, &generation);
         ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
               numPorts, generation, generation1);
     } while (generation1 != generation && status == NO_ERROR);
@@ -2113,10 +2088,9 @@
                                                   (audio_devices_t)device);
 }
 
-static jboolean
-android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
-        jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask, jint streamType)
-{
+static jint android_media_AudioSystem_getOffloadSupport(JNIEnv *env, jobject thiz, jint encoding,
+                                                        jint sampleRate, jint channelMask,
+                                                        jint channelIndexMask, jint streamType) {
     audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
     format.format = (audio_format_t) audioFormatToNative(encoding);
     format.sample_rate = (uint32_t) sampleRate;
@@ -2128,7 +2102,7 @@
     // client side code cannot access "audio.offload.min.duration.secs" property to make a query
     // agnostic of duration, so using acceptable estimate of 2mn
     format.duration_us = 120 * 1000000;
-    return AudioSystem::isOffloadSupported(format);
+    return AudioSystem::getOffloadSupport(format);
 }
 
 static jint
@@ -2381,9 +2355,12 @@
 
 static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz,
                                                                    jint strategy, jint role) {
-    return (jint)check_AudioSystem_Command(
-            AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy,
-                                                      (device_role_t)role));
+    return (jint)
+            check_AudioSystem_Command(AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)
+                                                                                        strategy,
+                                                                                (device_role_t)
+                                                                                        role),
+                                      {NAME_NOT_FOUND});
 }
 
 static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz,
@@ -2604,8 +2581,8 @@
           (void *)android_media_AudioSystem_registerRecordingCallback},
          {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
          {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
-         {"native_is_offload_supported", "(IIIII)Z",
-          (void *)android_media_AudioSystem_isOffloadSupported},
+         {"native_get_offload_support", "(IIIII)I",
+          (void *)android_media_AudioSystem_getOffloadSupport},
          {"getMicrophones", "(Ljava/util/ArrayList;)I",
           (void *)android_media_AudioSystem_getMicrophones},
          {"getSurroundFormats", "(Ljava/util/Map;Z)I",
@@ -2671,6 +2648,7 @@
 
     jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
     gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+    gArrayListMethods.cstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
     gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
     gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
 
@@ -2733,7 +2711,7 @@
     gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
     gAudioDevicePortCstor =
             GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
-                             "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I"
+                             "(Landroid/media/AudioHandle;Ljava/lang/String;Ljava/util/List;"
                              "[Landroid/media/AudioGain;ILjava/lang/String;[I[I)V");
 
     // When access AudioPort as AudioDevicePort
@@ -2743,8 +2721,10 @@
 
     jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
     gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
-    gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
-            "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
+    gAudioMixPortCstor =
+            GetMethodIDOrDie(env, audioMixPortClass, "<init>",
+                             "(Landroid/media/AudioHandle;IILjava/lang/String;Ljava/util/List;"
+                             "[Landroid/media/AudioGain;)V");
 
     jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
     gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
@@ -2846,6 +2826,10 @@
     jclass listClass = FindClassOrDie(env, "java/util/List");
     gListMethods.add = GetMethodIDOrDie(env, listClass, "add", "(Ljava/lang/Object;)Z");
 
+    jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile");
+    gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass);
+    gAudioProfileCstor = GetMethodIDOrDie(env, audioProfileClass, "<init>", "(I[I[I[I)V");
+
     AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);
 
     RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index ecb3cd6..82611ee 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -23,6 +23,7 @@
 
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include "core_jni_helpers.h"
 
 #include <utils/Log.h>
@@ -85,9 +86,12 @@
     delete lpToneGen;
 }
 
-static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
-        jint streamType, jint volume) {
-    ToneGenerator *lpToneGen = new ToneGenerator((audio_stream_type_t) streamType, AudioSystem::linearToLog(volume), true);
+static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz, jint streamType,
+                                                     jint volume, jstring opPackageName) {
+    ScopedUtfChars opPackageNameStr(env, opPackageName);
+    ToneGenerator *lpToneGen =
+            new ToneGenerator((audio_stream_type_t)streamType, AudioSystem::linearToLog(volume),
+                              true /*threadCanCallJava*/, opPackageNameStr.c_str());
 
     env->SetLongField(thiz, fields.context, 0);
 
@@ -123,15 +127,14 @@
 
 // ----------------------------------------------------------------------------
 
-static const JNINativeMethod gMethods[] = {
-    { "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone },
-    { "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone },
-    { "getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
-    { "release", "()V", (void *)android_media_ToneGenerator_release },
-    { "native_setup", "(II)V", (void *)android_media_ToneGenerator_native_setup },
-    { "native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize }
-};
-
+static const JNINativeMethod gMethods[] =
+        {{"startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone},
+         {"stopTone", "()V", (void *)android_media_ToneGenerator_stopTone},
+         {"getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
+         {"release", "()V", (void *)android_media_ToneGenerator_release},
+         {"native_setup", "(IILjava/lang/String;)V",
+          (void *)android_media_ToneGenerator_native_setup},
+         {"native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize}};
 
 int register_android_media_ToneGenerator(JNIEnv *env) {
     jclass clazz = FindClassOrDie(env, "android/media/ToneGenerator");
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index bf79a44..bb51c57 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -847,6 +847,17 @@
     return ionPss;
 }
 
+static jlong android_os_Debug_getGpuTotalUsageKb(JNIEnv* env, jobject clazz) {
+    jlong sizeKb = -1;
+    uint64_t size;
+
+    if (meminfo::ReadGpuTotalUsageKb(&size)) {
+        sizeKb = size;
+    }
+
+    return sizeKb;
+}
+
 static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
 {
     static enum {
@@ -915,6 +926,8 @@
             (void*)android_os_Debug_getIonPoolsSizeKb },
     { "getIonMappedSizeKb", "()J",
             (void*)android_os_Debug_getIonMappedSizeKb },
+    { "getGpuTotalUsageKb", "()J",
+            (void*)android_os_Debug_getGpuTotalUsageKb },
     { "isVmapStack", "()Z",
             (void*)android_os_Debug_isVmapStack },
 };
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 9f4e3e5..4eaa016 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -60,13 +60,17 @@
     // Not sure why, but JNI is complaining when I pass this through directly.
     jboolean hasMic = deviceInfo.hasMic() ? JNI_TRUE : JNI_FALSE;
 
-    ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz,
-                gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(),
-                deviceInfo.getControllerNumber(), nameObj.get(),
-                static_cast<int32_t>(ident.vendor), static_cast<int32_t>(ident.product),
-                descriptorObj.get(), deviceInfo.isExternal(), deviceInfo.getSources(),
-                deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(),
-                hasMic, deviceInfo.hasButtonUnderPad()));
+    ScopedLocalRef<jobject>
+            inputDeviceObj(env,
+                           env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor,
+                                          deviceInfo.getId(), deviceInfo.getGeneration(),
+                                          deviceInfo.getControllerNumber(), nameObj.get(),
+                                          static_cast<int32_t>(ident.vendor),
+                                          static_cast<int32_t>(ident.product), descriptorObj.get(),
+                                          deviceInfo.isExternal(), deviceInfo.getSources(),
+                                          deviceInfo.getKeyboardType(), kcmObj.get(),
+                                          deviceInfo.hasVibrator(), hasMic,
+                                          deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor()));
 
     const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
     for (const InputDeviceInfo::MotionRange& range: ranges) {
@@ -87,7 +91,8 @@
     gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
 
     gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
-            "(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V");
+                                                  "(IIILjava/lang/String;IILjava/lang/"
+                                                  "String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V");
 
     gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
             "addMotionRange", "(IIFFFFF)V");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 6ec656c..a6dbd19 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -52,6 +52,7 @@
 #include <ui/Rect.h>
 #include <ui/Region.h>
 #include <utils/Log.h>
+#include <utils/LightRefBase.h>
 
 // ----------------------------------------------------------------------------
 
@@ -206,6 +207,16 @@
     jfieldID appRequestRefreshRateMax;
 } gDesiredDisplayConfigSpecsClassInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID onJankDataAvailable;
+} gJankDataListenerClassInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID ctor;
+} gJankDataClassInfo;
+
 class JNamedColorSpace {
 public:
     // ColorSpace.Named.SRGB.ordinal() = 0;
@@ -1601,6 +1612,77 @@
     transaction->setFrameTimelineVsync(frameTimelineVsyncId);
 }
 
+class JankDataListenerWrapper : public JankDataListener {
+public:
+    JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) {
+        mOnJankDataListenerWeak = env->NewWeakGlobalRef(onJankDataListenerObject);
+        env->GetJavaVM(&mVm);
+    }
+
+    ~JankDataListenerWrapper() {
+        JNIEnv* env = getEnv();
+        env->DeleteWeakGlobalRef(mOnJankDataListenerWeak);
+    }
+
+    void onJankDataAvailable(const std::vector<JankData>& jankData) {
+        JNIEnv* env = getEnv();
+
+        jobject target = env->NewLocalRef(mOnJankDataListenerWeak);
+        if (target == nullptr) return;
+
+        jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
+                gJankDataClassInfo.clazz, nullptr);
+        for (int i = 0; i < jankData.size(); i++) {
+            jobject jJankData = env->NewObject(gJankDataClassInfo.clazz,
+                    gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType);
+            env->SetObjectArrayElement(jJankDataArray, i, jJankData);
+        }
+        env->CallVoidMethod(target,
+                gJankDataListenerClassInfo.onJankDataAvailable,
+                jJankDataArray);
+        env->DeleteLocalRef(target);
+    }
+
+private:
+
+    JNIEnv* getEnv() {
+        JNIEnv* env;
+        mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+        return env;
+    }
+
+    JavaVM* mVm;
+    jobject mOnJankDataListenerWeak;
+};
+
+static void nativeAddJankDataListener(JNIEnv* env, jclass clazz,
+                                       jlong jankDataCallbackListenerPtr,
+                                       jlong nativeSurfaceControl) {
+    sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(nativeSurfaceControl));
+    if (surface == nullptr) {
+        return;
+    }
+    JankDataListenerWrapper* wrapper =
+            reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr);
+    TransactionCompletedListener::getInstance()->addJankListener(wrapper, surface);
+}
+
+static void nativeRemoveJankDataListener(JNIEnv* env, jclass clazz,
+                                          jlong jankDataCallbackListenerPtr) {
+    JankDataListenerWrapper* wrapper =
+            reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr);
+    TransactionCompletedListener::getInstance()->removeJankListener(wrapper);
+}
+
+static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz,
+                                                 jobject jankDataListenerObject) {
+    return reinterpret_cast<jlong>(new JankDataListenerWrapper(env, jankDataListenerObject));
+}
+
+static jint nativeGetGPUContextPriority(JNIEnv* env, jclass clazz) {
+    return static_cast<jint>(SurfaceComposerClient::getGPUContextPriority());
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1785,6 +1867,14 @@
             (void*)nativeSetFocusedWindow},
     {"nativeSetFrameTimelineVsync", "(JJ)V",
             (void*)nativeSetFrameTimelineVsync },
+    {"nativeAddJankDataListener", "(JJ)V",
+            (void*)nativeAddJankDataListener },
+    {"nativeRemoveJankDataListener", "(J)V",
+            (void*)nativeRemoveJankDataListener },
+    {"nativeCreateJankDataListenerWrapper", "(Landroid/view/SurfaceControl$OnJankDataListener;)J",
+            (void*)nativeCreateJankDataListenerWrapper },
+    {"nativeGetGPUContextPriority", "()I",
+            (void*)nativeGetGPUContextPriority },
         // clang-format on
 };
 
@@ -1966,6 +2056,18 @@
     gScreenCaptureListenerClassInfo.onScreenCaptureComplete =
             GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete",
                              "(Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;)V");
+
+    jclass jankDataClazz =
+                FindClassOrDie(env, "android/view/SurfaceControl$JankData");
+    gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz);
+    gJankDataClassInfo.ctor =
+            GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JI)V");
+    jclass onJankDataListenerClazz =
+            FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener");
+    gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz);
+    gJankDataListenerClassInfo.onJankDataAvailable =
+            GetMethodIDOrDie(env, onJankDataListenerClazz, "onJankDataAvailable",
+                             "([Landroid/view/SurfaceControl$JankData;)V");
     return err;
 }
 
diff --git a/core/proto/android/hardware/sensorprivacy.proto b/core/proto/android/hardware/sensorprivacy.proto
new file mode 100644
index 0000000..07e938d
--- /dev/null
+++ b/core/proto/android/hardware/sensorprivacy.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.service;
+
+option java_multiple_files = true;
+option java_outer_classname = "SensorPrivacyServiceProto";
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+message SensorPrivacyServiceDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Is global sensor privacy enabled
+    optional bool is_enabled = 1;
+
+    // Per sensor privacy enabled
+    repeated SensorPrivacyIndividualEnabledSensorProto individual_enabled_sensor = 2;
+}
+
+message SensorPrivacyIndividualEnabledSensorProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    enum Sensor {
+        UNKNOWN = 0;
+
+        MICROPHONE = 1;
+        CAMERA = 2;
+    }
+
+    // Sensor for which privacy might be enabled
+    optional Sensor sensor = 1;
+
+    // If sensor privacy is enabled for this sensor
+    optional bool is_enabled = 2;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 9113111..36d48e2 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -313,39 +313,39 @@
         // The minimum amount of time between quota check alarms.
         optional int64 min_quota_check_delay_ms = 23;
 
-        // The total session limit of the particular standby bucket. Apps in this standby bucket can
-        // only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-        // HPJs).
-        optional int64 hpj_limit_active_ms = 24;
-        // The total session limit of the particular standby bucket. Apps in this standby bucket can
-        // only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-        // HPJs).
-        optional int64 hpj_limit_working_ms = 25;
-        // The total session limit of the particular standby bucket. Apps in this standby bucket can
-        // only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-        // HPJs).
-        optional int64 hpj_limit_frequent_ms = 26;
-        // The total session limit of the particular standby bucket. Apps in this standby bucket can
-        // only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-        // HPJs).
-        optional int64 hpj_limit_rare_ms = 27;
-        // The total session limit of the particular standby bucket. Apps in this standby bucket can
-        // only have HPJ sessions totalling HPJ_LIMIT (without factoring in any rewards or free
-        // HPJs).
-        optional int64 hpj_limit_restricted_ms = 28;
-        // The period of time used to calculate HPJ sessions. Apps can only have HPJ sessions
-        // totalling HPJ_LIMIT_<bucket>_MS within this period of time (without factoring in any
-        // rewards or free HPJs).
-        optional int64 hpj_window_size_ms = 29;
+        // The total expedited job session limit of the particular standby bucket. Apps in this
+        // standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_limit_active_ms = 24;
+        // The total expedited job session limit of the particular standby bucket. Apps in this
+        // standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_limit_working_ms = 25;
+        // The total expedited job session limit of the particular standby bucket. Apps in this
+        // standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_limit_frequent_ms = 26;
+        // The total expedited job session limit of the particular standby bucket. Apps in this
+        // standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_limit_rare_ms = 27;
+        // The total expedited job session limit of the particular standby bucket. Apps in this
+        // standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_limit_restricted_ms = 28;
+        // The period of time used to calculate expedited job sessions. Apps can only have expedited
+        // job sessions totalling EJ_LIMIT_<bucket>_MS within this period of time (without factoring
+        // in any rewards or free EJs).
+        optional int64 expedited_job_window_size_ms = 29;
         // Length of time used to split an app's top time into chunks.
-        optional int64 hpj_top_app_time_chunk_size_ms = 30;
-        // How much HPJ quota to give back to an app based on the number of top app time chunks
+        optional int64 expedited_job_top_app_time_chunk_size_ms = 30;
+        // How much EJ quota to give back to an app based on the number of top app time chunks
         // it had.
-        optional int64 hpj_reward_top_app_ms = 31;
-        // How much HPJ quota to give back to an app based on each non-top user interaction.
-        optional int64 hpj_reward_interaction_ms = 32;
-        // How much HPJ quota to give back to an app based on each notification seen event.
-        optional int64 hpj_reward_notification_seen_ms = 33;
+        optional int64 expedited_job_reward_top_app_ms = 31;
+        // How much EJ quota to give back to an app based on each non-top user interaction.
+        optional int64 expedited_job_reward_interaction_ms = 32;
+        // How much EJ quota to give back to an app based on each notification seen event.
+        optional int64 expedited_job_reward_notification_seen_ms = 33;
 
         // Next tag: 34
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1250eb7..28f5e35 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -393,6 +393,7 @@
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
+    <protected-broadcast android:name="android.net.wifi.action.REFRESH_USER_PROVISIONING" />
     <protected-broadcast android:name="android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION" />
     <protected-broadcast android:name="android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
@@ -1361,7 +1362,7 @@
         android:description="@string/permdesc_systemCamera"
         android:protectionLevel="system|signature" />
 
-    <!-- Allows receiving the camera service notifications when a camera is opened
+    <!-- @SystemApi Allows receiving the camera service notifications when a camera is opened
             (by a certain application package) or closed.
         @hide -->
     <permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER"
@@ -1536,7 +1537,8 @@
     <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
+    <!-- @SystemApi @hide Allows an application to modify the cell broadcasts configuration
+         (i.e. enable or disable channels).
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_CELL_BROADCASTS"
                 android:protectionLevel="signature|privileged" />
@@ -2212,6 +2214,13 @@
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+         Often required in authentication to access the carrier's server and manage services
+         of the subscriber.
+         <p>Protection level: signature|appop -->
+    <permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"
+        android:protectionLevel="signature|appop" />
+
     <!-- @SystemApi Allows read access to emergency number information for ongoing calls or SMS
          sessions.
          @hide Used internally. -->
@@ -2252,7 +2261,9 @@
     <!-- Allows to query ongoing call details and manage ongoing calls
      <p>Protection level: signature|appop -->
     <permission android:name="android.permission.MANAGE_ONGOING_CALLS"
-        android:protectionLevel="signature|appop" />
+        android:protectionLevel="signature|appop"
+        android:label="@string/permlab_manageOngoingCalls"
+        android:description="@string/permdesc_manageOngoingCalls" />
 
     <!-- Allows the app to request network scans from telephony.
          <p>Not for use by third-party applications.
@@ -2379,6 +2390,15 @@
     <permission android:name="android.permission.READ_CARRIER_APP_INFO"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an GbaService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_GBA_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
     <!-- ================================== -->
@@ -2714,6 +2734,10 @@
     <permission android:name="android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an app to prevent non-system-overlay windows from being drawn on top of it -->
+    <permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"
+                android:protectionLevel="normal" />
+
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
     <!-- ================================== -->
@@ -3268,6 +3292,7 @@
          {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
          to hide non-system-overlay windows.
          <p>Not for use by third-party applications.
+         @deprecated Use {@link android.Manifest.permission#HIDE_OVERLAY_WINDOWS} instead
          @hide
     -->
     <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"
@@ -3946,6 +3971,12 @@
     <permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
                 android:protectionLevel="signature" />
 
+    <!-- Allows an application to subscribe to notifications about the presence status change
+         of their associated companion device
+         -->
+    <permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"
+                android:protectionLevel="normal" />
+
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
@@ -3953,6 +3984,14 @@
     <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows an application to rotate a surface by arbitrary degree.
+         This is a sub-feature of ACCESS_SURFACE_FLINGER and can be granted in a more concrete way.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.ROTATE_SURFACE_FLINGER"
+        android:protectionLevel="signature|recents" />
+
     <!-- Allows an application to take screen shots and more generally
          get access to the frame buffer data.
          <p>Not for use by third-party applications.
@@ -4067,6 +4106,14 @@
     <permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows an application to capture the audio from tuner input devices types,
+     such as FM_TUNER.
+
+     <p>Not for use by third-party applications.</p>
+     @hide -->
+    <permission android:name="android.permission.CAPTURE_TUNER_AUDIO_INPUT"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Allows an application to capture audio output.
          Use the {@code CAPTURE_MEDIA_OUTPUT} permission if only the {@code USAGE_UNKNOWN}),
          {@code USAGE_MEDIA}) or {@code USAGE_GAME}) usages are intended to be captured.
@@ -4615,7 +4662,7 @@
     <!-- Allows access to keyguard secure storage.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|setup" />
 
     <!-- Allows applications to set the initial lockscreen state.
          <p>Not for use by third-party applications. @hide -->
@@ -4997,6 +5044,11 @@
     <permission android:name="android.permission.MANAGE_APP_PREDICTIONS"
          android:protectionLevel="signature|appPredictor" />
 
+    <!-- @SystemApi Allows an application to manage the search ui service.
+     @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.MANAGE_SEARCH_UI"
+        android:protectionLevel="signature" />
+
     <!-- Allows an app to set the theme overlay in /vendor/overlay
          being used.
          @hide  <p>Not for use by third-party applications.</p> -->
@@ -5262,7 +5314,7 @@
     <attribution android:tag="TwilightService" android:label="@string/twilight_service"/>
     <!-- Attribution for the Offline LocationTimeZoneProvider, used to detect time zone using
          on-device data -->
-    <attribution android:tag="OfflineLocationTimeZoneProvider"
+    <attribution android:tag="OfflineLocationTimeZoneProviderService"
                  android:label="@string/offline_location_time_zone_detection_service_attribution"/>
 
     <application android:process="system"
@@ -5732,11 +5784,10 @@
 
         <!-- AOSP configures a default secondary LocationTimeZoneProvider that uses an on-device
              data set from the com.android.geotz APEX. -->
-        <uses-library android:name="com.android.location.provider" />
-        <service android:name="com.android.timezone.geotz.provider.OfflineLocationTimeZoneService"
+        <service android:name="com.android.timezone.geotz.provider.OfflineLocationTimeZoneProviderService"
                  android:exported="false">
             <intent-filter>
-                <action android:name="com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider" />
+                <action android:name="android.service.timezone.SecondaryLocationTimeZoneProviderService" />
             </intent-filter>
             <meta-data android:name="serviceVersion" android:value="1" />
             <meta-data android:name="serviceIsMultiuser" android:value="true" />
diff --git a/core/res/OWNERS b/core/res/OWNERS
new file mode 100644
index 0000000..02cf0b7
--- /dev/null
+++ b/core/res/OWNERS
@@ -0,0 +1,18 @@
+adamp@google.com
+alanv@google.com
+dsandler@android.com
+dsandler@google.com
+hackbod@android.com
+hackbod@google.com
+jsharkey@android.com
+jsharkey@google.com
+juliacr@google.com
+michaelwr@google.com
+nandana@google.com
+narayan@google.com
+ogunwale@google.com
+patb@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+toddke@google.com
+yamasani@google.com
diff --git a/core/res/res/drawable-car/car_button_background.xml b/core/res/res/drawable-car/car_button_background.xml
index 3e2610c..e568aeb 100644
--- a/core/res/res/drawable-car/car_button_background.xml
+++ b/core/res/res/drawable-car/car_button_background.xml
@@ -13,24 +13,48 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<!-- Default background styles for car buttons when enabled/disabled. -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:attr/colorControlHighlight">
+<!-- Default background styles for car buttons when enabled/disabled,
+     focused/unfocused, and pressed/unpressed -->
+<!-- TODO(b/175161842) Add rotary fill color -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:state_enabled="false">
+        <shape android:shape="rectangle">
+            <corners android:radius="@*android:dimen/car_button_radius"/>
+            <solid android:color="@*android:color/car_grey_300"/>
+            <stroke android:width="8dp"
+                    android:color="#0059B3"/>
+        </shape>
+    </item>
+    <item android:state_focused="true" android:state_pressed="true">
+        <shape android:shape="rectangle">
+            <corners android:radius="@*android:dimen/car_button_radius"/>
+            <solid android:color="?android:attr/colorButtonNormal"/>
+            <stroke android:width="4dp"
+                    android:color="#0059B3"/>
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape android:shape="rectangle">
+            <corners android:radius="@*android:dimen/car_button_radius"/>
+            <solid android:color="?android:attr/colorButtonNormal"/>
+            <stroke android:width="8dp"
+                    android:color="#0059B3"/>
+        </shape>
+    </item>
+    <item android:state_enabled="false">
+        <shape android:shape="rectangle">
+            <corners android:radius="@*android:dimen/car_button_radius"/>
+            <solid android:color="@*android:color/car_grey_300"/>
+        </shape>
+    </item>
     <item>
-        <selector>
-            <item android:state_enabled="false">
-                <shape android:shape="rectangle">
-                    <corners android:radius="@*android:dimen/car_button_radius"/>
-                    <solid android:color="@*android:color/car_grey_300"/>
-                </shape>
-            </item>
+        <ripple android:color="?android:attr/colorControlHighlight">
             <item>
                 <shape android:shape="rectangle">
                     <corners android:radius="@*android:dimen/car_button_radius"/>
                     <solid android:color="?android:attr/colorButtonNormal"/>
                 </shape>
             </item>
-        </selector>
+        </ripple>
     </item>
-</ripple>
+</selector>
diff --git a/core/res/res/drawable-car/car_switch_thumb.xml b/core/res/res/drawable-car/car_switch_thumb.xml
index 03efc18..66cf443 100644
--- a/core/res/res/drawable-car/car_switch_thumb.xml
+++ b/core/res/res/drawable-car/car_switch_thumb.xml
@@ -14,12 +14,15 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <solid android:color="@color/car_switch"/>
-    <size
-        android:width="@dimen/car_seekbar_thumb_size"
-        android:height="@dimen/car_seekbar_thumb_size"/>
-</shape>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:gravity="center_vertical|fill_horizontal"
+        android:top="@dimen/car_switch_thumb_margin_size"
+        android:bottom="@dimen/car_switch_thumb_margin_size">
+        <shape android:shape="oval">
+            <solid android:color="@color/car_switch"/>
+            <size
+                android:width="@dimen/car_switch_thumb_size"
+                android:height="@dimen/car_switch_thumb_size"/>
+        </shape>
+    </item>
+</layer-list>
diff --git a/core/res/res/drawable-car/car_switch_track.xml b/core/res/res/drawable-car/car_switch_track.xml
new file mode 100644
index 0000000..cb0b9be
--- /dev/null
+++ b/core/res/res/drawable-car/car_switch_track.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+  <item
+    android:height="@dimen/car_touch_target_size_minus_one"
+    android:width="@dimen/car_touch_target_size_minus_one"
+    android:gravity="center">
+    <selector>
+      <item android:state_focused="true" android:state_pressed="true">
+        <shape android:shape="oval">
+          <solid android:color="#8A94CBFF"/>
+          <stroke android:width="4dp"
+              android:color="#94CBFF"/>
+        </shape>
+      </item>
+      <item android:state_focused="true">
+        <shape android:shape="oval">
+          <solid android:color="#3D94CBFF"/>
+          <stroke android:width="8dp"
+              android:color="#94CBFF"/>
+        </shape>
+      </item>
+    </selector>
+  </item>
+  <item android:gravity="center_vertical|fill_horizontal"
+      android:left="@dimen/car_switch_track_margin_size"
+      android:right="@dimen/car_switch_track_margin_size">
+    <shape
+        android:shape="rectangle"
+        android:tint="@color/switch_track_material">
+      <corners android:radius="7dp" />
+      <solid android:color="@color/white_disabled_material" />
+      <size android:height="14dp" />
+      <padding
+          android:right="@dimen/car_switch_track_margin_size"
+          android:left="@dimen/car_switch_track_margin_size"/>
+    </shape>
+  </item>
+</layer-list>
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..7cda03f 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -112,12 +112,12 @@
         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="@dimen/notification_header_separating_margin"
+        android:layout_gravity="center"
         android:scaleType="fitCenter"
         android:src="@drawable/ic_feedback_indicator"
         android:background="?android:selectableItemBackgroundBorderless"
+        android:paddingTop="2dp"
         android:visibility="gone"
         android:contentDescription="@string/notification_feedback_indicator"
         />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 171d896..9f92d72 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-diens"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorkennisgewingdiens"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Skemerdiens"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tydsonebespeurder (geen konnektiwiteit nie)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Jou toestel sal uitgevee word"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Die administrasieprogram kan nie gebruik word nie. Jou toestel sal nou uitgevee word.\n\nKontak jou organisasie se administrateur as jy vrae het."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Druk is gedeaktiveer deur <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Program loop tans"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuut: Venstervergrootglas"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Jy kan nou jou hele skerm of \'n deel daarvan vergroot"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Skakel aan in Instellings"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Maak toe"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5871fe2..bc40003 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -20,12 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="byteShort" msgid="202579285008794431">"B"</string>
+    <string name="byteShort" msgid="202579285008794431">"ባ"</string>
     <string name="kilobyteShort" msgid="2214285521564195803">"ኪባ"</string>
-    <string name="megabyteShort" msgid="6649361267635823443">"MB"</string>
-    <string name="gigabyteShort" msgid="7515809460261287991">"GB"</string>
-    <string name="terabyteShort" msgid="1822367128583886496">"TB"</string>
-    <string name="petabyteShort" msgid="5651571254228534832">"PB"</string>
+    <string name="megabyteShort" msgid="6649361267635823443">"ሜባ"</string>
+    <string name="gigabyteShort" msgid="7515809460261287991">"ጊባ"</string>
+    <string name="terabyteShort" msgid="1822367128583886496">"ቴባ"</string>
+    <string name="petabyteShort" msgid="5651571254228534832">"ፔባ"</string>
     <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="3381766946944136678">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="emptyPhoneNumber" msgid="5812172618020360048">"(ምንም ስልክ ቁጥር የለም)"</string>
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS አገልግሎት"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"የዳሳሽ ማሳወቂያ አገልግሎት"</string>
     <string name="twilight_service" msgid="8964898045693187224">"የውጋገን አገልግሎት"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"የሰዓት ሰቅ አንባቢ (ግንኙነት የለም)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"የዩኤስቢ ግንኙነት"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP እየሠራ ነው"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ማጉላት"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"አዲስ፦ የመስኮት ማጉያ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"አሁን የተወሰነ ወይም ሁሉንም ማያ ገጽዎን ማጉላት ይችላሉ"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b578769..5a18497 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -207,6 +207,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"‏خدمة GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"خدمة إشعارات جهاز الاستشعار"</string>
     <string name="twilight_service" msgid="8964898045693187224">"خدمة الغسق"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"أداة التعرّف على المنطقة الزمنية (ليس هناك حاجة للاتصال بالشبكة)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -299,8 +300,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"‏اتصال USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"التطبيق قيد التشغيل"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"التكبير"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string>
@@ -365,6 +365,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>
@@ -2326,12 +2328,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"‏جديد: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"يمكنك الآن تكبير الشاشة كلها أو جزء منها."</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"التفعيل من خلال \"الإعدادات\""</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"إغلاق"</string>
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index f1b0d84..e087332 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS সেৱা"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"ছেন্সৰ জাননী সেৱা"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight সেৱা"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"সময় মণ্ডল চিনাক্তকাৰী (সংযোগ নাই)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"ইউএছবি সংযোগ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: ৱিণ্ড’ বিৱৰ্ধক"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"আপুনি সকলো অথবা কেইখনমান স্ক্ৰীন বিবৰ্ধন কৰিব পাৰে"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string>
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 01fb48e..2e36aab 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS Xidməti"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Bildiriş Xidməti"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Alaqaranlıq Xidməti"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Saat Qurşağı Aşkarlayıcısı (Bağlantı yoxdur)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız təmizlənəcəkdir"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Admin tətbiqini istifadə etmək mümkün deyil. Cihaz indi təmizlənəcək.\n\nSualınız varsa, təşkilatın admini ilə əlaqə saxlayın."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Çap <xliff:g id="OWNER_APP">%s</xliff:g> tərəfindən deaktiv edildi."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB əlaqə"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tətbiq işləyir"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Böyütmə"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Davam edən zəngləri idarə edin"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Tətbiqə cihazınızda davam edən zənglər haqqında məlumatları görmək və bu zəngləri idarə etmək imkanı verir."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pəncərə Böyüdücüsü"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"İndi ekranı qismən və ya tam şəkildə böyüdə bilərsiniz"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlarda aktiv edin"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Qapadın"</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index bfbd3e4..77220b2 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS usluga"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obaveštenja senzora"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nema internet veze)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti obrisan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećanje"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string>
@@ -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>
@@ -932,7 +934,7 @@
     <string name="granularity_label_link" msgid="9007852307112046526">"link"</string>
     <string name="granularity_label_line" msgid="376204904280620221">"red"</string>
     <string name="factorytest_failed" msgid="3190979160945298006">"Fabričko testiranje nije uspelo"</string>
-    <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u direktorijumu /system/app."</string>
+    <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u folderu /system/app."</string>
     <string name="factorytest_no_action" msgid="339252838115675515">"Nije pronađen nijedan paket koji obezbeđuje radnju FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="2050147445567257365">"Restartuj"</string>
     <string name="js_dialog_title" msgid="7464775045615023241">"Na stranici na adresi „<xliff:g id="TITLE">%s</xliff:g>“ piše:"</string>
@@ -2048,7 +2050,7 @@
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija telefona je dovoljno napunjena. Funkcije više nisu ograničene."</string>
     <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterija tableta je dovoljno napunjena. Funkcije više nisu ograničene."</string>
     <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterija uređaja je dovoljno napunjena. Funkcije više nisu ograničene."</string>
-    <string name="mime_type_folder" msgid="2203536499348787650">"Direktorijum"</string>
+    <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android aplikacija"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string>
     <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> datoteka"</string>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa za prozor"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Možete da uvećate deo ekrana ili ceo ekran"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Podešavanjima"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index c4a3a7e..8c06ad6 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Служба апавяшчэнняў датчыка"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Служба Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Дэтэктар часавога пояса (няма падключэння)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Даныя вашай прылады будуць сцерты"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Немагчыма выкарыстоўваць праграму адміністравання. Звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара арганізацыі."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Друк адключаны ўладальнікам праграмы <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Падключэнне USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Праграма працуе"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Павелічэнне"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string>
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</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>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новая функцыя Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Цяпер можна павялічваць увесь экран ці яго частку."</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Уключыць у Наладах"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Адхіліць"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 07f1ce7..c648398 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Услуга за GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известия за сензорите"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Услуга Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Инструмент за установяване на часовата зона (няма връзка)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Данните на устройството ви ще бъдат изтрити"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Приложението за администриране не може да се използва. Сега данните на устройството ви ще бъдат изтрити.\n\nАко имате въпроси, свържете се с администратора на организацията си."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Отпечатването е деактивиранo от <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB връзка"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложението работи"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Увеличаване на прозорци"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увеличите целия екран или част от него"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включете от настройките"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Отхвърляне"</string>
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 9b85fc7..98ba23c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS পরিষেবা"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"সেন্সর বিজ্ঞপ্তি পরিষেবা"</string>
     <string name="twilight_service" msgid="8964898045693187224">"গোধূলি পরিষেবা"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"টাইম জোন ডিটেক্টর (কানেকশন নেই)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"অ্যাডমিন অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনও প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের অ্যাডমিনের সাথে যোগাযোগ করুন।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> প্রিন্টিং বন্ধ রেখেছে।"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB সংযোগ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"অ্যাপ চলছে"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখুন"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: উইন্ডো ম্যাগনিফায়ার"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"এখন আপনি কিছু বা সবকটি স্ক্রিন বড় করে দেখতে পারেন"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"সেটিংস থেকে চালু করুন"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"বাতিল করুন"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 3d2249b..53a03a7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obavještavanja putem senzora"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Usluga Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Pokrenuta aplikacija"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećavanje"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
@@ -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>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: povećalo prozora"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sada možete uvećati dio ekrana ili cijeli ekran"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f1845e3..5ce2ff2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Servei GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Servei de notificacions de sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Servei Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horària (sense connectivitat)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"El contingut del dispositiu s\'esborrarà"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No es pot utilitzar l\'aplicació d\'administració. S\'esborraran les dades del dispositiu.\n\nSi tens cap dubte, contacta amb l\'administrador de la teva organització."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha desactivat la impressió."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Connexió USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicació en execució"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliació"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
@@ -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>
@@ -1800,8 +1802,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string>
-    <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string>
+    <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Per reduir l\'ús de dades, la funció Economitzador de dades evita que determinades aplicacions enviïn o rebin dades en segon pla. L\'aplicació que estiguis fent servir podrà accedir a les dades, però menys sovint. Això vol dir, per exemple, que les imatges no es mostraran fins que no les toquis."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Activar l\'Economitzador de dades?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activa"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novetat: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ara pots ampliar la pantalla completa o una part"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activa a Configuració"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 42d5636..6840e2d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Služba oznámení ze senzoru"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Služba detekce soumraku"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez připojení)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Zařízení bude vymazáno"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikaci pro správu nelze použít. Zařízení teď bude vymazáno.\n\nV případě dotazů vám pomůže administrátor organizace."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Aplikace <xliff:g id="OWNER_APP">%s</xliff:g> tisk zakazuje."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Připojení USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikace je spuštěna"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zvětšení"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string>
@@ -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>
@@ -1282,7 +1284,7 @@
     <string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string>
     <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string>
     <string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string>
+    <string name="ringtone_silent" msgid="397111123930141876">"Žádné"</string>
     <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string>
     <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string>
     <string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Zvětšení oken"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nyní můžete zvětšit celou obrazovku nebo její část"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnout v Nastavení"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Zavřít"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0487406..d7ff335 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Tjenesten Sensor Notification"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Tjenesten Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszoneregistrering (ingen forbindelse)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheden slettes"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administrationsappen kan ikke bruges. Enheden vil nu blive ryddet. \n\nKontakt din organisations administrator, hvis du har spørgsmål."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Udskrivning er deaktiveret af <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-forbindelse"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Appen kører"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørrelse"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhed: Forstørrelse af vindue"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kan nu forstørre dele af eller hele skærmen"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivér i Indstillinger"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Luk"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index ebbde3c..8038fc9 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-Dienst"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zeitzonen-Erkennung (keine Verbindung)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Die Daten auf deinem Gerät werden gelöscht."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Die Admin-App kann nicht verwendet werden. Die Daten auf deinem Gerät werden nun gelöscht.\n\nBitte wende dich bei Fragen an den Administrator deiner Organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drucken wurde von <xliff:g id="OWNER_APP">%s</xliff:g> deaktiviert."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-Verbindung"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App wird ausgeführt"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergrößerung"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Aktuelle Anrufe verwalten"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ermöglicht einer App, Details zu aktuellen Anrufen auf deinem Gerät zu sehen und diese Anrufe zu verwalten."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Neu: Fenstervergrößerung"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kannst das Display teilweise oder ganz vergrößern"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"In den Einstellungen aktivieren"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Schließen"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 306d36e..aa2ee69 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Υπηρεσία GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Υπηρεσία ειδοποίησης αισθητήρα"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Υπηρεσία Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Εντοπισμός ζώνης ώρας (χωρίς συνδεσιμότητα)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Η συσκευή σας θα διαγραφεί"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Δεν είναι δυνατή η χρήση της εφαρμογής διαχειριστή. Η συσκευή σας θα διαγραφεί.\n\nΕάν έχετε ερωτήσεις, επικοινωνήστε με τον διαχειριστή του οργανισμού σας."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Η εκτύπωση απενεργοποιήθηκε από τον χρήστη <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Σύνδεση USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Η εφαρμογή εκτελείται"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Μεγιστοποίηση"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Νέο: Μεγέθυνση παραθύρου"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Μεγεθύνετε μέρος ή ολόκληρη την οθόνη σας"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ενεργοποίηση στις Ρυθμίσεις"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Παράβλεψη"</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index a8706cb..de5dba2 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 57e2eae..7bd62aa 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 33ffbe3..b21b67d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 f5be6fd..69acec6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 cd3ff36..ae57206 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎GNSS Service‎‏‎‎‏‎"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎Sensor Notification Service‎‏‎‎‏‎"</string>
     <string name="twilight_service" msgid="8964898045693187224">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎Twilight Service‎‏‎‎‏‎"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎Time Zone Detector (No connectivity)‎‏‎‎‏‎"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎Your device will be erased‎‏‎‎‏‎"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎The admin app can\'t be used. Your device will now be erased.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎If you have questions, contact your organization\'s admin.‎‏‎‎‏‎"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎Printing disabled by ‎‏‎‎‏‏‎<xliff:g id="OWNER_APP">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
@@ -352,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 2d521b3..f5bd810 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Servicio de Sistemas Globales de Navegación por Satélites (GNSS)"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificaciones del sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Se borrarán los datos del dispositivo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No se puede usar la app de administrador. Ahora se borrará tu dispositivo.\n\nSi tienes preguntas, comunícate con el administrador de tu organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> inhabilitó la impresión."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App en ejecución"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nueva: Ampliación de ventanas"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Puedes ampliar toda tu pantalla o parte de ella"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Descartar"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index abc6946..e234efbf 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Servicio GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificación de sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Tu dispositivo se borrará"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"No se puede utilizar la aplicación de administración. Se borrarán todos los datos del dispositivo.\n\nSi tienes alguna pregunta, ponte en contacto con el administrador de tu organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha inhabilitado la impresión."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicación en ejecución"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
@@ -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>
@@ -832,7 +834,7 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Introduce el código PIN para desbloquear."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"Código PIN incorrecto"</string>
     <string name="keyguard_label_text" msgid="3841953694564168384">"Para desbloquear el teléfono, pulsa la tecla de menú y, a continuación, pulsa 0."</string>
-    <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Llamada de emergencia"</string>
+    <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Número de emergencia"</string>
     <string name="lockscreen_carrier_default" msgid="6192313772955399160">"Sin servicio"</string>
     <string name="lockscreen_screen_locked" msgid="7364905540516041817">"Pantalla bloqueada"</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pulsa la tecla de menú para desbloquear el teléfono o realizar una llamada de emergencia."</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuevo: Lupa de ventanas"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ahora puedes ampliar toda la pantalla o una parte"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Ajustes"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Cerrar"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 130ef6e..543b5a1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-teenus"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Anduri märguande teenus"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Teenus Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ajavööndi tuvastaja (ühenduvus puudub)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seade kustutatakse"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administraatori rakendust ei saa kasutada. Teie seade tühjendatakse nüüd.\n\nKui teil on küsimusi, võtke ühendust organisatsiooni administraatoriga."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Rakendus <xliff:g id="OWNER_APP">%s</xliff:g> on printimise keelanud."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-ühendus"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Rakendus töötab"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurendus"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uus: akna suurendaja"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nüüd saab suurendada kogu ekraanikuva või osa sellest"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Lülitage sisse menüüs Seaded"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Loobu"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 5273a48..c552e8f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS zerbitzua"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sentsorearen jakinarazpen-zerbitzua"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Ilunabarreko zerbitzua"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ordu-zonaren hautemailea (ez zaude konektatuta sarera)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Gailuko datuak ezabatu egingo dira"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ezin da erabili administratzeko aplikazioa. Ezabatu egingo da gailuko eduki guztia.\n\nZalantzarik baduzu, jarri erakundeko administratzailearekin harremanetan."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> aplikazioak desgaitu egin du inprimatzeko aukera."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB konexioa"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikazio bat abian da"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Lupa"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
@@ -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>
@@ -500,7 +502,7 @@
     <string name="permdesc_changeNetworkState" msgid="649341947816898736">"Sarearen konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_changeTetherState" msgid="9079611809931863861">"aldatu telefono bidezko konektagarritasuna"</string>
     <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string>
-    <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi bidezko konexioak"</string>
+    <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi-konexioak"</string>
     <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Wi-Fi sareei buruzko informazioa ikusteko baimena ematen die aplikazioei, adibidez, Wi-Fi konexioa aktibatuta dagoen eta konektatutako Wi-Fi gailuen izenak zein diren."</string>
     <string name="permlab_changeWifiState" msgid="7947824109713181554">"konektatu wifira edo deskonektatu bertatik"</string>
     <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Berria: leihoen lupa"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Orain, pantaila osoa edo haren zati bat handi dezakezu"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktibatu ezarpenetan"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Baztertu"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7596bab..3d523fd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"‏سرویس GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"سرویس اعلان حسگر"</string>
     <string name="twilight_service" msgid="8964898045693187224">"‏سرویس Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"شناساگر منطقه زمانی (بدون اتصال)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمی‌توان استفاده کرد. دستگاه شما در این لحظه پاک می‌شود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"‏اتصال USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"برنامه درحال اجرا"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامه‌های مصرف‌کننده باتری"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"درشت‌نمایی"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"‏جدید: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اکنون می‌توانید بخشی از صفحه یا کل آن را درشت کنید"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index d337315..81546d9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-palvelu"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Anturin ilmoituspalvelu"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight-palvelu"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Aikavyöhykkeen tunnistin (ei yhteyttä)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Laitteen tiedot poistetaan"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Hallintasovellusta ei voi käyttää. Laitteen tiedot pyyhitään.\n\nPyydä ohjeita järjestelmänvalvojaltasi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> on poistanut tulostuksen käytöstä."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-yhteys"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Sovellus käynnissä"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurennus"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uutta: ikkunan suurennus"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Voit nyt suurentaa näytön osittain tai kokonaan"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Laita päälle asetuksista"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Hylkää"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d2c89bc..55e916e 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -52,7 +52,6 @@
     <string name="enablePin" msgid="2543771964137091212">"Opération infructueuse. Activez le verrouillage SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée.</item>
-      <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM soit verrouillée.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"Code IIEM"</string>
@@ -180,7 +179,6 @@
     <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">Autorité de certification installée</item>
-      <item quantity="many">Certificate authorities installed</item>
       <item quantity="other">Autorités de certification installées</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -201,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification de capteur"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Service de crépuscule"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Détecteur de fuseau horaire (aucune connectivité)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -255,7 +254,6 @@
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bogue. Aucune capture d\'écran supplémentaire ne peut être capturée, et vous ne pouvez entrer aucune autre information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
       <item quantity="one">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde.</item>
-      <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran prise avec le rapport de bogue"</string>
@@ -290,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string>
@@ -356,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gérer les appels en cours"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Autorise une application à afficher les renseignements concernant les appels en cours sur votre appareil et à les gérer."</string>
     <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>
@@ -1006,7 +1005,6 @@
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
       <item quantity="one">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1029,82 +1027,66 @@
     <string name="now_string_shortest" msgid="3684914126941650330">"maintenant"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
       <item quantity="one">il y a<xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other">il y a<xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1477,7 +1459,6 @@
     <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
       <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"Terminé"</string>
@@ -1611,7 +1592,6 @@
     <string name="kg_wrong_pin" msgid="3680925703673166482">"NIP incorrect."</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
       <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="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1798,7 +1778,6 @@
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le NIP est trop court. Il doit comporter au moins 4 chiffres."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
-      <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Réessayez plus tard"</string>
@@ -1830,42 +1809,34 @@
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
       <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
       <item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
       <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
       <item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
       <item quantity="one">Pendant %d minute</item>
-      <item quantity="many">For %d minutes</item>
       <item quantity="other">Pendant %d minutes</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
       <item quantity="one">Pendant %d min</item>
-      <item quantity="many">For %d min</item>
       <item quantity="other">Pendant %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
       <item quantity="one">Pendant %d heure</item>
-      <item quantity="many">For %d hours</item>
       <item quantity="other">Pendant %d heures</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
       <item quantity="one">Pendant %d h</item>
-      <item quantity="many">For %d hr</item>
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1907,7 +1878,6 @@
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1975,7 +1945,6 @@
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de remplissage automatique"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de remplissage automatique</item>
-      <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de remplissage automatique</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
@@ -2070,7 +2039,6 @@
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement en cours…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
-      <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
@@ -2224,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveauté : Loupe de fenêtre"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir une partie ou la totalité de votre écran"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1992068..3a0d0cd 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -52,7 +52,6 @@
     <string name="enablePin" msgid="2543771964137091212">"Échec de l\'opération. Veuillez activer le verrouillage de la carte SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée.</item>
-      <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"Code IMEI"</string>
@@ -180,7 +179,6 @@
     <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">Autorité de certification installée</item>
-      <item quantity="many">Certificate authorities installed</item>
       <item quantity="other">Autorités de certification installées</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -201,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification du capteur"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Service Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Outil de détection du fuseau horaire (aucune connectivité)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Les données de votre appareil vont être effacées"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, contactez l\'administrateur de votre organisation."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -255,7 +254,6 @@
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bug. Aucune capture d\'écran supplémentaire ne peut être prise, et vous ne pouvez saisir aucune autre information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
       <item quantity="one">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde</item>
-      <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran avec rapport de bug effectuée"</string>
@@ -290,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string>
@@ -356,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gérer les appels en cours"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Autorise une application à afficher les détails concernant les appels en cours sur votre appareil et à contrôler ces appels."</string>
     <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>
@@ -1006,7 +1005,6 @@
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
       <item quantity="one">Le dernier jour (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
-      <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Les <xliff:g id="COUNT_1">%d</xliff:g> derniers jours</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1029,82 +1027,66 @@
     <string name="now_string_shortest" msgid="3684914126941650330">"mainten."</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1477,7 +1459,6 @@
     <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
       <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"OK"</string>
@@ -1611,7 +1592,6 @@
     <string name="kg_wrong_pin" msgid="3680925703673166482">"Code PIN incorrect."</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
       <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="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1798,7 +1778,6 @@
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le code PIN est trop court. Il doit comporter au moins 4 chiffres."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
-      <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Veuillez réessayer ultérieurement."</string>
@@ -1823,49 +1802,41 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n·• active le thème sombre ;\n·• désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n • active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n• active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\"."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Pour réduire la consommation de données, l\'économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Ainsi, les applications que vous utilisez peuvent toujours accéder aux données, mais pas en permanence. Par exemple, il se peut que les images ne s\'affichent pas tant que vous n\'appuyez pas dessus."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données ?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
       <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
       <item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
       <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
       <item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
       <item quantity="one">Pendant %d minute</item>
-      <item quantity="many">For %d minutes</item>
       <item quantity="other">Pendant %d minutes</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
       <item quantity="one">Pendant %d min</item>
-      <item quantity="many">For %d min</item>
       <item quantity="other">Pendant %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
       <item quantity="one">Pendant %d heure</item>
-      <item quantity="many">For %d hours</item>
       <item quantity="other">Pendant %d heures</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
       <item quantity="one">Pendant %d h</item>
-      <item quantity="many">For %d hr</item>
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1907,7 +1878,6 @@
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1975,7 +1945,6 @@
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de saisie automatique"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de saisie automatique</item>
-      <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de saisie automatique</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
@@ -2070,7 +2039,6 @@
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
-      <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
@@ -2224,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveau : agrandissement de la fenêtre"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir tout ou partie de l\'écran"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 7583502..8c21193 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Servizo GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Servizo de notificacións dos sensores"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Servizo Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horario (non require conexión)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Borrarase o teu dispositivo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Non se pode utilizar a aplicación de administración. Borrarase o teu dispositivo.\n\nSe tes preguntas, contacta co administrador da organización."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> desactivou a impresión."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"conexión USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Estase executando a aplicación"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Xestionar as chamadas saíntes"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que unha aplicación controle as chamadas saíntes do teu dispositivo e consulte os detalles sobre elas."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nova función: Lupa de ventá"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Agora podes ampliar toda a pantalla ou parte dela"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string>
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6f140c4..48edb0c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS સેવા"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"સેન્સર નોટિફિકેશન સેવા"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ટ્વાઇલાઇટ સેવા"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"સમય ઝોન શોધવાની સુવિધા (કનેક્ટિવિટી જરૂરી નથી)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"વ્યવસ્થાપક ઍપનો ઉપયોગ કરી શકાશે નહીં. તમારું ઉપકરણ હવે કાઢી નાખવામાં આવશે.\n\nજો તમને પ્રશ્નો હોય, તો તમારી સંસ્થાના વ્યવસ્થાપકનો સંપર્ક કરો."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> દ્વારા પ્રિન્ટ કરવાનું બંધ કરાયું છે."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB કનેક્શન"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ઍપ ચાલી રહ્યું છે"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"મોટું કરવાની સુવિધા"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"નવી: વિંડો મોટી કરવાની સુવિધા"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"હવે તમે તમારી કેટલીક કે આખી સ્ક્રીનને મોટી કરી શકો છો"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"સેટિંગમાં ચાલુ કરો"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"છોડી દો"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5892dab..e63e502 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"जीएनएसएस सेवा"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"सेंसर से जुड़ी सूचना सेवा"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट समय बताने वाली सेवा"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र का पता लगाने वाली सुविधा (ऑफ़लाइन होने पर)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"आपके डिवाइस को मिटा दिया जाएगा"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"एडमिन ऐप्लिकेशन का इस्तेमाल नहीं किया जा सकता. आपके डिवाइस पर मौजूद डेटा अब मिटा दिया जाएगा.\n\nअगर आप कुछ पूछना चाहते हैं तो, अपने संगठन के एडमिन से संपर्क करें."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ने प्रिंटिंग सुविधा बंद कर दी है."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ऐप अभी इस्तेमाल हो रहा है"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ज़ूम करने की सुविधा"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नई सुविधा: विंडो को ज़ूम करके देखने की सुविधा"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"अब अपनी पूरी स्क्रीन या कुछ हिस्से को ज़ूम करके देख सकते हैं"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग में जाकर, इस सुविधा को चालू करें"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"खारिज करें"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f4d9842..45c89a6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS-a"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga Obavijesti senzora"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će se izbrisati"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratorska aplikacija ne može se upotrebljavati. Uređaj će se izbrisati.\n\nAko imate pitanja, obratite se administratoru organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Ispis je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Izvodi se aplikacija"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povećavanje"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string>
@@ -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>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: alat za povećanje prozora"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sad možete povećati dio zaslona ili cijeli zaslon"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index bff1773..9525801 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-szolgáltatás"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Szenzoros értesítési szolgáltatás"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight szolgáltatás"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Időzóna-felismerő (Offline)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"A rendszer törölni fogja eszközét"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"A rendszergazdai alkalmazás nem használható. A rendszer most törli az eszközt.\n\nKérdéseivel forduljon szervezete rendszergazdájához."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"A(z) <xliff:g id="OWNER_APP">%s</xliff:g> letiltotta a nyomtatást."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-kapcsolat"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Jelenleg futó alkalmazás"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Nagyítás"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Folyamatban lévő hívások kezelése"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Engedélyezi az alkalmazásnak, hogy az eszközén folyamatban lévő hívások részleteihez hozzáférjen, és vezérelje ezeket a hívásokat."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Újdonság: Ablaknagyító"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ezután nagyíthatja a képernyőt vagy egy részét"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bekapcsolás a Beállításokban"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Elvetés"</string>
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1f2e642..b28e5fd 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS ծառայություն"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Տվիչների ծանուցումների մշակման ծառայություն"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Մթնշաղի սկիզբը որոշող ծառայություն"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ժամային գոտու դետեկտոր (աշխատում է առանց ինտերնետի)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Ձեր սարքը ջնջվելու է"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Հնարավոր չէ օգտագործել ադմինիստրատորի հավելվածը։ Ձեր սարքից բոլոր տվյալները կջնջվեն։\n\nՀարցեր ունենալու դեպքում դիմեք ձեր կազմակերպության ադմինիստրատորին։"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Տպումն անջատված է <xliff:g id="OWNER_APP">%s</xliff:g> հավելվածի կողմից։"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB կապակցում"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Հավելվածն աշխատում է"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Խոշորացում"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Նոր գործառույթ. Պատուհանի խոշորացույց"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Այժմ կարող եք խոշորացնել ամբողջ էկրանը կամ դրա մի մասը"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Միացնել կարգավորումներում"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Փակել"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 4f26eb6..e6b4977 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Layanan GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Layanan Notifikasi Sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Layanan Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pendeteksi Zona Waktu (Tidak ada konektivitas)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Perangkat akan dihapus"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikasi admin tidak dapat digunakan. Perangkat Anda kini akan dihapus.\n\nJika ada pertanyaan, hubungi admin organisasi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Fitur pencetakan dinonaktifkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikasi berjalan"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Mengelola panggilan yang sedang berlangsung"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Mengizinkan aplikasi untuk melihat detail panggilan yang sedang berlangsung di perangkat dan mengontrolnya."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baru: Pembesar Jendela"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Anda bisa memperbesar sebagian atau seluruh layar"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktifkan di Setelan"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Tutup"</string>
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index d5539a3..867fca8 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-þjónusta"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Tilkynningaþjónusta nema"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Ljósaskiptaþjónusta"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tímabeltisgreinir (engin tenging)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Tækið verður hreinsað"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Ekki er hægt að nota stjórnunarforritið. Tækinu verður eytt.\n\nEf spurningar vakna skaltu hafa samband við kerfisstjóra fyrirtækisins."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> lokaði á prentun."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tenging"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Forrit er í gangi"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Stækkun"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
@@ -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>
@@ -1801,7 +1803,7 @@
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
     <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“\n\n"<annotation id="url">"Frekari upplýsingar"</annotation></string>
-    <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string>
+    <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n• Kveikir á dökku þema\n• Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Gagnasparnaður getur hjálpað til við að draga úr gagnanotkun með því að hindra forrit í að senda eða sækja gögn í bakgrunni. Forrit sem er í notkun getur náð í gögn, en gerir það kannski sjaldnar. Niðurstaðan getur verið, svo dæmi sé tekið, að myndir eru ekki birtar fyrr en þú ýtir á þær."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Kveikja á gagnasparnaði?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Kveikja"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nýtt: Gluggastækkun"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nú geturðu stækkað allan skjáinn eða hluta hans"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Kveikja á í stillingum"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Hunsa"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 152cfee..6f2e158 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Servizio GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Servizio di notifica dei sensori"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Servizio Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Rilevatore di fuso orario (connessione a Internet non necessaria)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Il dispositivo verrà resettato"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Impossibile usare l\'app di amministrazione. Il dispositivo verrà resettato.\n\nPer eventuali domande, contatta l\'amministratore della tua organizzazione."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Stampa disattivata da <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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>
@@ -1451,7 +1454,7 @@
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tocca per uscire dall\'app di guida."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Indietro"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Avanti"</string>
-    <string name="skip_button_label" msgid="3566599811326688389">"Ignora"</string>
+    <string name="skip_button_label" msgid="3566599811326688389">"Salta"</string>
     <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string>
     <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
@@ -1799,8 +1802,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\"\n\n"<annotation id="url">"Ulteriori informazioni"</annotation></string>
-    <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\""</string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\"\n\n"<annotation id="url">"Scopri di più"</annotation></string>
+    <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\""</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5ae9436..2846508 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"‏שירות GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"שירות להתראות מחיישנים"</string>
     <string name="twilight_service" msgid="8964898045693187224">"שירות דמדומים"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"מזהה אזור זמן (ללא צורך בקישוריות)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"תתבצע מחיקה של המכשיר"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"לא ניתן להשתמש באפליקציה של מנהל המערכת.\n\nאם יש לך שאלות, יש ליצור קשר עם מנהל המערכת של הארגון."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ההדפסה הושבתה על ידי <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"‏חיבור USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"אפליקציה פועלת"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"הגדלה"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string>
@@ -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>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"‏חדש: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"עכשיו אפשר להגדיל את המסך או חלקים ממנו"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"הפעלה בהגדרות"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"סגירה"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7a54a15..c6e8a14 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS サービス"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"センサー通知サービス"</string>
     <string name="twilight_service" msgid="8964898045693187224">"トワイライト サービス"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector(未接続)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"管理アプリを使用できません。デバイスのデータはこれから消去されます。\n\nご不明な点がある場合は、組織の管理者にお問い合わせください。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」により印刷は無効にされています。"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB 接続"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"実行中のアプリ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップして電池やデータの使用量を確認"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新機能: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"画面の一部または全体を拡大できるようになりました"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"[設定] で ON にする"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"閉じる"</string>
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1653cb9..912930f 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS სერვისი"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"სენსორის შეტყობინების სერვისი"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight სერვისი"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"სასაათო სარტყლის დეტექტორი (კავშირის გარეშე)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"თქვენი მოწყობილობა წაიშლება"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ადმინისტრატორის აპის გამოყენება ვერ მოხერხდება. თქვენი მოწყობილობა ახლა ამოიშლება.\n\nთუ შეკითხვები გაქვთ, დაუკავშირდით თქვენი ორგანიზაციის ადმინისტრატორს."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ბეჭდვა გათიშულია <xliff:g id="OWNER_APP">%s</xliff:g>-ის მიერ."</string>
@@ -352,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 635fed7..d615538 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS қызметі"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Датчик хабарландыруы қызметі"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight қызметі"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Уақыт белдеуін анықтағыш (қосылу мүмкіндігі жоқ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Құрылғыңыздағы деректер өшіріледі"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Әкімші қолданбасын пайдалану мүмкін емес. Қазір құрылғыдағы деректер өшіріледі\n\nСұрақтарыңыз болса, ұйым әкімшісіне хабарласыңыз."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Басып шығаруды <xliff:g id="OWNER_APP">%s</xliff:g> өшірді."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB байланысы"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Қолданба қосулы"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ұлғайту"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңа: Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Енді экранның бір бөлігін не барлығын ұлғайта аласыз."</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Параметрлер бөлімінен қосу"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Қабылдамау"</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 1160a40..075a652 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"សេវាកម្ម GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"សេវាកម្ម​ជូនដំណឹង​ឧបករណ៍​ចាប់សញ្ញា"</string>
     <string name="twilight_service" msgid="8964898045693187224">"សេវាកម្ម​ព្រលប់"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ឧបករណ៍សម្គាល់​ល្វែងម៉ោង (គ្មានការតភ្ជាប់ទេ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"មិនអាច​ប្រើ​កម្មវិធី​អ្នកគ្រប់គ្រង​បានទេ។ ឧបករណ៍​របស់អ្នក​នឹងលុប​ឥឡូវនេះ។\n\nប្រសិនបើ​អ្នកមាន​សំណួរផ្សេងៗ​ សូមទាក់ទង​ទៅអ្នក​គ្រប់គ្រង​ស្ថាប័ន​របស់​អ្នក។"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ការបោះពុម្ព​ត្រូវបាន​បិទ​ដោយ <xliff:g id="OWNER_APP">%s</xliff:g> ។"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"ការ​តភ្ជាប់ USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"កម្មវិធី​ដែល​កំពុង​ដំណើរការ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែល​កំពុងប្រើថ្ម"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ការពង្រីក"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ថ្មី៖ កម្មវិធីពង្រីក​វិនដូ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ឥឡូវនេះ អ្នកអាចពង្រីកផ្នែកខ្លះ ឬទាំងអស់នៃអេក្រង់របស់អ្នក"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"បើកនៅក្នុងការកំណត់"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ច្រានចោល"</string>
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 8eb3467..61ed9b3 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS ಸೇವೆ"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"ಸೆನ್ಸರ್ ಅಧಿಸೂಚನೆ ಸೇವೆ"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ಟ್ವಿಲೈಟ್ ಸೇವೆ"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ಸಮಯವಲಯ  ಡಿಟೆಕ್ಟರ್ (ಯಾವುದೇ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಇಲ್ಲ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ಇದೀಗ ಅಳಿಸಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮಲ್ಲಿ ಪ್ರಶ್ನೆಗಳಿದ್ದರೆ, ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ಮೂಲಕ ಪ್ರಿಂಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB ಸಂಪರ್ಕ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App ರನ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ಹೊಸದು: ವಿಂಡೋ ಮ್ಯಾಗ್ನಿಫೈಯರ್"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ಈಗ ಕೆಲವು ಅಥವಾ ಎಲ್ಲಾ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಿಗ್ಗಿಸಬಹುದು"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಆನ್ ಮಾಡಿ"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ವಜಾಗೊಳಿಸಿ"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 46b4a1b..b20a427 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS 서비스"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"센서 알림 서비스"</string>
     <string name="twilight_service" msgid="8964898045693187224">"새벽 서비스"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"시간대 감지(연결되지 않음)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"기기가 삭제됩니다."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"관리자 앱을 사용할 수 없습니다. 곧 기기가 삭제됩니다.\n\n궁금한 점이 있으면 조직의 관리자에게 문의하세요."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g>에 의해 사용 중지되었습니다."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB 연결"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"실행 중인 앱"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"확대"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"새로운 기능: 창 돋보기"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"이제 화면 일부 또는 전체를 확대할 수 있습니다."</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"설정에서 사용 설정"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"닫기"</string>
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index bb005f3..1e8b38b 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS кызматы"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Сенсордун билдирмелеринин кызматы"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight кызматы"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Убакыт алкагын аныктагыч (байланыш жок)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Түзмөгүңүз тазаланат"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Түзмөктү башкаруучу колдонмо жараксыз. Түзмөгүңүз азыр тазаланат.\n\nСуроолоруңуз болсо, ишканаңыздын администраторуна кайрылыңыз."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Басып чыгаруу <xliff:g id="OWNER_APP">%s</xliff:g> тарабынан өчүрүлдү."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB аркылуу туташуу"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Колдонмо иштеп жатат"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Чоңойтуу"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
@@ -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>
@@ -1800,8 +1802,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими төмөнкүлөрдү аткарат:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string>
-    <string name="battery_saver_description" msgid="6794188153647295212">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режиминде:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string>
+    <string name="battery_saver_description" msgid="6794188153647295212">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Трафикти үнөмдөө режиминде айрым колдонмолор дайын-даректерди фондо өткөрө алышпайт. Учурда сиз пайдаланып жаткан колдонмо дайын-даректерди жөнөтүп/ала алат, бирок адаттагыдан азыраак өткөргөндүктөн, анын айрым функциялары талаптагыдай иштебей коюшу мүмкүн. Мисалы, сүрөттөр басылмайынча жүктөлбөйт."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикти үнөмдөө режимин иштетесизби?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Күйгүзүү"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңы функция: Терезе чоңойткуч"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Эми толук экранды же анын бөлүгүн чоңойто аласыз"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Жөндөөлөрдөн күйгүзүү"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Жабуу"</string>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 8e4e467..c60d594 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"ບໍລິການ GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"ບໍລິການການແຈ້ງເຕືອນເຊັນເຊີ"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ບໍລິການ Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ຕົວກວດຫາເຂດເວລາ (ບໍ່ມີການເຊື່ອມຕໍ່)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ລຶບ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ບໍ່ສາມາດໃຊ້ແອັບຜູ້ເບິ່ງແຍງລະບົບໄດ້. ອຸປະກອນຂອງທ່ານຈະຖືກລຶບຂໍ້ມູນໃນຕອນນີ້.\n\nຫາກທ່ານມີຄຳຖາມ, ໃຫ້ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບອົງກອນຂອງທ່ານ."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ການພິມຖືກປິດໄວ້ໂດຍ <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"ການເຊື່ອມຕໍ່ USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ແອັບກຳລັງເຮັດວຽກ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ການຂະຫຍາຍ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ໃໝ່: ຕົວຂະຫຍາຍໜ້າຈໍ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ຕອນນີ້ທ່ານສາມາດຂະຫຍາຍບາງສ່ວນ ຫຼື ທັງໝົດຂອງໜ້າຈໍໄດ້"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ເປີດໃຊ້ໃນການຕັ້ງຄ່າ"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ປິດໄວ້"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a922716..39cbbe1 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS paslauga"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Jutiklių pranešimų paslauga"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Paslauga „Twilight“"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laiko juostos aptikimo priemonė (nėra ryšio)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Įrenginys bus ištrintas"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratoriaus programos negalima naudoti. Dabar įrenginio duomenys bus ištrinti.\n\nJei turite klausimų, susisiekite su organizacijos administratoriumi."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Neleidžiama spausdinti (<xliff:g id="OWNER_APP">%s</xliff:g>)."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB jungtis"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programa paleista"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Didinimas"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string>
@@ -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>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nauja: „Window Magnifier“"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Dabar galite padidinti dalį ekrano ar jį visą"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Įjungti nustatymuose"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Atmesti"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 2fec712..edc8728 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS pakalpojums"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensoru paziņojumu pakalpojums"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Krēslas noteikšanas pakalpojums"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laika joslas noteikšanas rīks (nav savienojuma)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Jūsu ierīces dati tiks dzēsti"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratora lietotni nevar izmantot. Ierīcē saglabātie dati tiks dzēsti.\n\nJa jums ir kādi jautājumi, sazinieties ar savas organizācijas administratoru."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drukāšanu atspējoja <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB savienojums"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Lietotne darbojas"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Palielinājums"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string>
@@ -356,6 +356,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Aktīvo zvanu pārvaldība"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ļauj lietotnei skatīt detalizētu informāciju par aktīvajiem zvaniem jūsu ierīcē, kā arī kontrolēt šos zvanus."</string>
     <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>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Jaunums: funkcija Window Magnifier"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tagad varat palielināt ekrāna daļu vai visu ekrānu"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ieslēgt sadaļā Iestatījumi"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Nerādīt"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 3d02757..63375f5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Услуга GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известување од сензорот"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Услуга за самрак"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Откривач на временска зона (не може да се поврзе)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Уредот ќе се избрише"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Апликацијата на администраторот не може да се користи. Уредот ќе се избрише сега.\n\nАко имате прашања, контактирајте со администраторот на организацијата."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Печатењето е оневозможено од <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-врска"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апликацијата работи"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Зголемување"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот сообраќај"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: „Лупа за прозорци“"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Сега може се зголеми целиот екран или само дел"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Вклучи во „Поставки“"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Отфрли"</string>
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 583c46e..a027b4c 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS സേവനം"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"സെൻസർ അറിയിപ്പ് സേവനം"</string>
     <string name="twilight_service" msgid="8964898045693187224">"സന്ധ്യാസമയത്തെ സേവനം"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"സമയമേഖല കണ്ടെത്താനുള്ള സംവിധാനം (കണക്റ്റിവിറ്റി ഇല്ല)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"നിങ്ങളുടെ ഉപകരണം മായ്‌ക്കും"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"അഡ്‌മിൻ ആപ്പ് ഉപയോഗിക്കാനാകില്ല. നിങ്ങളുടെ ഉപകരണം ഇപ്പോൾ മായ്ക്കപ്പെടും.\n\nനിങ്ങൾക്ക് ചോദ്യങ്ങൾ ഉണ്ടെങ്കിൽ, നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ അഡ്‌മിനെ ബന്ധപ്പെടുക."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> പ്രിന്റിംഗ് പ്രവർത്തനരഹിതമാക്കി."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB കണക്ഷൻ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ആപ്പ് പ്രവർത്തിക്കുന്നു"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"മാഗ്നിഫിക്കേഷൻ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"പുതിയത്: വിൻഡോ മാഗ്നിഫൈയർ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"സ്ക്രീനിന്റെ ഭാഗങ്ങളോ മുഴുവനുമോ മാഗ്നിഫൈ ചെയ്യാം"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ക്രമീകരണത്തിൽ ഓണാക്കുക"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ഡിസ്‌മിസ് ചെയ്യുക"</string>
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 081e170..366a5b7 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -48,7 +48,7 @@
     <string name="invalidPin" msgid="7542498253319440408">"4-8 тооноос бүтэх PIN-г бичнэ үү."</string>
     <string name="invalidPuk" msgid="8831151490931907083">"8-с цөөнгүй тооноос бүтэх PUK-г бичнэ үү."</string>
     <string name="needPuk" msgid="7321876090152422918">"SIM картны PUK-түгжигдсэн. Тайлах бол PUK кодыг бичнэ үү."</string>
-    <string name="needPuk2" msgid="7032612093451537186">"SIM картын хаалтыг болиулах бол PUK2-г бичнэ үү."</string>
+    <string name="needPuk2" msgid="7032612093451537186">"SIM картыг блокоос гаргах бол PUK2-г бичнэ үү."</string>
     <string name="enablePin" msgid="2543771964137091212">"Амжилтгүй боллоо, СИМ/РҮИМ түгжээг идэвхжүүлнэ үү."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="other">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS үйлчилгээ"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Мэдрэгчийн мэдэгдлийн үйлчилгээ"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight үйлчилгээ"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Цагийн бүс илрүүлэгч (Холболт байхгүй)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Таны төхөөрөмж устах болно."</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Админ аппыг ашиглах боломжгүй. Таны төхөөрөмжийг одоо устгана.\n\nХэрэв танд асуулт байгаа бол байгууллагынхаа админтай холбогдоно уу."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> хэвлэх үйлдлийг идэвхгүй болгосон."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB холболт"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апп ажиллаж байна"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Томруулах"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string>
@@ -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>
@@ -480,10 +482,10 @@
     <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Апп-д таблетын хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
     <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Аппад таны Android TV төхөөрөмжийн хэт улаан туяаны дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
     <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Апп-д утасны хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string>
-    <string name="permlab_setWallpaper" msgid="6959514622698794511">"ханын зургийг тохируулах"</string>
-    <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн ханын зургийг тохируулах боломжтой."</string>
-    <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны ханын зурагны хэмжээг тохируулах"</string>
-    <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн ханын зургийн хэмжээний саналыг тохируулах боломжтой"</string>
+    <string name="permlab_setWallpaper" msgid="6959514622698794511">"дэлгэцийн зургийг тохируулах"</string>
+    <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн дэлгэцийн зургийг тохируулах боломжтой."</string>
+    <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны дэлгэцийн зургийн хэмжээг тохируулах"</string>
+    <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн дэлгэцийн зургийн хэмжээний саналыг тохируулах боломжтой"</string>
     <string name="permlab_setTimeZone" msgid="7922618798611542432">"цагийн бүсийн тохиргоо"</string>
     <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Апп нь таблетын цагийн бүсийг солих боломжтой."</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Аппад таны Android TV төхөөрөмжийн цагийн бүсийг өөрчлөхийг зөвшөөрнө."</string>
@@ -1429,8 +1431,8 @@
     <string name="input_method_binding_label" msgid="1166731601721983656">"Оруулах арга"</string>
     <string name="sync_binding_label" msgid="469249309424662147">"Синк"</string>
     <string name="accessibility_binding_label" msgid="1974602776545801715">"Хандалт"</string>
-    <string name="wallpaper_binding_label" msgid="1197440498000786738">"Ханын зураг"</string>
-    <string name="chooser_wallpaper" msgid="3082405680079923708">"Ханын зураг солих"</string>
+    <string name="wallpaper_binding_label" msgid="1197440498000786738">"Дэлгэцийн зураг"</string>
+    <string name="chooser_wallpaper" msgid="3082405680079923708">"Дэлгэцийн зураг солих"</string>
     <string name="notification_listener_binding_label" msgid="2702165274471499713">"Мэдэгдэл сонсогч"</string>
     <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR сонсогч"</string>
     <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"Нөхцөл нийлүүлэгч"</string>
@@ -1510,7 +1512,7 @@
     <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-тай хуваалцана уу"</string>
     <string name="content_description_sliding_handle" msgid="982510275422590757">"Бариулыг гулсуулна. Хүрээд хүлээнэ."</string>
     <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Түгжээг тайлах бол татна уу"</string>
-    <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудасруу шилжих"</string>
+    <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудас руу шилжих"</string>
     <string name="action_bar_up_description" msgid="6611579697195026932">"Дээш шилжих"</string>
     <string name="action_menu_overflow_description" msgid="4579536843510088170">"Нэмэлт сонголтууд"</string>
     <string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Шинэ: Цонх томруулагч"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Та одоо зарим эсвэл бүх дэлгэцээ томруулж болно"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Тохиргоонд асаана уу"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Үл хэрэгсэх"</string>
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 0588633..197797f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सर सूचना सेवा"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ट्वायलाइट सेवा"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"टाइम झोन डिटेक्टर (कनेक्टिव्हिटी नाही)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासक अ‍ॅप वापरता येणार नाही. तुमचे डिव्हाइस आता साफ केले जाईल.\n\nतुम्हाला कुठलेही प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> नी प्रिंट करणे बंद केले आहे."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्‍शन"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP चालत आहे"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अ‍ॅप्स"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"मॅग्निफिकेशन"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अ‍ॅप्स बॅटरी वापरत आहेत"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्‍या तपशीलांसाठी टॅप करा"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नवीन: विंडो मॅग्निफायर"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"आता स्क्रीन अंशतः किंवा पूर्ण मॅग्निफाय करू शकता"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग्ज मध्ये सुरू करा"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"डिसमिस करा"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 1d70f76..705ab6b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Perkhidmatan GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Perkhidmatan Pemberitahuan Penderia"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Perkhidmatan Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pengesan Zon Waktu (Tiada kesambungan)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Peranti anda akan dipadam"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Apl pentadbir tidak dapat digunakan. Peranti anda akan dipadamkan sekarang.\n\nJika anda ingin mengemukakan soalan, hubungi pentadbir organisasi anda."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Pencetakan dilumpuhkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Apl berjalan"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Urus panggilan yang sedang berjalan"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Benarkan apl melihat butiran panggilan yang sedang berjalan pada peranti anda dan mengawal panggilan ini."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baharu: Pembesar Tetingkap"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Besarkan sebahagian atau keseluruhan skrin anda"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Hidupkan dalam Tetapan"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Tolak"</string>
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 097c6c5..96d4417 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS ဝန်ဆောင်မှု"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"အာရုံခံကိရိယာ အကြောင်းကြားချက် ဝန်ဆောင်မှု"</string>
     <string name="twilight_service" msgid="8964898045693187224">"နေဝင်ဆည်းဆာ ဝန်ဆောင်မှု"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ဒေသစံတော်ချိန် ရှာဖွေစနစ် (ချိတ်ဆက်နိုင်မှု မလိုပါ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"စီမံခန့်ခွဲမှု အက်ပ်ကို သုံး၍မရပါ။ သင်၏ စက်ပစ္စည်းအတွင်းရှိ အရာများကို ဖျက်လိုက်ပါမည်\n\nမေးစရာများရှိပါက သင့်အဖွဲ့အစည်း၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> က ပုံနှိပ်ထုတ်ယူခြင်းကို ပိတ်ထားသည်။"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB ချိတ်ဆက်မှု"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP လုပ်ဆောင်နေသည်"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ချဲ့ခြင်း"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"အသစ်- ဝင်းဒိုးမှန်ဘီလူး"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်း (သို့) တစ်ခုလုံး ချဲ့နိုင်ပါပြီ"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"\'ဆက်တင်များ\' တွင် ဖွင့်ရန်"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ပယ်ရန်"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 6fa80dd..c85626f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidssoneoppdagelse (ingen tilkobling)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten blir slettet"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administratorappen kan ikke brukes. Enheten din blir nå tømt.\n\nTa kontakt med administratoren for organisasjonen din hvis du har spørsmål."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> har slått av utskrift."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tilkobling"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App kjører"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørring"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string>
@@ -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>
@@ -1800,8 +1802,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string>
-    <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string>
+    <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Datasparing hindrer noen apper fra å sende og motta data i bakgrunnen, for å redusere dataforbruket. Aktive apper kan bruke data, men kanskje ikke så mye som ellers – for eksempel vises ikke bilder før du trykker på dem."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du slå på Datasparing?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Slå på"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nytt: vindusforstørrer"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nå kan du forstørre deler av eller hele skjermen"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Slå på i innstillingene"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Avvis"</string>
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 28c3525..d1ae9ab 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सरको सूचनासम्बन्धी सेवा"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट सेवा"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र पत्ता लगाउने सुविधा (नेटवर्क कनेक्सन नहुँदा)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"तपाईंको यन्त्र मेटिनेछ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासकको एप प्रयोग गर्न मिल्दैन। तपाईंको यन्त्रको डेटा अब मेटाइने छ।\n\nतपाईंसँग प्रश्नहरू भएका खण्डमा आफ्नो संगठनका प्रशासकसँग सम्पर्क गर्नुहोस्।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ले छाप्ने कार्यलाई असक्षम पार्यो।"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB जडान"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"एप चलिरहेको छ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"जुम इन गर्ने सुविधा"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string>
@@ -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>
@@ -1965,7 +1969,7 @@
     <string name="autofill_save_type_debit_card" msgid="3169397504133097468">"डेबिट कार्ड"</string>
     <string name="autofill_save_type_payment_card" msgid="6555012156728690856">"भुक्तानी कार्ड"</string>
     <string name="autofill_save_type_generic_card" msgid="1019367283921448608">"कार्ड"</string>
-    <string name="autofill_save_type_username" msgid="1018816929884640882">"प्रयोगकर्ताको नाम"</string>
+    <string name="autofill_save_type_username" msgid="1018816929884640882">"युजरनेम"</string>
     <string name="autofill_save_type_email_address" msgid="1303262336895591924">"इमेल ठेगाना"</string>
     <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
     <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नयाँ सुविधा: विन्डो म्याग्निफायर"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"तपाईं अब स्क्रिनको केही वा सबै भाग जुम इन गर्न सक्नुहुन्छ"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिङमा गई यो सुविधा अन गर्नुहोस्"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"हटाउनुहोस्"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8b571e8..9d470b8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-service"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Service voor sensormeldingen"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Service voor schemering"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tijdzonedetector (Geen verbinding)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App actief"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nieuw: Venstervergroting"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Je kunt je scherm nu (gedeeltelijk) vergroten"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Inschakelen in Instellingen"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Sluiten"</string>
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 4b5c9b0..df72172 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS ସର୍ଭିସ୍"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"ସେନ୍ସର୍ ନୋଟିଫିକେସନ୍ ସର୍ଭିସ୍"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ଟ୍ୱିଲାଇଟ୍ ସର୍ଭିସ୍"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ଟାଇମ୍‍ ଜୋନ୍‍ ଡିଟେକ୍ଟର୍‍ (କୌଣସି ସଂଯୋଗ ନାହିଁ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ୍‍ ଆପ୍‍‍ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍‍‌ର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ରହିଥାଏ, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନ୍‌ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରିଣ୍ଟିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB ସଂଯୋଗ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ଆପ୍‍ ଚାଲୁଛି"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍‍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ମ୍ୟାଗ୍ନିଫିକେସନ୍"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍‍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ନୂଆ: ୱିଣ୍ଡୋ ମ୍ୟାଗ୍ନିଫାୟର୍"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ଆପଣ ଏବେ ଆଂଶିକ ବା ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ ବଡ଼ କରିପାରିବେ"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ସେଟିଂସରେ ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ଖାରଜ କରନ୍ତୁ"</string>
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 5de0885..9736e57 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS ਸੇਵਾ"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"ਸੈਂਸਰ ਸੂਚਨਾ ਸੇਵਾ"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ਟਵੀਲਾਈਟ ਸੇਵਾ"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ਸਮਾਂ ਖੇਤਰ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਸੁਵਿਧਾ (ਕੋਈ ਕਨੈਕਟੀਵਿਟੀ ਨਹੀਂ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਿੰਟ ਕਰਨਾ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB ਕਨੈਕਸ਼ਨ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ਚੱਲ ਰਹੀ ਐਪ"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ਨਵਾਂ: Window ਵੱਡਦਰਸ਼ੀ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ਹੁਣ ਤੁਸੀਂ ਕੁਝ ਜਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ ਵੱਡਦਰਸ਼ੀ ਕਰ ਸਕਦੇ ਹੋ"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ਖਾਰਜ ਕਰੋ"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 427beb5..2feb6af 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Usługa GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Usługa powiadomień czujnika"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Usługa Zmierzch"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Wykrywanie strefy czasowej (brak połączenia)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Nie można użyć aplikacji administratora. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Połączenie USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Działa aplikacja"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Powiększenie"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string>
@@ -359,6 +359,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Zarządzaj połączeniami w toku"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Zezwala aplikacji zobaczyć detale dotyczące połączeń w toku na Twoim urządzeniu i na kontrolę tych połączeń."</string>
     <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>
@@ -1846,7 +1848,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n•włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"Aby wydłużyć czas pracy na baterii, Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nowość: powiększanie okna"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Możesz teraz powiększyć część lub całość ekranu"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Włącz w Ustawieniach"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Odrzuć"</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 3fed028..d9050bf 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 1c890dd..3de02ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Serviço GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detetor do fuso horário (sem conetividade)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"O seu dispositivo será apagado"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível utilizar a app de administrador. O seu dispositivo será agora apagado.\n\nSe tiver questões, contacte o administrador da entidade."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 3fed028..d9050bf 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -352,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 5cf3076..e73d96c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Serviciul GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Serviciu pentru notificări de la senzori"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Serviciul Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fus orar (fără conexiune)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Datele de pe dispozitiv vor fi șterse"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplicația de administrare nu poate fi utilizată. Dispozitivul va fi șters.\n\nDacă aveți întrebări, contactați administratorul organizației dvs."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printare dezactivată de <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Conexiune USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicația rulează"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Mărire"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string>
@@ -356,6 +356,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Să gestioneze apelurile în desfășurare"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite unei aplicații să vadă detalii despre apelurile în desfășurare de pe dispozitiv și să gestioneze apelurile respective."</string>
     <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>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nou: lupă fereastră"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Acum puteți mări o parte sau tot ecranul"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activați din Setări"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Respingeți"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index efd3c6c..7ca863a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Сервис для обработки уведомлений от датчиков"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Сервис для определения наступления сумерек"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Определитель часового пояса (работает без Интернета)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Все данные с устройства будут удалены"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Невозможно использовать приложение для администрирования. С устройства будут удалены все данные.\n\nЕсли у вас возникли вопросы, обратитесь к администратору."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Функция печати отключена приложением \"<xliff:g id="OWNER_APP">%s</xliff:g>\""</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-подключение"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложение активно"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string>
@@ -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">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</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">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Просмотр фидов пользователя"</string>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новинка: экранная лупа"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Теперь можно увеличивать весь экран или его часть."</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включить в настройках"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Закрыть"</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 100aed1..6c1c777 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS සේවාව"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"සංවේදක දැනුම් දීමේ සේවාව"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ඇඳිරි සේවාව"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"වේලා කලාප අනාවරකය (සම්බන්ධතාවක් නොමැත)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ඔබගේ උපාංගය මකා දැමෙනු ඇත"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"පරිපාලක යෙදුම භාවිතා කළ නොහැකිය. ඔබේ උපාංගය දැන් මකා දමනු ඇත.\n\nඔබට ප්‍රශ්න තිබේ නම්, ඔබේ සංවිධානයේ පරිපාලකට අමතන්න."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> විසින් මුද්‍රණය කිරීම අබල කර ඇත."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB සම්බන්ධතාවය"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"යෙදුම ධාවනය කරමින්"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"විශාලනය"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"නව: කවුළු විශාලකය"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ඔබට දැන් තිරයේ සමහර හෝ සියලු දේ විශාලනය කළ හැකිය"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"සැකසීම් තුළ ක්‍රියාත්මක කරන්න"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ඉවත ලන්න"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f7756e5..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>
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Služba upozornení senzora"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Služba stmievania"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez pripojenia)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Vaše zariadenie bude vymazané"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Daná aplikácia na správu sa nedá použiť. Vaše zariadenie bude vymazané.\n\nV prípade otázok kontaktujte správcu organizácie."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Tlač zakázala aplikácia <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Pripojenie USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikácia je spustená"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zväčšenie"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</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>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Lupa pre okná"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Teraz môžete zväčšiť celú obrazovku alebo jej časť"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnúť v Nastaveniach"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Zavrieť"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index df7e0ee..2a027b2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Storitev GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Storitev obvestil tipal"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Storitev Somrak"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaznavanje časovnega pasu (brez povezave)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Podatki v napravi bodo izbrisani"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Skrbniške aplikacije ni mogoče uporabljati. Podatki v napravi bodo izbrisani.\n\nČe imate vprašanja, se obrnite na skrbnika organizacije."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Tiskanje je onemogočil pravilnik <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Povezava USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacija se izvaja"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povečava"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string>
@@ -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>
@@ -1846,7 +1848,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n•vklopi temno temo,\n•izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo,\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo;\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Zaradi zmanjševanja prenesene količine podatkov funkcija varčevanja s podatki nekaterim aplikacijam preprečuje, da bi v ozadju pošiljale ali prejemale podatke. Aplikacija, ki jo trenutno uporabljate, lahko prenaša podatke, vendar to morda počne manj pogosto. To na primer pomeni, da se slike ne prikažejo, dokler se jih ne dotaknete."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Vklop varčevanja s podatki?"</string>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa v oknu"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Zdaj lahko povečate del zaslona ali celotni zaslon"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vklopite v nastavitvah"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Opusti"</string>
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 8de3f8c..18a1f98 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Shërbimi GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Shërbimi i njoftimeve të sensorit"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Shërbimi i muzgut"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zbuluesi i brezit orar (nuk nevojitet lidhja)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Pajisja do të spastrohet"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Aplikacioni i administratorit nuk mund të përdoret. Pajisja jote tani do të fshihet.\n\nNëse ke pyetje, kontakto me administratorin e organizatës."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Printimi është çaktivizuar nga <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Lidhja USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacioni është në ekzekutim"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zmadhimi"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Menaxho telefonatat në vazhdim"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Lejon që një aplikacion të shikojë detaje rreth telefonatave në vazhdim dhe t\'i kontrollojë këto telefonata."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Risi: Zmadhuesi i dritareve"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tani mund t\'i zmadhosh një pjesë apo të gjithë ekranin tënd"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivizo te \"Cilësimet\""</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Hiq"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e403118..fe12013 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -201,6 +201,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS услуга"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга обавештења сензора"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Услуга Сумрак"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Детектор временске зоне (нема интернет везе)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Уређај ће бити обрисан"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Не можете да користите ову апликацију за администраторе. Уређај ће сада бити обрисан.\n\nАко имате питања, контактирајте администратора организације."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Штампање је онемогућила апликација <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -290,8 +291,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB веза"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увећање"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string>
@@ -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>
@@ -932,7 +934,7 @@
     <string name="granularity_label_link" msgid="9007852307112046526">"линк"</string>
     <string name="granularity_label_line" msgid="376204904280620221">"ред"</string>
     <string name="factorytest_failed" msgid="3190979160945298006">"Фабричко тестирање није успело"</string>
-    <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string>
+    <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у фолдеру /system/app."</string>
     <string name="factorytest_no_action" msgid="339252838115675515">"Није пронађен ниједан пакет који обезбеђује радњу FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="2050147445567257365">"Рестартуј"</string>
     <string name="js_dialog_title" msgid="7464775045615023241">"На страници на адреси „<xliff:g id="TITLE">%s</xliff:g>“ пише:"</string>
@@ -2048,7 +2050,7 @@
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Батерија телефона је довољно напуњена. Функције више нису ограничене."</string>
     <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Батерија таблета је довољно напуњена. Функције више нису ограничене."</string>
     <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Батерија уређаја је довољно напуњена. Функције више нису ограничене."</string>
-    <string name="mime_type_folder" msgid="2203536499348787650">"Директоријум"</string>
+    <string name="mime_type_folder" msgid="2203536499348787650">"Фолдер"</string>
     <string name="mime_type_apk" msgid="3168784749499623902">"Android апликација"</string>
     <string name="mime_type_generic" msgid="4606589110116560228">"Датотека"</string>
     <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> датотека"</string>
@@ -2224,12 +2226,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Лупа за прозор"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увећате део екрана или цео екран"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Укључите у Подешавањима"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Одбаци"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cc21f39..60b14ff 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjänst"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszondetektering (ingen anslutning)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten kommer att rensas"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Det går inte att använda administratörsappen. Enheten rensas.\n\nKontakta organisationens administratör om du har några frågor."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Utskrift har inaktiverats av <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB-anslutning"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App körs"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Förstoring"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhet: Fönsterförstoring"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nu kan du förstora delar av eller hela skärmen"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivera i inställningarna"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Stäng"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 9478b0b..2f342b1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Huduma ya GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Huduma ya Arifa ya Kitambuzi"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Kitambua Saa za Eneo (Hakuna muunganisho)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Data iliyomo kwenye kifaa chako itafutwa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Huwezi kutumia programu ya msimamizi. Sasa data iliyo kwenye kifaa chako itafutwa.\n\nIkiwa una maswali yoyote, wasiliana na msimamizi wa shirika lako."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Kipengele cha kuchapisha kimezimwa na <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Muunganisho wa USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programu inaendelea kutekelezwa"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukuzaji"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Dhibiti simu zinazoendelea"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Huruhusu programu kuangalia maelezo kuhusu simu zinazoendelea kwenye kifaa chako na kuzidhibiti."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Mpya: Kikuza Dirisha"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sasa unaweza kukuza sehemu ya au skrini yako yote"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Washa katika Mipangilio"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Ondoa"</string>
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ebaeadd..0fe5962 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS சேவை"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"சென்சார் அறிவிப்புச் சேவை"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight சேவை"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"நேர மண்டல டிடெக்டர் (இணைப்பு இல்லை)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"சாதனத் தரவு அழிக்கப்படும்"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"நிர்வாகி ஆப்ஸை உபயோகிக்க முடியாது. இப்போது, உங்கள் சாதனம் ஆரம்ப நிலைக்கு மீட்டமைக்கப்படும்.\n\nஏதேனும் கேள்விகள் இருப்பின், உங்கள் நிறுவனத்தின் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"பிரிண்ட் செய்வதை <xliff:g id="OWNER_APP">%s</xliff:g> தடுத்துள்ளது."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB இணைப்பு"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ஆப்ஸ் இயங்குகிறது"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"பெரிதாக்கல்"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"புதிது: சாளரம் பெரிதாக்கும் கருவி"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"திரை முழுவதையுமோ ஒரு பகுதியையோ பெரிதாக்கலாம்"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"அமைப்புகளில் ஆன் செய்க"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"மூடுக"</string>
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c63d175..4602abb8 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS సర్వీస్"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"సెన్సార్ నోటిఫికేషన్ సర్వీస్"</string>
     <string name="twilight_service" msgid="8964898045693187224">"ట్విలైట్ సర్వీస్"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"టైమ్ జోన్ డిటెక్టర్ (కనెక్టివిటీ లేదు)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"నిర్వాహక యాప్‌ ఉపయోగించడం సాధ్యపడదు. మీ పరికరంలోని డేటా ఇప్పుడు తొలగించబడుతుంది.\n\nమీకు ప్రశ్నలు ఉంటే, మీ సంస్థ యొక్క నిర్వాహకులను సంప్రదించండి."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"ముద్రణ <xliff:g id="OWNER_APP">%s</xliff:g> ద్వారా నిలిపివేయబడింది."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB కనెక్షన్"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్‌లు"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మాగ్నిఫికేషన్"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్‌లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"కొత్తది: విండో మాగ్నిఫయర్"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"స్క్రీన్ మొత్తం లేదా కొంత భాగాన్ని జూమ్ చేయవచ్చు"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్‌లలో ఆన్ చేయండి"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b0acb12..abda062 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"บริการ GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"บริการแจ้งเตือนเกี่ยวกับเซ็นเซอร์"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ตัวตรวจจับเขตเวลา (ไม่มีการเชื่อมต่อ)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"ใช้แอปผู้ดูแลระบบนี้ไม่ได้ ขณะนี้ระบบจะลบข้อมูลในอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบขององค์กรหากมีคำถาม"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ปิดใช้การพิมพ์แล้ว"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"การเชื่อมต่อ USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"แอปที่ทำงานอยู่"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"การขยาย"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
@@ -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>
@@ -1800,7 +1802,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n•ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น \"Ok Google\""</string>
     <string name="data_saver_description" msgid="4995164271550590517">"เพื่อช่วยลดปริมาณการใช้อินเทอร์เน็ต โปรแกรมประหยัดอินเทอร์เน็ตจะช่วยป้องกันไม่ให้บางแอปส่งหรือรับข้อมูลโดยการใช้อินเทอร์เน็ตอยู่เบื้องหลัง แอปที่คุณกำลังใช้งานสามารถเข้าถึงอินเทอร์เน็ตได้ แต่อาจไม่บ่อยเท่าเดิม ตัวอย่างเช่น ภาพต่างๆ จะไม่แสดงจนกว่าคุณจะแตะที่ภาพเหล่านั้น"</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"เปิดการประหยัดอินเทอร์เน็ตไหม"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ใหม่: แว่นขยายหน้าต่าง"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"คุณสามารถขยายหน้าจอบางส่วนหรือทั้งหมดได้แล้วตอนนี้"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"เปิดในการตั้งค่า"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"ปิด"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f04e7e1..286d28d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Serbisyo ng GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Serbisyo ng Notification ng Sensor"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Serbisyo ng Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector ng Time Zone (Walang koneksyon)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Buburahin ang iyong device"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Hindi magamit ang admin app. Mabubura na ang iyong device.\n\nKung mayroon kang mga tanong, makipag-ugnayan sa admin ng iyong organisasyon."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Na-disable ng <xliff:g id="OWNER_APP">%s</xliff:g> ang pag-print."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Koneksyon ng USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tumatakbo ang app"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pag-magnify"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Bago: Magnifier ng Window"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Mama-magnify na ang bahagi o kabuuan ng screen mo"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"I-on sa Mga Setting"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"I-dismiss"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 79cfe19..324101d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS Hizmeti"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensör Bildirim Hizmeti"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Alacakaranlık Hizmeti"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaman Dilimi Algılayıcı (Bağlantı yok)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız silinecek"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Yönetim uygulaması kullanılamıyor. Cihazınız şimdi silinecek.\n\nSorularınız varsa kuruluşunuzun yöneticisine başvurun."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Yazdırma işlemi <xliff:g id="OWNER_APP">%s</xliff:g> tarafından devre dışı bırakıldı."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB bağlantısı"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uygulama çalışıyor"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Büyütme"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Devam eden aramaları yönetme"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Uygulamanın, cihazınızda devam eden aramalarla ilgili bilgileri görüp kontrol etmesine izin verir."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pencere Büyüteci"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Artık ekranınızın bir kısmını veya tamamını büyütebilirsiniz"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlar\'da aç"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Kapat"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a752010..ba124a6 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -203,6 +203,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Сервіс GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Сервіс \"Сповіщення датчика\""</string>
     <string name="twilight_service" msgid="8964898045693187224">"Сервіс \"Сутінки\""</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Визначення часового поясу (без Інтернету)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"З вашого пристрою буде стерто всі дані"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Не можна запускати додаток для адміністраторів. Буде відновлено заводські налаштування пристрою.\n\nЯкщо у вас є запитання, зв’яжіться з адміністратором своєї організації."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Додаток <xliff:g id="OWNER_APP">%s</xliff:g> вимкнув друк."</string>
@@ -293,8 +294,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"З’єднання USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Працює додаток"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Збільшення"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string>
@@ -359,6 +359,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 шкідливі додатки можуть перешкоджати роботі вашого пристрою."</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>
@@ -2258,12 +2260,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Нове: збільшення вікон"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Тепер можна збільшити весь екран або його частину"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Увімкнути в налаштуваннях"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Закрити"</string>
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 4324e36..6eabc7b 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"‏GNSS سروس"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"سینسر نوٹیفکیشن سروس"</string>
     <string name="twilight_service" msgid="8964898045693187224">"شفقی سروس"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ٹائم زون ڈیٹیکٹر (کوئی کنیکٹوٹی نہیں ہے)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"آپ کا آلہ صاف کر دیا جائے گا"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"منتظم کی ایپ استعمال نہیں کی جا سکتی۔ آپ کا آلہ اب مٹا دیا جائے گا۔\n\nاگر آپ کے سوالات ہیں تو اپنی تنظیم کے منتظم سے رابطہ کریں۔"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> نے پرنٹنگ کو غیر فعال کر دیا ہے۔"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"‏USB کنکشن"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ایپ چل رہی ہے"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"میگنیفکیشن"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string>
@@ -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>
@@ -2190,12 +2194,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"نیا: ونڈو میگنیفائر"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اب آپ اپنی تمام یا کچھ اسکرین کو بڑا کر سکتے ہیں"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ترتیبات میں آن کریں"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"برخاست کریں"</string>
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 923831c..00f2215 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS xizmati"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorli bildirishnoma xizmati"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight xizmati"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Vaqt mintaqasini aniqlagich (Oflayn)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Administrator ilovasini ishlatib bo‘lmaydi. Qurilmada barcha ma’lumotlar o‘chirib tashlanadi.\n\nSavollaringiz bo‘lsa, administrator bilan bog‘laning."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Chop etish funksiyasi <xliff:g id="OWNER_APP">%s</xliff:g> tomonidan faolsizlantirilgan."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB orqali ulanish"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ilova faol"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Kattalashtirish"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string>
@@ -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>
@@ -593,7 +595,7 @@
     <string name="face_acquired_too_right" msgid="2513391513020932655">"Telefonni chapga suring."</string>
     <string name="face_acquired_too_left" msgid="8882499346502714350">"Telefonni oʻngga suring."</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Qurilmaga tik qarang."</string>
-    <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefoningizga yuzingizni tik tuting."</string>
+    <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefonni yuzingizga tik qarating."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ortiqcha harakatlanmoqda. Qimirlatmasdan ushlang."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Yuzingizni qaytadan qayd qildiring."</string>
     <string name="face_acquired_too_different" msgid="4699657338753282542">"Yuz tanilmadi. Qaytadan urining."</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>
@@ -1800,7 +1802,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Hey Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string>
@@ -1894,7 +1896,7 @@
     <string name="app_suspended_title" msgid="888873445010322650">"Ilova ishlamayapti"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ishlamayapti. Uning ishlashini <xliff:g id="APP_NAME_1">%2$s</xliff:g> cheklamoqda."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"Batafsil"</string>
-    <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani ishga tushirish"</string>
+    <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani pauzadan chiqarish"</string>
     <string name="work_mode_off_title" msgid="5503291976647976560">"Ish profili yoqilsinmi?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"Ishga oid ilovalar, bildirishnomalar, ma’lumotlar va boshqa ish profili imkoniyatlari yoqiladi"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string>
@@ -2009,7 +2011,7 @@
     <string name="notification_feedback_indicator" msgid="663476517711323016">"Fikr-mulohaza yuborish"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Kun tartibi rejimi haqidagi bildirishnoma"</string>
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya quvvati odatdagidan ertaroq tugashi mumkin"</string>
-    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvati uzoqroq ishlashi uchun Tejamkor rejim yoqildi"</string>
+    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash rejimi yoqildi"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Quvvat tejash"</string>
     <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Quvvat tejash rejimi faolsizlantirildi"</string>
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yangi: Ekran lupasi"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ekranni toʻliq yoki qisman kattalashtirish mumkin"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Sozlamalar orqali yoqish"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Yopish"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 296261f..702f693 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Dịch vụ GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Dịch vụ Thông báo của cảm biến"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Dịch vụ Twilight"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Trình phát hiện múi giờ (Không có kết nối)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Thiết bị của bạn sẽ bị xóa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Không thể sử dụng ứng dụng quản trị. Thiết bị của bạn sẽ bị xóa ngay bây giờ.\n\nHãy liên hệ với quản trị viên của tổ chức nếu bạn có thắc mắc."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> đã tắt tính năng in."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Kết nối USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ứng dụng đang chạy"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Phóng to"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
@@ -353,6 +353,8 @@
     <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>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Quản lý cuộc gọi đang diễn ra"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Cho phép một ứng dụng xem thông tin chi tiết về các cuộc gọi đang diễn ra trên thiết bị và kiểm soát các cuộc gọi này."</string>
     <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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Tính năng mới: Phóng to cửa sổ"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Giờ đây, bạn có thể phóng to một phần hoặc toàn màn hình"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bật trong phần Cài đặt"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Đóng"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index a27e7b1..c8d8f11 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS 服务"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"传感器通知服务"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight 服务"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"时区检测器(无网络连接)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"系统将清空您的设备"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"无法使用管理应用,系统现在将清空您的设备。\n\n如有疑问,请与您所在单位的管理员联系。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"“<xliff:g id="OWNER_APP">%s</xliff:g>”已停用打印功能。"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB 连接"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"应用正在运行中"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大功能"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:窗口放大镜"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您现在可以放大屏幕上的部分或所有内容"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在“设置”中开启"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"关闭"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 5099ebf..33196c82 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string>
     <string name="twilight_service" msgid="8964898045693187224">"暮光服務"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (沒有連線)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"您的裝置將被清除"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理員應用程式。系統會現在清除您的裝置。\n\n如有任何疑問,請聯絡您的機構管理員。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」暫停了列印。"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式正在執行"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您現在可以放大部分或整個畫面"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 31bd99b..1194b49 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Twilight 服務"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (不必連上網路)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"你的裝置資料將遭到清除"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理應用程式,系統現在將清除你裝置中的資料。\n\n如有任何問題,請與貴機構的管理員聯絡。"</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」已停用列印功能。"</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式執行中"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string>
@@ -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>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"你可以放大局部或整個畫面"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 28eed9b..67eb874 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -199,6 +199,7 @@
     <string name="gnss_service" msgid="8907781262179951385">"Isevisi ye-GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Isevisi Yesaziso Senzwa"</string>
     <string name="twilight_service" msgid="8964898045693187224">"Isevisi Yangovivi"</string>
+    <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Isitholi Sezoni Yesikhathi (Akukho ukuxhumana)"</string>
     <string name="factory_reset_warning" msgid="6858705527798047809">"Idivayisi yakho izosulwa"</string>
     <string name="factory_reset_message" msgid="2657049595153992213">"Uhlelo lokusebenza lomlawuli alikwazi ukusetshenziswa. Idivayisi yakho manje izosuswa.\n\nUma unemibuzo, xhumana nomlawuli wezinhlangano zakho."</string>
     <string name="printing_disabled_by" msgid="3517499806528864633">"Ukuphrinta kukhutshazwe nge-<xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -287,8 +288,7 @@
     <string name="notification_channel_usb" msgid="1528280969406244896">"Ukuxhumeka kwe-USB"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uhlelo loksuebenza olusebenzayo"</string>
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string>
-    <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
-    <skip />
+    <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukukhuliswa"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string>
@@ -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>
@@ -817,7 +819,7 @@
     <string name="relationTypeReferredBy" msgid="5285082289602849400">"Kusikiselwe ngu-"</string>
     <string name="relationTypeRelative" msgid="3396498519818009134">"Isihlobo"</string>
     <string name="relationTypeSister" msgid="3721676005094140671">"Usisi"</string>
-    <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingane"</string>
+    <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingani"</string>
     <string name="sipAddressTypeCustom" msgid="6283889809842649336">"Ngokwezifiso"</string>
     <string name="sipAddressTypeHome" msgid="5918441930656878367">"Ekhaya"</string>
     <string name="sipAddressTypeWork" msgid="7873967986701216770">"Umsebenzi"</string>
@@ -2190,12 +2192,8 @@
     <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
-    <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
-    <skip />
-    <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
-    <skip />
-    <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
-    <skip />
-    <!-- no translation found for dismiss_action (1728820550388704784) -->
-    <skip />
+    <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Okusha: Isikhulisi sewindi"</string>
+    <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Manje usungakwazi ukukhulisa esinye noma sonke isikrini sakho"</string>
+    <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vula Kumasethingi"</string>
+    <string name="dismiss_action" msgid="1728820550388704784">"Cashisa"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f4c3063..7ca3faf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3871,6 +3871,9 @@
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. -->
         <attr name="settingsActivity"/>
+        <!-- Whether the device must be screen on before routing data to this service.
+             The default is true.-->
+        <attr name="requireDeviceScreenOn" format="boolean"/>
     </declare-styleable>
 
     <!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -3889,6 +3892,12 @@
         <attr name="settingsActivity"/>
         <!-- Secure Element which the AIDs should be routed to -->
         <attr name="secureElementName" format="string"/>
+        <!-- Whether the device must be unlocked before routing data to this service.
+             The default is false.-->
+        <attr name="requireDeviceUnlock"/>
+        <!-- Whether the device must be screen on before routing data to this service.
+             The default is false.-->
+        <attr name="requireDeviceScreenOn"/>
     </declare-styleable>
 
     <!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 85b19e7..060c8b1 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -226,6 +226,9 @@
              to share specific features explicitly because they are being built
              together. -->
         <flag name="signatureOrSystem" value="3" />
+        <!-- <strong>Base permission type</strong>: a permission that is managed internally by the
+             system and only granted according to the protection flags. -->
+        <flag name="internal" value="4" />
         <!-- Additional flag from base permission type: this permission can also
              be granted to any applications installed as privileged apps on the system image.
              Please avoid using this option, as the
@@ -306,6 +309,8 @@
         <!-- Additional flag from base permission type: this permission will be granted to the
              recents app. -->
         <flag name="recents" value="0x2000000" />
+        <!-- Additional flag from base permission type: this permission is managed by role. -->
+        <flag name="role" value="0x4000000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 40e11cb..da658cc 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -654,10 +654,9 @@
          The default is false. -->
     <bool name="config_lidControlsSleep">false</bool>
 
-    <!-- Indicate whether closing the lid causes the device to enter the folded state which means
-         to get a smaller screen and opening the lid causes the device to enter the unfolded state
-         which means to get a larger screen. -->
-    <bool name="config_lidControlsDisplayFold">false</bool>
+    <!-- The device state (supplied by DeviceStateManager) that should be treated as folded by the
+         display fold controller. Default is DeviceStateManager.INVALID_DEVICE_STATE. -->
+    <integer name="config_foldedDeviceState">-1</integer>
 
     <!-- Indicate the display area rect for foldable devices in folded state. -->
     <string name="config_foldedArea"></string>
@@ -3303,6 +3302,10 @@
          is non-interactive. -->
     <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
 
+    <!-- Allow the gesture to quick tap the power button multiple times to start the emergency sos
+         experience while the device is non-interactive. -->
+    <bool name="config_emergencyGestureEnabled">true</bool>
+
     <!-- Allow the gesture power + volume up to change the ringer mode while the device
          is interactive. -->
     <bool name="config_volumeHushGestureEnabled">true</bool>
@@ -3738,6 +3741,16 @@
     -->
     <string name="config_defaultContentSuggestionsService" translatable="false"></string>
 
+    <!-- The package name for the system's search ui service.
+     This service returns search results when provided with an input string.
+
+     This service must be trusted, as it can be activated without explicit consent of the user.
+     If no service with the specified name exists on the device, on device search wil be
+     disabled.
+     Example: "com.android.intelliegence/.SearchUiService"
+-->
+    <string name="config_defaultSearchUiService" translatable="false"></string>
+
     <string name="config_defaultMusicRecognitionService" translatable="false"></string>
 
     <!-- The package name for the default retail demo app.
@@ -4570,6 +4583,9 @@
     <!-- Indicates that default fitness tracker app needs to request sensor and location permissions. -->
     <bool name="config_trackerAppNeedsPermissions">false</bool>
 
-  <!-- Component with platform query permissions for AppSearch -->
-    <string name="config_defaultAppSearchPlatformQuerierComponent" translatable="false"></string>
+    <!-- Package with global data query permissions for AppSearch -->
+    <string name="config_globalAppSearchDataQuerierPackage" translatable="false"></string>
+
+    <!-- If true, attach the navigation bar to the app during app transition -->
+    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 05db741..5b19a48 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">20dp</dimen>
 
     <!-- Size of the profile badge for notifications -->
     <dimen name="notification_badge_size">12dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 2c4f4c8..c3cd80b 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -84,6 +84,14 @@
     <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
     <dimen name="car_pill_button_size">56dp</dimen>
     <dimen name="car_touch_target_size">76dp</dimen>
+    <dimen name="car_touch_target_size_minus_one">75dp</dimen>
+
+    <!-- Switch. -->
+    <!-- Thumb size + 2*thumb margin size must equal car_touch_target_size -->
+    <!-- 2 * Thumb size + 2*track margin size must equal car_touch_target_size -->
+    <dimen name="car_switch_thumb_size">24dp</dimen>
+    <dimen name="car_switch_thumb_margin_size">26dp</dimen>
+    <dimen name="car_switch_track_margin_size">14dp</dimen>
 
     <!-- Seekbar -->
     <dimen name="car_seekbar_height">6dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1e9a747..4313d4a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3049,6 +3049,7 @@
     <public name="windowLayoutAffinity" />
     <!-- @hide -->
     <public name="windowBackgroundBlurRadius"/>
+    <public name="requireDeviceScreenOn" />
   </public-group>
 
   <public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 89b986b..3a593b9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -928,6 +928,15 @@
         interfere with the performance or operation of your device when an
         emergency cell broadcast is received.</string>
 
+    <!-- Title for an application which grants an app the ability to see and manage calls on
+         the user's device. Usually reserved for apps associated with wearable devices that
+         can show information about calls. -->
+    <string name="permlab_manageOngoingCalls">Manage ongoing calls</string>
+    <!-- Description of an application permission, listed so the user can choose whether they
+         want to allow the application to do this. -->
+    <string name="permdesc_manageOngoingCalls">Allows an app to see details about ongoing calls
+         on your device and to control these calls.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readCellBroadcasts">read cell broadcast messages</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -5357,6 +5366,14 @@
     <!-- Feedback Indicator -->
     <!-- Content description of the feedback icon in the notification. [CHAR LIMIT=NONE] -->
     <string name="notification_feedback_indicator">Provide Feedback</string>
+    <!-- Content description of the alerted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+    <string name="notification_feedback_indicator_alerted">This notification was promoted to Default. Tap to provide feedback.</string>
+    <!-- Content description of the silenced feedback icon in the notification. [CHAR LIMIT=NONE] -->
+    <string name="notification_feedback_indicator_silenced">This notification was demoted to Silent. Tap to provide feedback.</string>
+    <!-- Content description of the promoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+    <string name="notification_feedback_indicator_promoted">This notification was ranked higher. Tap to provide feedback.</string>
+    <!-- Content description of the demoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+    <string name="notification_feedback_indicator_demoted">This notification was ranked lower. Tap to provide feedback.</string>
 
     <!-- Dynamic mode battery saver strings -->
     <!-- The user visible name of the notification channel for the routine mode battery saver fyi notification [CHAR_LIMIT=80]-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e50eee6..fa66451 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" />
@@ -2248,6 +2252,10 @@
   <java-symbol type="string" name="ext_media_move_success_message" />
   <java-symbol type="string" name="ext_media_move_failure_title" />
   <java-symbol type="string" name="ext_media_move_failure_message" />
+  <java-symbol type="string" name="notification_feedback_indicator_alerted" />
+  <java-symbol type="string" name="notification_feedback_indicator_silenced" />
+  <java-symbol type="string" name="notification_feedback_indicator_promoted" />
+  <java-symbol type="string" name="notification_feedback_indicator_demoted" />
   <java-symbol type="style" name="Animation.RecentApplications" />
   <java-symbol type="integer" name="dock_enter_exit_duration" />
   <java-symbol type="bool" name="config_battery_percentage_setting_available" />
@@ -2823,6 +2831,7 @@
   <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
   <java-symbol type="integer" name="config_cameraLiftTriggerSensorType" />
   <java-symbol type="string" name="config_cameraLiftTriggerSensorStringType" />
+  <java-symbol type="bool" name="config_emergencyGestureEnabled" />
   <java-symbol type="bool" name="config_volumeHushGestureEnabled" />
 
   <java-symbol type="drawable" name="platlogo_m" />
@@ -3472,6 +3481,7 @@
   <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
   <java-symbol type="string" name="config_defaultAppPredictionService" />
   <java-symbol type="string" name="config_defaultContentSuggestionsService" />
+  <java-symbol type="string" name="config_defaultSearchUiService" />
   <java-symbol type="string" name="config_defaultMusicRecognitionService" />
   <java-symbol type="string" name="config_defaultAttentionService" />
   <java-symbol type="string" name="config_defaultSystemCaptionsService" />
@@ -3701,7 +3711,7 @@
   <java-symbol type="string" name="config_customCountryDetector" />
 
   <!-- For Foldables -->
-  <java-symbol type="bool" name="config_lidControlsDisplayFold" />
+  <java-symbol type="integer" name="config_foldedDeviceState" />
   <java-symbol type="string" name="config_foldedArea" />
 
   <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
@@ -4115,11 +4125,13 @@
 
   <java-symbol type="bool" name="config_trackerAppNeedsPermissions"/>
 
-  <!-- Component with platform query permissions for AppSearch -->
-  <java-symbol type="string" name="config_defaultAppSearchPlatformQuerierComponent" />
+  <!-- Package with global data query permissions for AppSearch -->
+  <java-symbol type="string" name="config_globalAppSearchDataQuerierPackage" />
 
   <!-- Color used by the accessibility focus rectangle -->
   <java-symbol type="color" name="accessibility_focus_highlight_color" />
   <!-- Width of the outline stroke used by the accessibility focus rectangle -->
   <java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
+
+  <java-symbol type="bool" name="config_attachNavBarToAppDuringTransition" />
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/OWNERS b/core/tests/ConnectivityManagerTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/PackageInstallerSessions/OWNERS b/core/tests/PackageInstallerSessions/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/PackageInstallerSessions/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
new file mode 100644
index 0000000..ade97b8
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
@@ -0,0 +1,13 @@
+android_test {
+    name: "BatteryStatsLoadTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "compatibility-device-util-axt",
+        "junit",
+    ],
+    libs: ["android.test.runner"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/AndroidManifest.xml b/core/tests/batterystatstests/BatteryStatsLoadTests/AndroidManifest.xml
new file mode 100644
index 0000000..adc20c6
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.frameworks.core.batterystatsloadtests">
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.BATTERY_STATS"/>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.DEVICE_POWER"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.frameworks.core.batterystatsloadtests"
+        android:label="Power Stats Load Tests" />
+
+    <queries>
+        <!-- The load test resolves http://... intents. Let it do so. -->
+        <package android:name="com.android.chrome"/>
+    </queries>
+</manifest>
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/ConnectivitySetupRule.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/ConnectivitySetupRule.java
new file mode 100644
index 0000000..1afc22b7
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/ConnectivitySetupRule.java
@@ -0,0 +1,159 @@
+/*
+ * 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.frameworks.core.batterystatsloadtests;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ConnectivitySetupRule implements TestRule {
+
+    private final boolean mWifiEnabled;
+    private final ConnectivityManager mConnectivityManager;
+    private final WifiManager mWifiManager;
+    private boolean mInitialWifiState;
+
+    public ConnectivitySetupRule(boolean wifiEnabled) {
+        mWifiEnabled = wifiEnabled;
+
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        Context context = instrumentation.getContext();
+        mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+        mWifiManager = context.getSystemService(WifiManager.class);
+    }
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                try {
+                    mInitialWifiState = isWiFiConnected();
+                    setWiFiState(mWifiEnabled);
+                    base.evaluate();
+                } finally {
+                    setWiFiState(mInitialWifiState);
+                }
+            }
+        };
+    }
+
+    private void setWiFiState(final boolean enable) throws InterruptedException {
+        boolean wiFiConnected = isWiFiConnected();
+        if (enable == wiFiConnected) {
+            return;
+        }
+
+        NetworkTracker tracker = new NetworkTracker(!mWifiEnabled);
+        mConnectivityManager.registerNetworkCallback(
+                new NetworkRequest.Builder()
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED).build(),
+                tracker);
+
+        if (enable) {
+            SystemUtil.runShellCommand("svc wifi enable");
+            //noinspection deprecation
+            SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
+                    android.Manifest.permission.NETWORK_SETTINGS);
+        } else {
+            SystemUtil.runShellCommand("svc wifi disable");
+        }
+
+        tracker.waitForExpectedState();
+
+        assertEquals("Wifi must be " + (enable ? "connected to" : "disconnected from")
+                + " an access point for this test.", enable, isWiFiConnected());
+
+        mConnectivityManager.unregisterNetworkCallback(tracker);
+    }
+
+    private boolean isWiFiConnected() {
+        return mWifiManager.isWifiEnabled() && mConnectivityManager.getActiveNetwork() != null
+                && !mConnectivityManager.isActiveNetworkMetered();
+    }
+
+    private class NetworkTracker extends ConnectivityManager.NetworkCallback {
+        private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
+
+        private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+        private final boolean mExpectedMetered;
+
+        private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
+                    checkActiveNetwork();
+                }
+            }
+        };
+
+        private NetworkTracker(boolean expectedMetered) {
+            mExpectedMetered = expectedMetered;
+        }
+
+        @Override
+        public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
+                LinkProperties linkProperties, boolean blocked) {
+            checkActiveNetwork();
+        }
+
+        @Override
+        public void onLost(Network network) {
+            checkActiveNetwork();
+        }
+
+        boolean waitForExpectedState() throws InterruptedException {
+            checkActiveNetwork();
+            return mReceiveLatch.await(60, TimeUnit.SECONDS);
+        }
+
+        private void checkActiveNetwork() {
+            if (mReceiveLatch.getCount() == 0) {
+                return;
+            }
+
+            if (mConnectivityManager.getActiveNetwork() != null
+                    && mConnectivityManager.isActiveNetworkMetered() == mExpectedMetered) {
+                mReceiveLatch.countDown();
+            } else {
+                mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
+            }
+        }
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java
new file mode 100644
index 0000000..dbe5773
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java
@@ -0,0 +1,278 @@
+/*
+ * 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.frameworks.core.batterystatsloadtests;
+
+import android.os.Process;
+
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PowerMetrics {
+    private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
+    private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
+    private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
+    private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
+            PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
+
+    enum MetricKind {
+        POWER,
+        DURATION,
+    }
+
+    public static final String METRIC_APP_POWER = "appPower";
+    public static final String METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL = "appPowerExcludeSystem";
+    public static final String METRIC_APP_POWER_EXCLUDE_SMEARED = "appPowerExcludeSmeared";
+    public static final String METRIC_SCREEN_POWER = "screenPower";
+    public static final String METRIC_WIFI_POWER = "wifiPower";
+    public static final String METRIC_SYSTEM_SERVICE_CPU_POWER = "systemService";
+    public static final String METRIC_OTHER_POWER = "otherPower";
+    public static final String METRIC_CPU_POWER = "cpuPower";
+    public static final String METRIC_RAM_POWER = "ramPower";
+    public static final String METRIC_WAKELOCK_POWER = "wakelockPower";
+    public static final String METRIC_MOBILE_RADIO_POWER = "mobileRadioPower";
+    public static final String METRIC_BLUETOOTH_POWER = "bluetoothPower";
+    public static final String METRIC_GPS_POWER = "gpsPower";
+    public static final String METRIC_CAMERA_POWER = "cameraPower";
+    public static final String METRIC_FLASHLIGHT_POWER = "flashlightPower";
+    public static final String METRIC_SENSORS_POWER = "sensorsPower";
+    public static final String METRIC_AUDIO_POWER = "audioPower";
+    public static final String METRIC_VIDEO_POWER = "videoPower";
+    public static final String METRIC_CPU_TIME = "cpuTime";
+    public static final String METRIC_CPU_FOREGROUND_TIME = "cpuForegroundTime";
+    public static final String METRIC_WAKELOCK_TIME = "wakelockTime";
+    public static final String METRIC_WIFI_RUNNING_TIME = "wifiRunningTime";
+    public static final String METRIC_BLUETOOTH_RUNNING_TIME = "bluetoothRunningTime";
+    public static final String METRIC_GPS_TIME = "gpsTime";
+    public static final String METRIC_CAMERA_TIME = "cameraTime";
+    public static final String METRIC_FLASHLIGHT_TIME = "flashlightTime";
+    public static final String METRIC_AUDIO_TIME = "audioTime";
+    public static final String METRIC_VIDEO_TIME = "videoTime";
+
+    public static class Metric {
+        public String metricType;
+        public MetricKind metricKind;
+        public String title;
+        public double value;
+        public double total;
+    }
+
+    private final double mMinDrainedPower;
+    private final double mMaxDrainedPower;
+
+    private List<Metric> mMetrics = new ArrayList<>();
+
+    public PowerMetrics(BatteryStatsHelper batteryStatsHelper, int uid) {
+        mMinDrainedPower = batteryStatsHelper.getMinDrainedPower();
+        mMaxDrainedPower = batteryStatsHelper.getMaxDrainedPower();
+
+        List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
+
+        double totalPowerMah = 0;
+        double totalSmearedPowerMah = 0;
+        double totalPowerExcludeSystemMah = 0;
+        double totalScreenPower = 0;
+        double totalProportionalSmearMah = 0;
+        double totalCpuPowerMah = 0;
+        double totalSystemServiceCpuPowerMah = 0;
+        double totalUsagePowerMah = 0;
+        double totalWakeLockPowerMah = 0;
+        double totalMobileRadioPowerMah = 0;
+        double totalWifiPowerMah = 0;
+        double totalBluetoothPowerMah = 0;
+        double totalGpsPowerMah = 0;
+        double totalCameraPowerMah = 0;
+        double totalFlashlightPowerMah = 0;
+        double totalSensorPowerMah = 0;
+        double totalAudioPowerMah = 0;
+        double totalVideoPowerMah = 0;
+
+        long totalCpuTimeMs = 0;
+        long totalCpuFgTimeMs = 0;
+        long totalWakeLockTimeMs = 0;
+        long totalWifiRunningTimeMs = 0;
+        long totalBluetoothRunningTimeMs = 0;
+        long totalGpsTimeMs = 0;
+        long totalCameraTimeMs = 0;
+        long totalFlashlightTimeMs = 0;
+        long totalAudioTimeMs = 0;
+        long totalVideoTimeMs = 0;
+
+        BatterySipper uidSipper = null;
+        for (BatterySipper sipper : usageList) {
+            if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
+                totalScreenPower = sipper.sumPower();
+            }
+
+            if (isHiddenDrainType(sipper.drainType)) {
+                continue;
+            }
+
+            if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) {
+                uidSipper = sipper;
+            }
+
+            totalPowerMah += sipper.sumPower();
+            totalSmearedPowerMah += sipper.totalSmearedPowerMah;
+            totalProportionalSmearMah += sipper.proportionalSmearMah;
+
+            if (!isSystemSipper(sipper)) {
+                totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
+            }
+
+            totalCpuPowerMah += sipper.cpuPowerMah;
+            totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
+            totalUsagePowerMah += sipper.usagePowerMah;
+            totalWakeLockPowerMah += sipper.wakeLockPowerMah;
+            totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
+            totalWifiPowerMah += sipper.wifiPowerMah;
+            totalBluetoothPowerMah += sipper.bluetoothPowerMah;
+            totalGpsPowerMah += sipper.gpsPowerMah;
+            totalCameraPowerMah += sipper.cameraPowerMah;
+            totalFlashlightPowerMah += sipper.flashlightPowerMah;
+            totalSensorPowerMah += sipper.sensorPowerMah;
+            totalAudioPowerMah += sipper.audioPowerMah;
+            totalVideoPowerMah += sipper.videoPowerMah;
+
+            totalCpuTimeMs += sipper.cpuTimeMs;
+            totalCpuFgTimeMs += sipper.cpuFgTimeMs;
+            totalWakeLockTimeMs += sipper.wakeLockTimeMs;
+            totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
+            totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
+            totalGpsTimeMs += sipper.gpsTimeMs;
+            totalCameraTimeMs += sipper.cameraTimeMs;
+            totalFlashlightTimeMs += sipper.flashlightTimeMs;
+            totalAudioTimeMs += sipper.audioTimeMs;
+            totalVideoTimeMs += sipper.videoTimeMs;
+        }
+
+        if (uidSipper == null) {
+            return;
+        }
+
+        addMetric(METRIC_APP_POWER, MetricKind.POWER, "Total power",
+                uidSipper.totalSmearedPowerMah, totalSmearedPowerMah);
+        addMetric(METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL, MetricKind.POWER,
+                "Total power excluding system",
+                uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah);
+        addMetric(METRIC_SCREEN_POWER, MetricKind.POWER, "Screen, smeared",
+                uidSipper.screenPowerMah, totalScreenPower);
+        addMetric(METRIC_OTHER_POWER, MetricKind.POWER, "Other, smeared",
+                uidSipper.proportionalSmearMah, totalProportionalSmearMah);
+        addMetric(METRIC_APP_POWER_EXCLUDE_SMEARED, MetricKind.POWER, "Excluding smeared",
+                uidSipper.totalPowerMah, totalPowerMah);
+        addMetric(METRIC_CPU_POWER, MetricKind.POWER, "CPU",
+                uidSipper.cpuPowerMah, totalCpuPowerMah);
+        addMetric(METRIC_SYSTEM_SERVICE_CPU_POWER, MetricKind.POWER, "System services",
+                uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
+        addMetric(METRIC_RAM_POWER, MetricKind.POWER, "RAM",
+                uidSipper.usagePowerMah, totalUsagePowerMah);
+        addMetric(METRIC_WAKELOCK_POWER, MetricKind.POWER, "Wake lock",
+                uidSipper.wakeLockPowerMah, totalWakeLockPowerMah);
+        addMetric(METRIC_MOBILE_RADIO_POWER, MetricKind.POWER, "Mobile radio",
+                uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah);
+        addMetric(METRIC_WIFI_POWER, MetricKind.POWER, "WiFi",
+                uidSipper.wifiPowerMah, totalWifiPowerMah);
+        addMetric(METRIC_BLUETOOTH_POWER, MetricKind.POWER, "Bluetooth",
+                uidSipper.bluetoothPowerMah, totalBluetoothPowerMah);
+        addMetric(METRIC_GPS_POWER, MetricKind.POWER, "GPS",
+                uidSipper.gpsPowerMah, totalGpsPowerMah);
+        addMetric(METRIC_CAMERA_POWER, MetricKind.POWER, "Camera",
+                uidSipper.cameraPowerMah, totalCameraPowerMah);
+        addMetric(METRIC_FLASHLIGHT_POWER, MetricKind.POWER, "Flashlight",
+                uidSipper.flashlightPowerMah, totalFlashlightPowerMah);
+        addMetric(METRIC_SENSORS_POWER, MetricKind.POWER, "Sensors",
+                uidSipper.sensorPowerMah, totalSensorPowerMah);
+        addMetric(METRIC_AUDIO_POWER, MetricKind.POWER, "Audio",
+                uidSipper.audioPowerMah, totalAudioPowerMah);
+        addMetric(METRIC_VIDEO_POWER, MetricKind.POWER, "Video",
+                uidSipper.videoPowerMah, totalVideoPowerMah);
+
+        addMetric(METRIC_CPU_TIME, MetricKind.DURATION, "CPU time",
+                uidSipper.cpuTimeMs, totalCpuTimeMs);
+        addMetric(METRIC_CPU_FOREGROUND_TIME, MetricKind.DURATION, "CPU foreground time",
+                uidSipper.cpuFgTimeMs, totalCpuFgTimeMs);
+        addMetric(METRIC_WAKELOCK_TIME, MetricKind.DURATION, "Wake lock time",
+                uidSipper.wakeLockTimeMs, totalWakeLockTimeMs);
+        addMetric(METRIC_WIFI_RUNNING_TIME, MetricKind.DURATION, "WiFi running time",
+                uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs);
+        addMetric(METRIC_BLUETOOTH_RUNNING_TIME, MetricKind.DURATION, "Bluetooth time",
+                uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
+        addMetric(METRIC_GPS_TIME, MetricKind.DURATION, "GPS time",
+                uidSipper.gpsTimeMs, totalGpsTimeMs);
+        addMetric(METRIC_CAMERA_TIME, MetricKind.DURATION, "Camera time",
+                uidSipper.cameraTimeMs, totalCameraTimeMs);
+        addMetric(METRIC_FLASHLIGHT_TIME, MetricKind.DURATION, "Flashlight time",
+                uidSipper.flashlightTimeMs, totalFlashlightTimeMs);
+        addMetric(METRIC_AUDIO_TIME, MetricKind.DURATION, "Audio time",
+                uidSipper.audioTimeMs, totalAudioTimeMs);
+        addMetric(METRIC_VIDEO_TIME, MetricKind.DURATION, "Video time",
+                uidSipper.videoTimeMs, totalVideoTimeMs);
+    }
+
+    public List<Metric> getMetrics() {
+        return mMetrics;
+    }
+
+    public double getMinDrainedPower() {
+        return mMinDrainedPower;
+    }
+
+    public double getMaxDrainedPower() {
+        return mMaxDrainedPower;
+    }
+
+    protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) {
+        return drainType == BatterySipper.DrainType.IDLE
+                || drainType == BatterySipper.DrainType.CELL
+                || drainType == BatterySipper.DrainType.SCREEN
+                || drainType == BatterySipper.DrainType.UNACCOUNTED
+                || drainType == BatterySipper.DrainType.OVERCOUNTED
+                || drainType == BatterySipper.DrainType.BLUETOOTH
+                || drainType == BatterySipper.DrainType.WIFI;
+    }
+
+    private boolean isSystemSipper(BatterySipper sipper) {
+        final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
+        if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
+            return true;
+        } else if (sipper.mPackages != null) {
+            for (final String packageName : sipper.mPackages) {
+                for (final String systemPackage : PACKAGES_SYSTEM) {
+                    if (systemPackage.equals(packageName)) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private void addMetric(String metricType, MetricKind metricKind, String title, double amount,
+            double totalAmount) {
+        Metric metric = new Metric();
+        metric.metricType = metricType;
+        metric.metricKind = metricKind;
+        metric.title = title;
+        metric.value = amount;
+        metric.total = totalAmount;
+        mMetrics.add(metric);
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java
new file mode 100644
index 0000000..254458c
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java
@@ -0,0 +1,305 @@
+/*
+ * 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.frameworks.core.batterystatsloadtests;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.TimeUtils;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.os.LoggingPrintStream;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PowerMetricsCollector implements TestRule {
+    private final String mTag;
+    private final float mBatteryDrainThresholdPct;
+    private final int mTimeoutMillis;
+
+    private final Context mContext;
+    private final UserManager mUserManager;
+    private final int mUid;
+    private final BatteryStatsHelper mStatsHelper;
+    private final CountDownLatch mSuspendingBatteryInput = new CountDownLatch(1);
+
+    private long mStartTime;
+    private volatile float mInitialBatteryLevel;
+    private volatile float mCurrentBatteryLevel;
+    private int mIterations;
+    private PowerMetrics mInitialPowerMetrics;
+    private PowerMetrics mFinalPowerMetrics;
+    private List<PowerMetrics.Metric> mPowerMetricsDelta;
+    private Intent mBatteryStatus;
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                BroadcastReceiver batteryBroadcastReceiver = new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        handleBatteryStatus(intent);
+                    }
+                };
+                mBatteryStatus = mContext.registerReceiver(batteryBroadcastReceiver,
+                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+                disableCharger();
+                try {
+                    prepareBatteryLevelMonitor();
+                    mStartTime = SystemClock.uptimeMillis();
+                    base.evaluate();
+                    captureFinalPowerStatsData();
+                } finally {
+                    mContext.unregisterReceiver(batteryBroadcastReceiver);
+                    enableCharger();
+                }
+            }
+        };
+    }
+
+    public PowerMetricsCollector(String tag, float batteryDrainThresholdPct, int timeoutMillis) {
+        mTag = tag;
+        mBatteryDrainThresholdPct = batteryDrainThresholdPct;
+        mTimeoutMillis = timeoutMillis;
+
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        mContext = instrumentation.getContext();
+        mUid = Process.myUid();
+        mUserManager = mContext.getSystemService(UserManager.class);
+        // TODO(b/175324611): Use BatteryUsageStats instead
+        mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */);
+        mStatsHelper.create((Bundle) null);
+    }
+
+    private void disableCharger() throws InterruptedException {
+        SystemUtil.runShellCommand("dumpsys battery suspend_input");
+        final boolean success = mSuspendingBatteryInput.await(10, TimeUnit.SECONDS);
+        assertTrue("Timed out waiting for battery input to be suspended", success);
+    }
+
+    private void enableCharger() {
+        SystemUtil.runShellCommand("dumpsys battery reset");
+    }
+
+    private PowerMetrics readBatteryStatsData() {
+        mStatsHelper.clearStats();
+        mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
+                mUserManager.getUserProfiles());
+        return new PowerMetrics(mStatsHelper, mUid);
+    }
+
+    protected void prepareBatteryLevelMonitor() {
+        handleBatteryStatus(mBatteryStatus);
+        mInitialBatteryLevel = mCurrentBatteryLevel;
+    }
+
+    protected void handleBatteryStatus(Intent intent) {
+        if (mFinalPowerMetrics != null) {
+            return;
+        }
+
+        final boolean isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
+
+        if (mSuspendingBatteryInput.getCount() > 0) {
+            if (!isCharging) {
+                mSuspendingBatteryInput.countDown();
+            }
+            return;
+        }
+
+        if (isCharging) {
+            fail("Device must remain disconnected from the power source "
+                    + "for the duration of the test");
+        }
+
+        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+
+        mCurrentBatteryLevel = level * 100 / (float) scale;
+        Log.i(mTag, "Battery level = " + mCurrentBatteryLevel);
+
+        // We delay tracking until the battery level drops.  If the resolution of
+        // battery level is 1%, and the initially reported level is 73, we don't know whether
+        // it's 73.1 or 73.7. Once it drops to 72, we can be confident that the real battery
+        // level it is very close to 72.0 and can start tracking.
+        if (mInitialPowerMetrics == null && mCurrentBatteryLevel < mInitialBatteryLevel) {
+            mInitialBatteryLevel = mCurrentBatteryLevel;
+            mInitialPowerMetrics = readBatteryStatsData();
+        }
+    }
+
+    private void captureFinalPowerStatsData() {
+        if (mFinalPowerMetrics != null) {
+            return;
+        }
+
+        mFinalPowerMetrics = readBatteryStatsData();
+
+        mPowerMetricsDelta = new ArrayList<>();
+        List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
+        List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
+        for (PowerMetrics.Metric initialMetric : initialPowerMetrics) {
+            PowerMetrics.Metric finalMetric = null;
+            for (PowerMetrics.Metric metric : finalPowerMetrics) {
+                if (metric.title.equals(initialMetric.title)) {
+                    finalMetric = metric;
+                    break;
+                }
+            }
+
+            if (finalMetric != null) {
+                PowerMetrics.Metric delta = new PowerMetrics.Metric();
+                delta.metricType = initialMetric.metricType;
+                delta.metricKind = initialMetric.metricKind;
+                delta.title = initialMetric.title;
+                delta.total = finalMetric.total - initialMetric.total;
+                delta.value = finalMetric.value - initialMetric.value;
+                mPowerMetricsDelta.add(delta);
+            }
+        }
+    }
+
+    /**
+     * Returns false if sufficient data has been accumulated.
+     */
+    public boolean checkpoint() {
+        long elapsedTime = SystemClock.uptimeMillis() - mStartTime;
+        if (elapsedTime >= mTimeoutMillis) {
+            Log.i(mTag, "Timeout reached " + TimeUtils.formatDuration(elapsedTime));
+            captureFinalPowerStatsData();
+            return false;
+        }
+
+        if (mInitialPowerMetrics == null) {
+            return true;
+        }
+
+        if (mInitialBatteryLevel - mCurrentBatteryLevel >= mBatteryDrainThresholdPct) {
+            Log.i(mTag,
+                    "Battery drain reached " + (mInitialBatteryLevel - mCurrentBatteryLevel) + "%");
+            captureFinalPowerStatsData();
+            return false;
+        }
+
+        mIterations++;
+        return true;
+    }
+
+
+    public int getIterationCount() {
+        return mIterations;
+    }
+
+    public void dumpMetrics() {
+        dumpMetrics(new LoggingPrintStream() {
+            @Override
+            protected void log(String line) {
+                Log.i(mTag, line);
+            }
+        });
+    }
+
+    public void dumpMetrics(PrintStream out) {
+        List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
+        List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
+
+        out.println("== Power metrics at test start");
+        dumpPowerStatsData(out, initialPowerMetrics);
+
+        out.println("== Power metrics at test end");
+        dumpPowerStatsData(out, finalPowerMetrics);
+
+        out.println("== Power metrics delta");
+        dumpPowerStatsData(out, mPowerMetricsDelta);
+    }
+
+    protected void dumpPowerStatsData(PrintStream out, List<PowerMetrics.Metric> metrics) {
+        Locale locale = Locale.getDefault();
+        for (PowerMetrics.Metric metric : metrics) {
+            double proportion = metric.total != 0 ? metric.value * 100 / metric.total : 0;
+            switch (metric.metricKind) {
+                case POWER:
+                    out.println(
+                            String.format(locale, "    %-30s %7.1f mAh %4.1f%%", metric.title,
+                                    metric.value, proportion));
+                    break;
+                case DURATION:
+                    out.println(
+                            String.format(locale, "    %-30s %,7d ms  %4.1f%%", metric.title,
+                                    (long) metric.value, proportion));
+                    break;
+            }
+        }
+    }
+
+    public void dumpMetricAsPercentageOfDrainedPower(String metricType) {
+        double minDrainedPower =
+                mFinalPowerMetrics.getMinDrainedPower() - mInitialPowerMetrics.getMinDrainedPower();
+        double maxDrainedPower =
+                mFinalPowerMetrics.getMaxDrainedPower() - mInitialPowerMetrics.getMaxDrainedPower();
+
+        PowerMetrics.Metric metric = getMetric(metricType);
+        double metricDelta = metric.value;
+
+        if (maxDrainedPower - minDrainedPower < 0.1f) {
+            Log.i(mTag, String.format(Locale.getDefault(),
+                    "%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
+                    metric.title, metricDelta, maxDrainedPower,
+                    metricDelta / maxDrainedPower * 100));
+        } else {
+            Log.i(mTag, String.format(Locale.getDefault(),
+                    "%s power consumed by the test: %.1f of %.1f - %.1f mAh (%.1f%% - %.1f%%)",
+                    metric.title, metricDelta, minDrainedPower, maxDrainedPower,
+                    metricDelta / minDrainedPower * 100, metricDelta / maxDrainedPower * 100));
+        }
+    }
+
+    public PowerMetrics.Metric getMetric(String metricType) {
+        for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
+            if (metric.metricType.equals(metricType)) {
+                return metric;
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java
new file mode 100644
index 0000000..488469d
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworks.core.batterystatsloadtests;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class SystemServiceCallLoadTest {
+    private static final String TAG = "SystemServiceCallLoadTest";
+    private static final int TIMEOUT_MILLIS = 60 * 60 * 1000;
+    private static final float BATTERY_DRAIN_THRESHOLD_PCT = 2.99f;
+
+    @Rule
+    public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG,
+            BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS);
+
+    private PackageManager mPackageManager;
+
+    @Before
+    public void setup() {
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        mPackageManager = instrumentation.getContext().getPackageManager();
+    }
+
+    @Test
+    public void test() {
+        while (mPowerMetricsCollector.checkpoint()) {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.setDataAndType(Uri.parse("http://example.com/"), "text/plain");
+            intent.addCategory(Intent.CATEGORY_BROWSABLE);
+            ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
+            assertNotNull(resolveInfo);
+        }
+
+        mPowerMetricsCollector.dumpMetrics();
+
+        Log.i(TAG, "==");
+        Log.i(TAG, "Total system server calls made " + mPowerMetricsCollector.getIterationCount());
+
+        mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
+                PowerMetrics.METRIC_SYSTEM_SERVICE_CPU_POWER);
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java
new file mode 100644
index 0000000..27495da
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.frameworks.core.batterystatsloadtests;
+
+import android.util.Log;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+public class WiFiLoadTest {
+    private static final String TAG = "WiFiLoadTest";
+    private static final String DOWNLOAD_TEST_URL =
+            "https://i.ytimg.com/vi/l5mE3Tpjejs/maxresdefault.jpg";
+
+    private static final int TIMEOUT_MILLIS = 60 * 60 * 1000;
+    private static final float BATTERY_DRAIN_THRESHOLD_PCT = 0.99f;
+
+    @Rule
+    public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG,
+            BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS);
+
+    @Rule
+    public ConnectivitySetupRule mConnectivitySetupRule =
+            new ConnectivitySetupRule(/* WiFi enabled */true);
+
+    @Test
+    public void test() throws IOException {
+        long totalBytesRead = 0;
+        URL url = new URL(DOWNLOAD_TEST_URL);
+        byte[] buffer = new byte[131072];  // Large buffer to minimize CPU usage
+
+        while (mPowerMetricsCollector.checkpoint()) {
+            try (InputStream inputStream = url.openStream()) {
+                while (true) {
+                    int count = inputStream.read(buffer);
+                    if (count < 0) {
+                        break;
+                    }
+                    totalBytesRead += count;
+                }
+            }
+        }
+
+        mPowerMetricsCollector.dumpMetrics();
+
+        Log.i(TAG, "==");
+        Log.i(TAG, "WiFi running time: " + (long) mPowerMetricsCollector.getMetric(
+                PowerMetrics.METRIC_WIFI_RUNNING_TIME).value);
+        Log.i(TAG, "Total bytes read over WiFi: " + totalBytesRead);
+
+        mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
+                PowerMetrics.METRIC_WIFI_POWER);
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/Android.bp b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
new file mode 100644
index 0000000..1e0498b
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
@@ -0,0 +1,13 @@
+android_test {
+    name: "BatteryStatsViewer",
+    srcs: ["src/**/*.java"],
+    defaults: ["SettingsLibDefaults"],
+    static_libs: [
+        "androidx.appcompat_appcompat",
+        "androidx.cardview_cardview",
+        "androidx.recyclerview_recyclerview",
+        "com.google.android.material_material",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/AndroidManifest.xml b/core/tests/batterystatstests/BatteryStatsViewer/AndroidManifest.xml
new file mode 100644
index 0000000..edb1b10
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.frameworks.core.batterystatsviewer"
+          android:sharedUserId="android.uid.system">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.BATTERY_STATS"/>
+
+    <application
+        android:theme="@style/Theme"
+        android:label="Battery Stats Viewer">
+        <activity android:name=".BatteryStatsViewerActivity"
+                  android:label="Battery Stats Viewer"
+                  android:launchMode="singleTop"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BatteryConsumerPickerActivity"
+                  android:label="Select a battery consumer"/>
+    </application>
+</manifest>
diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_entry_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml
similarity index 100%
rename from core/tests/powertests/PowerStatsViewer/res/layout/power_stats_entry_layout.xml
rename to core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml
diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_info_layout.xml
similarity index 100%
rename from core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml
rename to core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_info_layout.xml
diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_activity_layout.xml
similarity index 100%
rename from core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml
rename to core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_activity_layout.xml
diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_layout.xml
similarity index 100%
rename from core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml
rename to core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_layout.xml
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml
new file mode 100644
index 0000000..e58a08f
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <androidx.cardview.widget.CardView
+            style="@style/LoadTestCardView"
+            android:id="@+id/app_card"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:layout_marginEnd="10dp"
+            android:layout_marginBottom="10dp"
+            android:layout_marginStart="10dp"
+            android:padding="20dp">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:minHeight="80dp"
+                android:paddingStart="10dp"
+                android:paddingEnd="10dp">
+
+                <include layout="@layout/battery_consumer_info_layout"/>
+
+            </LinearLayout>
+        </androidx.cardview.widget.CardView>
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/battery_consumer_data_view"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+        <TextView
+            android:id="@+id/empty_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:visibility="gone"
+            android:text="No battery stats available"/>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/loading_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#AAFFFFFF">
+        <ProgressBar
+            style="?android:attr/progressBarStyleLarge"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:indeterminate="true"/>
+    </FrameLayout>
+</FrameLayout>
diff --git a/core/tests/powertests/PowerStatsViewer/res/values/styles.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/values/styles.xml
similarity index 100%
rename from core/tests/powertests/PowerStatsViewer/res/values/styles.xml
rename to core/tests/batterystatstests/BatteryStatsViewer/res/values/styles.xml
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
new file mode 100644
index 0000000..8086ff2
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -0,0 +1,332 @@
+/*
+ * 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.frameworks.core.batterystatsviewer;
+
+import android.content.Context;
+import android.os.BatteryConsumer;
+import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+import android.os.UserHandle;
+
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BatteryConsumerData {
+    private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
+    private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
+    private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
+    private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
+            PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
+
+    // Temporary placeholder voltage for converting energy to charge
+    // TODO: remove this when b/173765509 is resolved
+    private static final double MOCK_NOMINAL_VOLTAGE = 3.7;
+
+    // Unit conversion:
+    //   mAh = uWs * (1/1000)(milli/micro) * (1/Voltage) * (1/3600)(hours/second)
+    private static final double UJ_2_MAH =
+            (1.0 / 1000) * (1.0 / MOCK_NOMINAL_VOLTAGE) * (1.0 / 3600);
+
+    enum EntryType {
+        POWER,
+        DURATION,
+    }
+
+    public static class Entry {
+        public String title;
+        public EntryType entryType;
+        public double value;
+        public double total;
+    }
+
+    private final BatteryConsumerInfoHelper.BatteryConsumerInfo mBatteryConsumerInfo;
+    private final List<Entry> mEntries = new ArrayList<>();
+
+    public BatteryConsumerData(Context context, BatteryStatsHelper batteryStatsHelper,
+            BatteryUsageStats batteryUsageStats, String batteryConsumerId) {
+        List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
+        BatteryStats batteryStats = batteryStatsHelper.getStats();
+
+        double totalPowerMah = 0;
+        double totalSmearedPowerMah = 0;
+        double totalPowerExcludeSystemMah = 0;
+        double totalScreenPower = 0;
+        double totalProportionalSmearMah = 0;
+        double totalCpuPowerMah = 0;
+        double totalSystemServiceCpuPowerMah = 0;
+        double totalUsagePowerMah = 0;
+        double totalWakeLockPowerMah = 0;
+        double totalMobileRadioPowerMah = 0;
+        double totalWifiPowerMah = 0;
+        double totalBluetoothPowerMah = 0;
+        double totalGpsPowerMah = 0;
+        double totalCameraPowerMah = 0;
+        double totalFlashlightPowerMah = 0;
+        double totalSensorPowerMah = 0;
+        double totalAudioPowerMah = 0;
+        double totalVideoPowerMah = 0;
+
+        long totalCpuTimeMs = 0;
+        long totalCpuFgTimeMs = 0;
+        long totalWakeLockTimeMs = 0;
+        long totalWifiRunningTimeMs = 0;
+        long totalBluetoothRunningTimeMs = 0;
+        long totalGpsTimeMs = 0;
+        long totalCameraTimeMs = 0;
+        long totalFlashlightTimeMs = 0;
+        long totalAudioTimeMs = 0;
+        long totalVideoTimeMs = 0;
+
+        BatterySipper requestedBatterySipper = null;
+        for (BatterySipper sipper : usageList) {
+            if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
+                totalScreenPower = sipper.sumPower();
+            }
+
+            if (batteryConsumerId(sipper).equals(batteryConsumerId)) {
+                requestedBatterySipper = sipper;
+            }
+
+            totalPowerMah += sipper.sumPower();
+            totalSmearedPowerMah += sipper.totalSmearedPowerMah;
+            totalProportionalSmearMah += sipper.proportionalSmearMah;
+
+            if (!isSystemSipper(sipper)) {
+                totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
+            }
+
+            totalCpuPowerMah += sipper.cpuPowerMah;
+            totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
+            totalUsagePowerMah += sipper.usagePowerMah;
+            totalWakeLockPowerMah += sipper.wakeLockPowerMah;
+            totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
+            totalWifiPowerMah += sipper.wifiPowerMah;
+            totalBluetoothPowerMah += sipper.bluetoothPowerMah;
+            totalGpsPowerMah += sipper.gpsPowerMah;
+            totalCameraPowerMah += sipper.cameraPowerMah;
+            totalFlashlightPowerMah += sipper.flashlightPowerMah;
+            totalSensorPowerMah += sipper.sensorPowerMah;
+            totalAudioPowerMah += sipper.audioPowerMah;
+            totalVideoPowerMah += sipper.videoPowerMah;
+
+            totalCpuTimeMs += sipper.cpuTimeMs;
+            totalCpuFgTimeMs += sipper.cpuFgTimeMs;
+            totalWakeLockTimeMs += sipper.wakeLockTimeMs;
+            totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
+            totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
+            totalGpsTimeMs += sipper.gpsTimeMs;
+            totalCameraTimeMs += sipper.cameraTimeMs;
+            totalFlashlightTimeMs += sipper.flashlightTimeMs;
+            totalAudioTimeMs += sipper.audioTimeMs;
+            totalVideoTimeMs += sipper.videoTimeMs;
+        }
+
+        BatteryConsumer requestedBatteryConsumer = null;
+        double totalModeledCpuPowerMah = 0;
+
+        for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
+            if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
+                requestedBatteryConsumer = consumer;
+            }
+
+            totalModeledCpuPowerMah += consumer.getConsumedPowerForCustomComponent(
+                    BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                            + BatteryConsumer.POWER_COMPONENT_CPU);
+        }
+
+        if (requestedBatterySipper == null) {
+            mBatteryConsumerInfo = null;
+            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();
+
+        addEntry("Total power", EntryType.POWER,
+                requestedBatterySipper.totalSmearedPowerMah, totalSmearedPowerMah);
+        maybeAddMeasuredEnergyEntry(requestedBatterySipper.drainType, batteryStats);
+
+        addEntry("... excluding system", EntryType.POWER,
+                requestedBatterySipper.totalSmearedPowerMah, totalPowerExcludeSystemMah);
+        addEntry("Screen, smeared", EntryType.POWER,
+                requestedBatterySipper.screenPowerMah, totalScreenPower);
+        if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
+            final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ;
+            final double ratio = measuredCharge / totalScreenPower;
+            addEntry("Screen, smeared (PowerStatsHal adjusted)", EntryType.POWER,
+                    requestedBatterySipper.screenPowerMah * ratio, measuredCharge);
+        }
+        addEntry("Other, smeared", EntryType.POWER,
+                requestedBatterySipper.proportionalSmearMah, totalProportionalSmearMah);
+        addEntry("Excluding smeared", EntryType.POWER,
+                requestedBatterySipper.totalPowerMah, totalPowerMah);
+        if (requestedBatteryConsumer != null) {
+            addEntry("CPU", EntryType.POWER,
+                    requestedBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU),
+                    totalCpuPowerMah);
+            if (totalModeledCpuPowerMah != 0) {
+                addEntry("CPU (modeled)", EntryType.POWER,
+                        requestedBatteryConsumer.getConsumedPowerForCustomComponent(
+                                BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                                        + BatteryConsumer.POWER_COMPONENT_CPU),
+                        totalModeledCpuPowerMah);
+            }
+        } else {
+            addEntry("CPU (sipper)", EntryType.POWER,
+                    requestedBatterySipper.cpuPowerMah, totalCpuPowerMah);
+        }
+        addEntry("System services", EntryType.POWER,
+                requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
+        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,
+                requestedBatterySipper.mobileRadioPowerMah, totalMobileRadioPowerMah);
+        addEntry("WiFi", EntryType.POWER,
+                requestedBatterySipper.wifiPowerMah, totalWifiPowerMah);
+        addEntry("Bluetooth", EntryType.POWER,
+                requestedBatterySipper.bluetoothPowerMah, totalBluetoothPowerMah);
+        addEntry("GPS", EntryType.POWER,
+                requestedBatterySipper.gpsPowerMah, totalGpsPowerMah);
+        addEntry("Camera", EntryType.POWER,
+                requestedBatterySipper.cameraPowerMah, totalCameraPowerMah);
+        addEntry("Flashlight", EntryType.POWER,
+                requestedBatterySipper.flashlightPowerMah, totalFlashlightPowerMah);
+        addEntry("Sensors", EntryType.POWER,
+                requestedBatterySipper.sensorPowerMah, totalSensorPowerMah);
+        addEntry("Audio", EntryType.POWER,
+                requestedBatterySipper.audioPowerMah, totalAudioPowerMah);
+        addEntry("Video", EntryType.POWER,
+                requestedBatterySipper.videoPowerMah, totalVideoPowerMah);
+
+        addEntry("CPU time", EntryType.DURATION,
+                requestedBatterySipper.cpuTimeMs, totalCpuTimeMs);
+        addEntry("CPU foreground time", EntryType.DURATION,
+                requestedBatterySipper.cpuFgTimeMs, totalCpuFgTimeMs);
+        addEntry("Wake lock time", EntryType.DURATION,
+                requestedBatterySipper.wakeLockTimeMs, totalWakeLockTimeMs);
+        addEntry("WiFi running time", EntryType.DURATION,
+                requestedBatterySipper.wifiRunningTimeMs, totalWifiRunningTimeMs);
+        addEntry("Bluetooth time", EntryType.DURATION,
+                requestedBatterySipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
+        addEntry("GPS time", EntryType.DURATION,
+                requestedBatterySipper.gpsTimeMs, totalGpsTimeMs);
+        addEntry("Camera time", EntryType.DURATION,
+                requestedBatterySipper.cameraTimeMs, totalCameraTimeMs);
+        addEntry("Flashlight time", EntryType.DURATION,
+                requestedBatterySipper.flashlightTimeMs, totalFlashlightTimeMs);
+        addEntry("Audio time", EntryType.DURATION,
+                requestedBatterySipper.audioTimeMs, totalAudioTimeMs);
+        addEntry("Video time", EntryType.DURATION,
+                requestedBatterySipper.videoTimeMs, totalVideoTimeMs);
+    }
+
+    private boolean isSystemSipper(BatterySipper sipper) {
+        final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
+        if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
+            return true;
+        } else if (sipper.mPackages != null) {
+            for (final String packageName : sipper.mPackages) {
+                for (final String systemPackage : PACKAGES_SYSTEM) {
+                    if (systemPackage.equals(packageName)) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private void addEntry(String title, EntryType entryType, double amount, double totalAmount) {
+        Entry entry = new Entry();
+        entry.title = title;
+        entry.entryType = entryType;
+        entry.value = amount;
+        entry.total = totalAmount;
+        mEntries.add(entry);
+    }
+
+    private void maybeAddMeasuredEnergyEntry(BatterySipper.DrainType drainType,
+            BatteryStats batteryStats) {
+        switch (drainType) {
+            case AMBIENT_DISPLAY:
+                final long totalDozeMeasuredEnergyUJ = batteryStats.getScreenDozeEnergy();
+                if (totalDozeMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
+                    final double measuredCharge = UJ_2_MAH * totalDozeMeasuredEnergyUJ;
+                    addEntry("Measured ambient display power", EntryType.POWER, measuredCharge,
+                            measuredCharge);
+                }
+                break;
+            case SCREEN:
+                final long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy();
+                if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
+                    final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ;
+                    addEntry("Measured screen power", EntryType.POWER, measuredCharge,
+                            measuredCharge);
+                }
+                break;
+        }
+    }
+
+    public BatteryConsumerInfoHelper.BatteryConsumerInfo getBatteryConsumerInfo() {
+        return mBatteryConsumerInfo;
+    }
+
+    public List<Entry> getEntries() {
+        return mEntries;
+    }
+
+    public static String batteryConsumerId(BatterySipper sipper) {
+        return sipper.drainType + "|" + sipper.userId + "|" + sipper.getUid();
+    }
+
+    public static String batteryConsumerId(BatteryConsumer consumer) {
+        if (consumer instanceof UidBatteryConsumer) {
+            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/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java
new file mode 100644
index 0000000..8ee6c604
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java
@@ -0,0 +1,156 @@
+/*
+ * 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.frameworks.core.batterystatsviewer;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Process;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.os.BatterySipper;
+
+import java.util.Locale;
+
+class BatteryConsumerInfoHelper {
+
+    private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
+
+    public static class BatteryConsumerInfo {
+        public String id;
+        public CharSequence label;
+        public double powerMah;
+        public ApplicationInfo iconInfo;
+        public CharSequence packages;
+        public CharSequence details;
+    }
+
+    @NonNull
+    public static BatteryConsumerInfo makeBatteryConsumerInfo(PackageManager packageManager,
+            @NonNull BatterySipper sipper) {
+        BatteryConsumerInfo info = new BatteryConsumerInfo();
+        info.id = BatteryConsumerData.batteryConsumerId(sipper);
+        sipper.sumPower();
+        info.powerMah = sipper.totalSmearedPowerMah;
+        switch (sipper.drainType) {
+            case APP: {
+                int uid = sipper.getUid();
+                info.details = String.format("UID: %d", uid);
+                String packageWithHighestDrain = sipper.packageWithHighestDrain;
+                if (uid == Process.ROOT_UID) {
+                    info.label = "<root>";
+                } else {
+                    String[] packages = packageManager.getPackagesForUid(uid);
+                    String primaryPackageName = null;
+                    if (uid == Process.SYSTEM_UID) {
+                        primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME;
+                    } else if (packages != null) {
+                        for (String name : packages) {
+                            primaryPackageName = name;
+                            if (name.equals(packageWithHighestDrain)) {
+                                break;
+                            }
+                        }
+                    }
+
+                    if (primaryPackageName != null) {
+                        try {
+                            ApplicationInfo applicationInfo =
+                                    packageManager.getApplicationInfo(primaryPackageName, 0);
+                            info.label = applicationInfo.loadLabel(packageManager);
+                            info.iconInfo = applicationInfo;
+                        } catch (PackageManager.NameNotFoundException e) {
+                            info.label = primaryPackageName;
+                        }
+                    } else if (packageWithHighestDrain != null) {
+                        info.label = packageWithHighestDrain;
+                    }
+
+                    if (packages != null && packages.length > 0) {
+                        StringBuilder sb = new StringBuilder();
+                        if (primaryPackageName != null) {
+                            sb.append(primaryPackageName);
+                        }
+                        for (String packageName : packages) {
+                            if (packageName.equals(primaryPackageName)) {
+                                continue;
+                            }
+
+                            if (sb.length() != 0) {
+                                sb.append(", ");
+                            }
+                            sb.append(packageName);
+                        }
+
+                        info.packages = sb;
+                    }
+                }
+                break;
+            }
+            case USER:
+                info.label = "User";
+                info.details = String.format(Locale.getDefault(), "User ID: %d", sipper.userId);
+                break;
+            case AMBIENT_DISPLAY:
+                info.label = "Ambient display";
+                break;
+            case BLUETOOTH:
+                info.label = "Bluetooth";
+                break;
+            case CAMERA:
+                info.label = "Camera";
+                break;
+            case CELL:
+                info.label = "Cell";
+                break;
+            case FLASHLIGHT:
+                info.label = "Flashlight";
+                break;
+            case IDLE:
+                info.label = "Idle";
+                break;
+            case MEMORY:
+                info.label = "Memory";
+                break;
+            case OVERCOUNTED:
+                info.label = "Overcounted";
+                break;
+            case PHONE:
+                info.label = "Phone";
+                break;
+            case SCREEN:
+                info.label = "Screen";
+                break;
+            case UNACCOUNTED:
+                info.label = "Unaccounted";
+                break;
+            case WIFI:
+                info.label = "WiFi";
+                break;
+        }
+        // Default the app icon to System Server. This includes root, dex2oat and other UIDs.
+        if (info.iconInfo == null) {
+            try {
+                info.iconInfo =
+                        packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0);
+            } catch (PackageManager.NameNotFoundException nameNotFoundException) {
+                // Won't happen
+            }
+        }
+        return info;
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java
new file mode 100644
index 0000000..2db848b
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java
@@ -0,0 +1,116 @@
+/*
+ * 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.frameworks.core.batterystatsviewer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.activity.result.contract.ActivityResultContract;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
+import com.google.android.material.tabs.TabLayout;
+
+/**
+ * Picker, showing a sorted lists of applications and other types of entities consuming power.
+ * Returns the selected entity ID or null.
+ */
+public class BatteryConsumerPickerActivity extends FragmentActivity {
+
+    public static final ActivityResultContract<Void, String> CONTRACT =
+            new ActivityResultContract<Void, String>() {
+                @NonNull
+                @Override
+                public Intent createIntent(@NonNull Context context, Void aVoid) {
+                    return new Intent(context, BatteryConsumerPickerActivity.class);
+                }
+
+                @Override
+                public String parseResult(int resultCode, @Nullable Intent intent) {
+                    if (resultCode != RESULT_OK || intent == null) {
+                        return null;
+                    }
+                    return intent.getStringExtra(Intent.EXTRA_RETURN_RESULT);
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        getActionBar().setDisplayHomeAsUpEnabled(true);
+
+        setContentView(R.layout.battery_consumer_picker_activity_layout);
+
+        ViewPager viewPager = findViewById(R.id.pager);
+
+        FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter(
+                getSupportFragmentManager()) {
+
+            @Override
+            public int getCount() {
+                return 2;
+            }
+
+            @NonNull
+            @Override
+            public Fragment getItem(int position) {
+                switch (position) {
+                    case 0:
+                        return new BatteryConsumerPickerFragment(
+                                BatteryConsumerPickerFragment.PICKER_TYPE_APP);
+                    case 1:
+                    default:
+                        return new BatteryConsumerPickerFragment(
+                                BatteryConsumerPickerFragment.PICKER_TYPE_DRAIN);
+                }
+            }
+
+            @Override
+            public CharSequence getPageTitle(int position) {
+                switch (position) {
+                    case 0:
+                        return "Apps";
+                    case 1:
+                        return "Drains";
+                }
+                return null;
+            }
+        };
+
+        viewPager.setAdapter(adapter);
+        TabLayout tabLayout = findViewById(R.id.tab_layout);
+        tabLayout.setupWithViewPager(viewPager);
+    }
+
+    public void setSelectedBatteryConsumer(String batteryConsumerId) {
+        Intent intent = new Intent();
+        intent.putExtra(Intent.EXTRA_RETURN_RESULT, batteryConsumerId);
+        setResult(RESULT_OK, intent);
+        finish();
+    }
+
+    @Override
+    public boolean onNavigateUp() {
+        onBackPressed();
+        return true;
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java
new file mode 100644
index 0000000..bb11fd5
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.frameworks.core.batterystatsviewer;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.frameworks.core.batterystatsviewer.BatteryConsumerInfoHelper.BatteryConsumerInfo;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Picker, showing a sorted lists of applications or other types of entities consuming power.
+ * Returns the selected entity ID or null.
+ */
+public class BatteryConsumerPickerFragment extends Fragment {
+    private static final String TAG = "AppPicker";
+
+    public static final String PICKER_TYPE = "pickertype";
+
+    public static final int PICKER_TYPE_APP = 0;
+    public static final int PICKER_TYPE_DRAIN = 1;
+
+    private BatteryConsumerListAdapter mBatteryConsumerListAdapter;
+    private RecyclerView mAppList;
+    private View mLoadingView;
+
+    private interface OnBatteryConsumerSelectedListener {
+        void onBatteryConsumerSelected(String batteryConsumerId);
+    }
+
+    public BatteryConsumerPickerFragment(int pickerType) {
+        Bundle args = new Bundle();
+        args.putInt(PICKER_TYPE, pickerType);
+        setArguments(args);
+    }
+
+    public BatteryConsumerPickerFragment() {
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+            @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.battery_consumer_picker_layout, container, false);
+        mLoadingView = view.findViewById(R.id.loading_view);
+
+        mAppList = view.findViewById(R.id.list_view);
+        mAppList.setLayoutManager(new LinearLayoutManager(getContext()));
+        mBatteryConsumerListAdapter = new BatteryConsumerListAdapter(
+                BatteryConsumerPickerFragment.this::setSelectedBatteryConsumer);
+        mAppList.setAdapter(mBatteryConsumerListAdapter);
+
+        LoaderManager.getInstance(this).initLoader(0, getArguments(),
+                new BatteryConsumerListLoaderCallbacks());
+        return view;
+    }
+
+    public void setSelectedBatteryConsumer(String id) {
+        ((BatteryConsumerPickerActivity) getActivity()).setSelectedBatteryConsumer(id);
+    }
+
+    private static class BatteryConsumerListLoader extends
+            AsyncLoaderCompat<List<BatteryConsumerInfo>> {
+        private final BatteryStatsHelper mStatsHelper;
+        private final int mPickerType;
+        private final UserManager mUserManager;
+        private final PackageManager mPackageManager;
+
+        BatteryConsumerListLoader(Context context, int pickerType) {
+            super(context);
+            mUserManager = context.getSystemService(UserManager.class);
+            mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */);
+            mPickerType = pickerType;
+            mStatsHelper.create((Bundle) null);
+            mStatsHelper.clearStats();
+            mPackageManager = context.getPackageManager();
+        }
+
+        @Override
+        public List<BatteryConsumerInfo> loadInBackground() {
+            List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>();
+
+            mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
+
+            final List<BatterySipper> usageList = mStatsHelper.getUsageList();
+            for (BatterySipper sipper : usageList) {
+                switch (mPickerType) {
+                    case PICKER_TYPE_APP:
+                        if (sipper.drainType != BatterySipper.DrainType.APP) {
+                            continue;
+                        }
+                        break;
+                    case PICKER_TYPE_DRAIN:
+                    default:
+                        if (sipper.drainType == BatterySipper.DrainType.APP) {
+                            continue;
+                        }
+                }
+
+                batteryConsumerList.add(
+                        BatteryConsumerInfoHelper.makeBatteryConsumerInfo(mPackageManager, sipper));
+            }
+
+            batteryConsumerList.sort(
+                    Comparator.comparing((BatteryConsumerInfo a) -> a.powerMah).reversed());
+            return batteryConsumerList;
+        }
+
+        @Override
+        protected void onDiscardResult(List<BatteryConsumerInfo> result) {
+        }
+    }
+
+    private class BatteryConsumerListLoaderCallbacks implements
+            LoaderManager.LoaderCallbacks<List<BatteryConsumerInfo>> {
+
+        @NonNull
+        @Override
+        public Loader<List<BatteryConsumerInfo>> onCreateLoader(int id, Bundle args) {
+            return new BatteryConsumerListLoader(getContext(), args.getInt(PICKER_TYPE));
+        }
+
+        @Override
+        public void onLoadFinished(@NonNull Loader<List<BatteryConsumerInfo>> loader,
+                List<BatteryConsumerInfo> batteryConsumerList) {
+            mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList);
+            mAppList.setVisibility(View.VISIBLE);
+            mLoadingView.setVisibility(View.GONE);
+        }
+
+        @Override
+        public void onLoaderReset(
+                @NonNull Loader<List<BatteryConsumerInfo>> loader) {
+        }
+    }
+
+    public class BatteryConsumerListAdapter extends
+            RecyclerView.Adapter<BatteryConsumerViewHolder> {
+        private final OnBatteryConsumerSelectedListener mListener;
+        private List<BatteryConsumerInfo> mBatteryConsumerList;
+
+        public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) {
+            mListener = listener;
+        }
+
+        void setBatteryConsumerList(List<BatteryConsumerInfo> batteryConsumerList) {
+            mBatteryConsumerList = batteryConsumerList;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getItemCount() {
+            return mBatteryConsumerList.size();
+        }
+
+        @NonNull
+        @Override
+        public BatteryConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
+                int position) {
+            LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
+            View view = layoutInflater.inflate(R.layout.battery_consumer_info_layout, viewGroup,
+                    false);
+            return new BatteryConsumerViewHolder(view, mListener);
+        }
+
+        @Override
+        public void onBindViewHolder(@NonNull BatteryConsumerViewHolder viewHolder, int position) {
+            BatteryConsumerInfo item = mBatteryConsumerList.get(position);
+            viewHolder.id = item.id;
+            viewHolder.titleView.setText(item.label);
+            if (item.details != null) {
+                viewHolder.detailsView.setText(item.details);
+                viewHolder.detailsView.setVisibility(View.VISIBLE);
+            } else {
+                viewHolder.detailsView.setVisibility(View.GONE);
+            }
+            viewHolder.powerView.setText(
+                    String.format(Locale.getDefault(), "%.1f mAh", item.powerMah));
+            viewHolder.iconView.setImageDrawable(
+                    item.iconInfo.loadIcon(getContext().getPackageManager()));
+            if (item.packages != null) {
+                viewHolder.packagesView.setText(item.packages);
+                viewHolder.packagesView.setVisibility(View.VISIBLE);
+            } else {
+                viewHolder.packagesView.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    // View Holder used when displaying apps
+    public static class BatteryConsumerViewHolder extends RecyclerView.ViewHolder
+            implements View.OnClickListener {
+        private final OnBatteryConsumerSelectedListener mListener;
+
+        public String id;
+        public TextView titleView;
+        public TextView detailsView;
+        public ImageView iconView;
+        public TextView packagesView;
+        public TextView powerView;
+
+        BatteryConsumerViewHolder(View view, OnBatteryConsumerSelectedListener listener) {
+            super(view);
+            mListener = listener;
+            view.setOnClickListener(this);
+            titleView = view.findViewById(android.R.id.title);
+            detailsView = view.findViewById(R.id.details);
+            iconView = view.findViewById(android.R.id.icon);
+            packagesView = view.findViewById(R.id.packages);
+            powerView = view.findViewById(R.id.power_mah);
+            powerView.setVisibility(View.VISIBLE);
+        }
+
+        @Override
+        public void onClick(View v) {
+            mListener.onBatteryConsumerSelected(id);
+        }
+    }
+}
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
new file mode 100644
index 0000000..87a175a
--- /dev/null
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
@@ -0,0 +1,342 @@
+/*
+ * 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.frameworks.core.batterystatsviewer;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.BatteryStats;
+import android.os.BatteryStatsManager;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.activity.ComponentActivity;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.app.LoaderManager.LoaderCallbacks;
+import androidx.loader.content.Loader;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+public class BatteryStatsViewerActivity extends ComponentActivity {
+    private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
+    public static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId";
+    public static final int LOADER_BATTERY_STATS_HELPER = 0;
+    public static final int LOADER_BATTERY_USAGE_STATS = 1;
+
+    private BatteryStatsDataAdapter mBatteryStatsDataAdapter;
+    private Runnable mBatteryStatsRefresh = this::periodicBatteryStatsRefresh;
+    private SharedPreferences mSharedPref;
+    private String mBatteryConsumerId;
+    private TextView mTitleView;
+    private TextView mDetailsView;
+    private ImageView mIconView;
+    private TextView mPackagesView;
+    private RecyclerView mBatteryConsumerDataView;
+    private View mLoadingView;
+    private View mEmptyView;
+    private ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult(
+            BatteryConsumerPickerActivity.CONTRACT, this::onApplicationSelected);
+    private BatteryStatsHelper mBatteryStatsHelper;
+    private BatteryUsageStats mBatteryUsageStats;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mSharedPref = getPreferences(Context.MODE_PRIVATE);
+
+        setContentView(R.layout.battery_stats_viewer_layout);
+
+        View appCard = findViewById(R.id.app_card);
+        appCard.setOnClickListener((e) -> startAppPicker());
+
+        mTitleView = findViewById(android.R.id.title);
+        mDetailsView = findViewById(R.id.details);
+        mIconView = findViewById(android.R.id.icon);
+        mPackagesView = findViewById(R.id.packages);
+
+        mBatteryConsumerDataView = findViewById(R.id.battery_consumer_data_view);
+        mBatteryConsumerDataView.setLayoutManager(new LinearLayoutManager(this));
+        mBatteryStatsDataAdapter = new BatteryStatsDataAdapter();
+        mBatteryConsumerDataView.setAdapter(mBatteryStatsDataAdapter);
+
+        mLoadingView = findViewById(R.id.loading_view);
+        mEmptyView = findViewById(R.id.empty_view);
+
+        mBatteryConsumerId = mSharedPref.getString(PREF_SELECTED_BATTERY_CONSUMER, null);
+        loadBatteryStats();
+        if (mBatteryConsumerId == null) {
+            startAppPicker();
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        periodicBatteryStatsRefresh();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh);
+    }
+
+    private void startAppPicker() {
+        mStartAppPicker.launch(null);
+    }
+
+    private void onApplicationSelected(String batteryConsumerId) {
+        if (batteryConsumerId == null) {
+            if (mBatteryConsumerId == null) {
+                finish();
+            }
+        } else {
+            mBatteryConsumerId = batteryConsumerId;
+            mSharedPref.edit()
+                    .putString(PREF_SELECTED_BATTERY_CONSUMER, mBatteryConsumerId)
+                    .apply();
+            mLoadingView.setVisibility(View.VISIBLE);
+            loadBatteryStats();
+        }
+    }
+
+    private void periodicBatteryStatsRefresh() {
+        loadBatteryStats();
+        getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS);
+    }
+
+    private void loadBatteryStats() {
+        LoaderManager loaderManager = LoaderManager.getInstance(this);
+        loaderManager.restartLoader(LOADER_BATTERY_STATS_HELPER, null,
+                new BatteryStatsHelperLoaderCallbacks());
+        loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null,
+                new BatteryUsageStatsLoaderCallbacks());
+    }
+
+    private static class BatteryStatsHelperLoader extends AsyncLoaderCompat<BatteryStatsHelper> {
+        private final BatteryStatsHelper mBatteryStatsHelper;
+        private final UserManager mUserManager;
+
+        BatteryStatsHelperLoader(Context context) {
+            super(context);
+            mUserManager = context.getSystemService(UserManager.class);
+            mBatteryStatsHelper = new BatteryStatsHelper(context,
+                    false /* collectBatteryBroadcast */);
+            mBatteryStatsHelper.create((Bundle) null);
+            mBatteryStatsHelper.clearStats();
+        }
+
+        @Override
+        public BatteryStatsHelper loadInBackground() {
+            mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
+                    UserHandle.myUserId());
+            return mBatteryStatsHelper;
+        }
+
+        @Override
+        protected void onDiscardResult(BatteryStatsHelper result) {
+        }
+    }
+
+    private class BatteryStatsHelperLoaderCallbacks implements LoaderCallbacks<BatteryStatsHelper> {
+        @NonNull
+        @Override
+        public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) {
+            return new BatteryStatsHelperLoader(BatteryStatsViewerActivity.this);
+        }
+
+        @Override
+        public void onLoadFinished(@NonNull Loader<BatteryStatsHelper> loader,
+                BatteryStatsHelper batteryStatsHelper) {
+            onBatteryStatsHelperLoaded(batteryStatsHelper);
+        }
+
+        @Override
+        public void onLoaderReset(@NonNull Loader<BatteryStatsHelper> loader) {
+        }
+    }
+
+    private static class BatteryUsageStatsLoader extends AsyncLoaderCompat<BatteryUsageStats> {
+        private final BatteryStatsManager mBatteryStatsManager;
+
+        BatteryUsageStatsLoader(Context context) {
+            super(context);
+            mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
+        }
+
+        @Override
+        public BatteryUsageStats loadInBackground() {
+            final BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
+                    .includeModeled()
+                    .build();
+            return mBatteryStatsManager.getBatteryUsageStats(query);
+        }
+
+        @Override
+        protected void onDiscardResult(BatteryUsageStats result) {
+        }
+    }
+
+    private class BatteryUsageStatsLoaderCallbacks implements LoaderCallbacks<BatteryUsageStats> {
+        @NonNull
+        @Override
+        public Loader<BatteryUsageStats> onCreateLoader(int id, Bundle args) {
+            return new BatteryUsageStatsLoader(BatteryStatsViewerActivity.this);
+        }
+
+        @Override
+        public void onLoadFinished(@NonNull Loader<BatteryUsageStats> loader,
+                BatteryUsageStats batteryUsageStats) {
+            onBatteryUsageStatsLoaded(batteryUsageStats);
+        }
+
+        @Override
+        public void onLoaderReset(@NonNull Loader<BatteryUsageStats> loader) {
+        }
+    }
+
+    public void onBatteryStatsHelperLoaded(BatteryStatsHelper batteryStatsHelper) {
+        mBatteryStatsHelper = batteryStatsHelper;
+        onBatteryStatsDataLoaded();
+    }
+
+    private void onBatteryUsageStatsLoaded(BatteryUsageStats batteryUsageStats) {
+        mBatteryUsageStats = batteryUsageStats;
+        onBatteryStatsDataLoaded();
+    }
+
+    public void onBatteryStatsDataLoaded() {
+        if (mBatteryStatsHelper == null || mBatteryUsageStats == null) {
+            return;
+        }
+
+        BatteryConsumerData batteryConsumerData = new BatteryConsumerData(this, mBatteryStatsHelper,
+                mBatteryUsageStats, mBatteryConsumerId);
+
+        BatteryConsumerInfoHelper.BatteryConsumerInfo
+                batteryConsumerInfo = batteryConsumerData.getBatteryConsumerInfo();
+        if (batteryConsumerInfo == null) {
+            mTitleView.setText("Battery consumer not found");
+            mPackagesView.setVisibility(View.GONE);
+        } else {
+            mTitleView.setText(batteryConsumerInfo.label);
+            if (batteryConsumerInfo.details != null) {
+                mDetailsView.setText(batteryConsumerInfo.details);
+                mDetailsView.setVisibility(View.VISIBLE);
+            } else {
+                mDetailsView.setVisibility(View.GONE);
+            }
+            mIconView.setImageDrawable(
+                    batteryConsumerInfo.iconInfo.loadIcon(getPackageManager()));
+
+            if (batteryConsumerInfo.packages != null) {
+                mPackagesView.setText(batteryConsumerInfo.packages);
+                mPackagesView.setVisibility(View.VISIBLE);
+            } else {
+                mPackagesView.setVisibility(View.GONE);
+            }
+        }
+
+        mBatteryStatsDataAdapter.setEntries(batteryConsumerData.getEntries());
+        if (batteryConsumerData.getEntries().isEmpty()) {
+            mEmptyView.setVisibility(View.VISIBLE);
+            mBatteryConsumerDataView.setVisibility(View.GONE);
+        } else {
+            mEmptyView.setVisibility(View.GONE);
+            mBatteryConsumerDataView.setVisibility(View.VISIBLE);
+        }
+
+        mLoadingView.setVisibility(View.GONE);
+    }
+
+    private static class BatteryStatsDataAdapter extends
+            RecyclerView.Adapter<BatteryStatsDataAdapter.ViewHolder> {
+        public static class ViewHolder extends RecyclerView.ViewHolder {
+            public TextView titleTextView;
+            public TextView amountTextView;
+            public TextView percentTextView;
+
+            ViewHolder(View itemView) {
+                super(itemView);
+
+                titleTextView = itemView.findViewById(R.id.title);
+                amountTextView = itemView.findViewById(R.id.amount);
+                percentTextView = itemView.findViewById(R.id.percent);
+            }
+        }
+
+        private List<BatteryConsumerData.Entry> mEntries = Collections.emptyList();
+
+        public void setEntries(List<BatteryConsumerData.Entry> entries) {
+            mEntries = entries;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getItemCount() {
+            return mEntries.size();
+        }
+
+        @NonNull
+        @Override
+        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
+            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
+            View itemView = layoutInflater.inflate(R.layout.battery_consumer_entry_layout, parent,
+                    false);
+            return new ViewHolder(itemView);
+        }
+
+        @Override
+        public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
+            BatteryConsumerData.Entry entry = mEntries.get(position);
+            switch (entry.entryType) {
+                case POWER:
+                    viewHolder.titleTextView.setText(entry.title);
+                    viewHolder.amountTextView.setText(
+                            String.format(Locale.getDefault(), "%.1f mAh", entry.value));
+                    break;
+                case DURATION:
+                    viewHolder.titleTextView.setText(entry.title);
+                    viewHolder.amountTextView.setText(
+                            String.format(Locale.getDefault(), "%,d ms", (long) entry.value));
+                    break;
+            }
+
+            double proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0;
+            viewHolder.percentTextView.setText(String.format(Locale.getDefault(), "%.1f%%",
+                    proportion));
+        }
+    }
+}
diff --git a/core/tests/batterystatstests/OWNERS b/core/tests/batterystatstests/OWNERS
new file mode 100644
index 0000000..c22f6a4
--- /dev/null
+++ b/core/tests/batterystatstests/OWNERS
@@ -0,0 +1,2 @@
+include /BATTERY_STATS_OWNERS
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/core/tests/benchmarks/src/android/net/OWNERS b/core/tests/benchmarks/src/android/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/benchmarks/src/android/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/bluetoothtests/OWNERS b/core/tests/bluetoothtests/OWNERS
new file mode 100644
index 0000000..98bb877
--- /dev/null
+++ b/core/tests/bluetoothtests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/bluetooth/OWNERS
diff --git a/core/tests/coretests/BstatsTestApp/OWNERS b/core/tests/coretests/BstatsTestApp/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/core/tests/coretests/BstatsTestApp/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/core/tests/coretests/apks/OWNERS b/core/tests/coretests/apks/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/coretests/apks/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/coretests/src/android/accessibilityservice/OWNERS b/core/tests/coretests/src/android/accessibilityservice/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/core/tests/coretests/src/android/accessibilityservice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
index 95da532..4b0ed65 100644
--- a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
@@ -90,7 +90,7 @@
         private boolean mAllow3rdPartyOnInternal = true;
 
         public MockedApplicationPackageManager() {
-            super(null, null, null);
+            super(null, null);
         }
 
         public void setForceAllowOnExternal(boolean forceAllowOnExternal) {
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/appsearch/external/app/cts/AppSearchResultCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
deleted file mode 100644
index 9c34b17..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.appsearch.AppSearchResult;
-
-import org.junit.Test;
-
-public class AppSearchResultCtsTest {
-
-    @Test
-    public void testResultEquals_identical() {
-        AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
-        AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("String");
-
-        assertThat(result1).isEqualTo(result2);
-        assertThat(result1.hashCode()).isEqualTo(result2.hashCode());
-
-        AppSearchResult<String> result3 =
-                AppSearchResult.newFailedResult(
-                        AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
-        AppSearchResult<String> result4 =
-                AppSearchResult.newFailedResult(
-                        AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
-
-        assertThat(result3).isEqualTo(result4);
-        assertThat(result3.hashCode()).isEqualTo(result4.hashCode());
-    }
-
-    @Test
-    public void testResultEquals_failure() {
-        AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
-        AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("Wrong");
-        AppSearchResult<String> resultNull = AppSearchResult.newSuccessfulResult(/*value=*/ null);
-
-        assertThat(result1).isNotEqualTo(result2);
-        assertThat(result1.hashCode()).isNotEqualTo(result2.hashCode());
-        assertThat(result1).isNotEqualTo(resultNull);
-        assertThat(result1.hashCode()).isNotEqualTo(resultNull.hashCode());
-
-        AppSearchResult<String> result3 =
-                AppSearchResult.newFailedResult(
-                        AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
-        AppSearchResult<String> result4 =
-                AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, "errorMessage");
-
-        assertThat(result3).isNotEqualTo(result4);
-        assertThat(result3.hashCode()).isNotEqualTo(result4.hashCode());
-
-        AppSearchResult<String> result5 =
-                AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, "Wrong");
-
-        assertThat(result3).isNotEqualTo(result5);
-        assertThat(result3.hashCode()).isNotEqualTo(result5.hashCode());
-
-        AppSearchResult<String> result6 =
-                AppSearchResult.newFailedResult(
-                        AppSearchResult.RESULT_INTERNAL_ERROR, /*errorMessage=*/ null);
-
-        assertThat(result3).isNotEqualTo(result6);
-        assertThat(result3.hashCode()).isNotEqualTo(result6.hashCode());
-    }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
deleted file mode 100644
index 7072a81..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.AppSearchSchema;
-import android.app.appsearch.AppSearchSchema.PropertyConfig;
-import android.app.appsearch.exceptions.IllegalSchemaException;
-
-import org.junit.Test;
-
-public class AppSearchSchemaCtsTest {
-    @Test
-    public void testInvalidEnums() {
-        PropertyConfig.Builder builder = new PropertyConfig.Builder("test");
-        expectThrows(IllegalArgumentException.class, () -> builder.setDataType(99));
-        expectThrows(IllegalArgumentException.class, () -> builder.setCardinality(99));
-    }
-
-    @Test
-    public void testMissingFields() {
-        PropertyConfig.Builder builder = new PropertyConfig.Builder("test");
-        IllegalSchemaException e = expectThrows(IllegalSchemaException.class, builder::build);
-        assertThat(e).hasMessageThat().contains("Missing field: dataType");
-
-        builder.setDataType(PropertyConfig.DATA_TYPE_DOCUMENT);
-        e = expectThrows(IllegalSchemaException.class, builder::build);
-        assertThat(e).hasMessageThat().contains("Missing field: schemaType");
-
-        builder.setSchemaType("TestType");
-        e = expectThrows(IllegalSchemaException.class, builder::build);
-        assertThat(e).hasMessageThat().contains("Missing field: cardinality");
-
-        builder.setCardinality(PropertyConfig.CARDINALITY_REPEATED);
-        builder.build();
-    }
-
-    @Test
-    public void testDuplicateProperties() {
-        AppSearchSchema.Builder builder =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build());
-        IllegalSchemaException e =
-                expectThrows(
-                        IllegalSchemaException.class,
-                        () ->
-                                builder.addProperty(
-                                        new PropertyConfig.Builder("subject")
-                                                .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                                .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                                .setIndexingType(
-                                                        PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                                .setTokenizerType(
-                                                        PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                                .build()));
-        assertThat(e).hasMessageThat().contains("Property defined more than once: subject");
-    }
-
-    @Test
-    public void testEquals_identical() {
-        AppSearchSchema schema1 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        AppSearchSchema schema2 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        assertThat(schema1).isEqualTo(schema2);
-        assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
-    }
-
-    @Test
-    public void testEquals_differentOrder() {
-        AppSearchSchema schema1 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        AppSearchSchema schema2 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .build())
-                        .build();
-        assertThat(schema1).isEqualTo(schema2);
-        assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
-    }
-
-    @Test
-    public void testEquals_failure() {
-        AppSearchSchema schema1 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        AppSearchSchema schema2 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(
-                                                PropertyConfig
-                                                        .INDEXING_TYPE_EXACT_TERMS) // Different
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        assertThat(schema1).isNotEqualTo(schema2);
-        assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
-    }
-
-    @Test
-    public void testEquals_failure_differentOrder() {
-        AppSearchSchema schema1 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .addProperty(
-                                new PropertyConfig.Builder("body")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        // Order of 'body' and 'subject' has been switched
-        AppSearchSchema schema2 =
-                new AppSearchSchema.Builder("Email")
-                        .addProperty(
-                                new PropertyConfig.Builder("body")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .addProperty(
-                                new PropertyConfig.Builder("subject")
-                                        .setDataType(PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
-                                        .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
-                                        .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
-                                        .build())
-                        .build();
-        assertThat(schema1).isNotEqualTo(schema2);
-        assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
-    }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
deleted file mode 100644
index 657d556..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.GenericDocument;
-
-import org.junit.Test;
-
-public class GenericDocumentCtsTest {
-    private static final byte[] sByteArray1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
-    private static final byte[] sByteArray2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
-    private static final GenericDocument sDocumentProperties1 =
-            new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
-                    .setCreationTimestampMillis(12345L)
-                    .build();
-    private static final GenericDocument sDocumentProperties2 =
-            new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
-                    .setCreationTimestampMillis(6789L)
-                    .build();
-
-    @Test
-    public void testDocumentEquals_identical() {
-        GenericDocument document1 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setTtlMillis(1L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-        GenericDocument document2 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setTtlMillis(1L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-        assertThat(document1).isEqualTo(document2);
-        assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
-    }
-
-    @Test
-    public void testDocumentEquals_differentOrder() {
-        GenericDocument document1 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .build();
-
-        // Create second document with same parameter but different order.
-        GenericDocument document2 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .build();
-        assertThat(document1).isEqualTo(document2);
-        assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
-    }
-
-    @Test
-    public void testDocumentEquals_failure() {
-        GenericDocument document1 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .build();
-
-        // Create second document with same order but different value.
-        GenericDocument document2 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
-                        .build();
-        assertThat(document1).isNotEqualTo(document2);
-        assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
-    }
-
-    @Test
-    public void testDocumentEquals_repeatedFieldOrder_failure() {
-        GenericDocument document1 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .build();
-
-        // Create second document with same order but different value.
-        GenericDocument document2 =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyBoolean("booleanKey1", true, true, false) // Different
-                        .build();
-        assertThat(document1).isNotEqualTo(document2);
-        assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
-    }
-
-    @Test
-    public void testDocumentGetSingleValue() {
-        GenericDocument document =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setScore(1)
-                        .setTtlMillis(1L)
-                        .setPropertyLong("longKey1", 1L)
-                        .setPropertyDouble("doubleKey1", 1.0)
-                        .setPropertyBoolean("booleanKey1", true)
-                        .setPropertyString("stringKey1", "test-value1")
-                        .setPropertyBytes("byteKey1", sByteArray1)
-                        .setPropertyDocument("documentKey1", sDocumentProperties1)
-                        .build();
-        assertThat(document.getUri()).isEqualTo("uri1");
-        assertThat(document.getTtlMillis()).isEqualTo(1L);
-        assertThat(document.getSchemaType()).isEqualTo("schemaType1");
-        assertThat(document.getCreationTimestampMillis()).isEqualTo(5);
-        assertThat(document.getScore()).isEqualTo(1);
-        assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
-        assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0);
-        assertThat(document.getPropertyBoolean("booleanKey1")).isTrue();
-        assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
-        assertThat(document.getPropertyBytes("byteKey1"))
-                .asList()
-                .containsExactly((byte) 1, (byte) 2, (byte) 3);
-        assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1);
-    }
-
-    @Test
-    public void testDocumentGetArrayValues() {
-        GenericDocument document =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-
-        assertThat(document.getUri()).isEqualTo("uri1");
-        assertThat(document.getSchemaType()).isEqualTo("schemaType1");
-        assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L);
-        assertThat(document.getPropertyDoubleArray("doubleKey1"))
-                .usingExactEquality()
-                .containsExactly(1.0, 2.0, 3.0);
-        assertThat(document.getPropertyBooleanArray("booleanKey1"))
-                .asList()
-                .containsExactly(true, false, true);
-        assertThat(document.getPropertyStringArray("stringKey1"))
-                .asList()
-                .containsExactly("test-value1", "test-value2", "test-value3");
-        assertThat(document.getPropertyBytesArray("byteKey1"))
-                .asList()
-                .containsExactly(sByteArray1, sByteArray2);
-        assertThat(document.getPropertyDocumentArray("documentKey1"))
-                .asList()
-                .containsExactly(sDocumentProperties1, sDocumentProperties2);
-    }
-
-    @Test
-    public void testDocument_toString() {
-        GenericDocument document =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setCreationTimestampMillis(5L)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString("stringKey1", "String1", "String2", "String3")
-                        .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
-                        .setPropertyDocument(
-                                "documentKey1", sDocumentProperties1, sDocumentProperties2)
-                        .build();
-        String exceptedString =
-                "{ key: 'creationTimestampMillis' value: 5 } "
-                        + "{ key: 'namespace' value:  } "
-                        + "{ key: 'properties' value: "
-                        + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } "
-                        + "{ key: 'byteKey1' value: "
-                        + "{ key: 'byteArray' value: [ '1' '2' '3' ] } "
-                        + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] }  } "
-                        + "{ key: 'documentKey1' value: [ '"
-                        + "{ key: 'creationTimestampMillis' value: 12345 } "
-                        + "{ key: 'namespace' value:  } "
-                        + "{ key: 'properties' value:  } "
-                        + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } "
-                        + "{ key: 'score' value: 0 } "
-                        + "{ key: 'ttlMillis' value: 0 } "
-                        + "{ key: 'uri' value: sDocumentProperties1 } ' '"
-                        + "{ key: 'creationTimestampMillis' value: 6789 } "
-                        + "{ key: 'namespace' value:  } "
-                        + "{ key: 'properties' value:  } "
-                        + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } "
-                        + "{ key: 'score' value: 0 } "
-                        + "{ key: 'ttlMillis' value: 0 } "
-                        + "{ key: 'uri' value: sDocumentProperties2 } ' ] } "
-                        + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } "
-                        + "{ key: 'longKey1' value: [ '1' '2' '3' ] } "
-                        + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] }  } "
-                        + "{ key: 'schemaType' value: schemaType1 } "
-                        + "{ key: 'score' value: 0 } "
-                        + "{ key: 'ttlMillis' value: 0 } "
-                        + "{ key: 'uri' value: uri1 } ";
-        assertThat(document.toString()).isEqualTo(exceptedString);
-    }
-
-    @Test
-    public void testDocumentGetValues_differentTypes() {
-        GenericDocument document =
-                new GenericDocument.Builder<>("uri1", "schemaType1")
-                        .setScore(1)
-                        .setPropertyLong("longKey1", 1L)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .build();
-
-        // Get a value for a key that doesn't exist
-        assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0);
-        assertThat(document.getPropertyDoubleArray("doubleKey1")).isNull();
-
-        // Get a value with a single element as an array and as a single value
-        assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
-        assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L);
-
-        // Get a value with multiple elements as an array and as a single value
-        assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
-        assertThat(document.getPropertyStringArray("stringKey1"))
-                .asList()
-                .containsExactly("test-value1", "test-value2", "test-value3");
-
-        // Get a value of the wrong type
-        assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0);
-        assertThat(document.getPropertyDoubleArray("longKey1")).isNull();
-    }
-
-    @Test
-    public void testDocumentInvalid() {
-        GenericDocument.Builder<?> builder = new GenericDocument.Builder<>("uri1", "schemaType1");
-        expectThrows(
-                IllegalArgumentException.class,
-                () -> builder.setPropertyBoolean("test", new boolean[] {}));
-    }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
deleted file mode 100644
index 50bca27..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.SearchSpec;
-
-import org.junit.Test;
-
-public class SearchSpecCtsTest {
-    @Test
-    public void buildSearchSpecWithoutTermMatchType() {
-        RuntimeException e =
-                expectThrows(
-                        RuntimeException.class,
-                        () -> new SearchSpec.Builder().addSchemaType("testSchemaType").build());
-        assertThat(e).hasMessageThat().contains("Missing termMatchType field");
-    }
-
-    @Test
-    public void testBuildSearchSpec() {
-        SearchSpec searchSpec =
-                new SearchSpec.Builder()
-                        .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
-                        .addNamespace("namespace1", "namespace2")
-                        .addSchemaType("schemaTypes1", "schemaTypes2")
-                        .setSnippetCount(5)
-                        .setSnippetCountPerProperty(10)
-                        .setMaxSnippetSize(15)
-                        .setResultCountPerPage(42)
-                        .setOrder(SearchSpec.ORDER_ASCENDING)
-                        .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
-                        .build();
-
-        assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
-        assertThat(searchSpec.getNamespaces())
-                .containsExactly("namespace1", "namespace2")
-                .inOrder();
-        assertThat(searchSpec.getSchemaTypes())
-                .containsExactly("schemaTypes1", "schemaTypes2")
-                .inOrder();
-        assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
-        assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
-        assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
-        assertThat(searchSpec.getResultCountPerPage()).isEqualTo(42);
-        assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
-        assertThat(searchSpec.getRankingStrategy())
-                .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
-    }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
deleted file mode 100644
index 29b5754..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts.customer;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.annotation.NonNull;
-import android.app.appsearch.GenericDocument;
-
-import org.junit.Test;
-
-/**
- * Tests that {@link GenericDocument} and {@link GenericDocument.Builder} are extendable by
- * developers.
- *
- * <p>This class is intentionally in a different package than {@link GenericDocument} to make sure
- * there are no package-private methods required for external developers to add custom types.
- */
-public class CustomerDocumentTest {
-
-    private static final byte[] BYTE_ARRAY1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
-    private static final byte[] BYTE_ARRAY2 = new byte[] {(byte) 4, (byte) 5, (byte) 6};
-    private static final GenericDocument DOCUMENT_PROPERTIES1 =
-            new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
-                    .build();
-    private static final GenericDocument DOCUMENT_PROPERTIES2 =
-            new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
-                    .build();
-
-    @Test
-    public void testBuildCustomerDocument() {
-        CustomerDocument customerDocument =
-                new CustomerDocument.Builder("uri1")
-                        .setScore(1)
-                        .setCreationTimestampMillis(0)
-                        .setPropertyLong("longKey1", 1L, 2L, 3L)
-                        .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
-                        .setPropertyBoolean("booleanKey1", true, false, true)
-                        .setPropertyString(
-                                "stringKey1", "test-value1", "test-value2", "test-value3")
-                        .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2)
-                        .setPropertyDocument(
-                                "documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2)
-                        .build();
-
-        assertThat(customerDocument.getUri()).isEqualTo("uri1");
-        assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument");
-        assertThat(customerDocument.getScore()).isEqualTo(1);
-        assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L);
-        assertThat(customerDocument.getPropertyLongArray("longKey1"))
-                .asList()
-                .containsExactly(1L, 2L, 3L);
-        assertThat(customerDocument.getPropertyDoubleArray("doubleKey1"))
-                .usingExactEquality()
-                .containsExactly(1.0, 2.0, 3.0);
-        assertThat(customerDocument.getPropertyBooleanArray("booleanKey1"))
-                .asList()
-                .containsExactly(true, false, true);
-        assertThat(customerDocument.getPropertyStringArray("stringKey1"))
-                .asList()
-                .containsExactly("test-value1", "test-value2", "test-value3");
-        assertThat(customerDocument.getPropertyBytesArray("byteKey1"))
-                .asList()
-                .containsExactly(BYTE_ARRAY1, BYTE_ARRAY2);
-        assertThat(customerDocument.getPropertyDocumentArray("documentKey1"))
-                .asList()
-                .containsExactly(DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2);
-    }
-
-    /**
-     * An example document type for test purposes, defined outside of {@link GenericDocument} (the
-     * way an external developer would define it).
-     */
-    private static class CustomerDocument extends GenericDocument {
-        private CustomerDocument(GenericDocument document) {
-            super(document);
-        }
-
-        public static class Builder extends GenericDocument.Builder<CustomerDocument.Builder> {
-            private Builder(@NonNull String uri) {
-                super(uri, "customerDocument");
-            }
-
-            @Override
-            @NonNull
-            public CustomerDocument build() {
-                return new CustomerDocument(super.build());
-            }
-        }
-    }
-}
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/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 4654f63..b2b34d6 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 
+import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -43,6 +44,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.function.Supplier;
+
 /**
  * Tests for {@link ObjectPool}.
  *
@@ -144,24 +147,22 @@
         persistableBundle.putInt("k", 4);
         IBinder assistToken = new Binder();
 
-        LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null,
-                null, null, 0, null, null, null, null, false, null, null, null);
-        LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
-                config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
-                procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, assistToken,
-                null /* fixedRotationAdjustments */);
+        Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder()
+                .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config())
+                .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer)
+                .setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
+                .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
+                .setIsForward(true).setAssistToken(assistToken).build();
+
+        LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
+        LaunchActivityItem item = itemSupplier.get();
         assertNotSame(item, emptyItem);
         assertFalse(item.equals(emptyItem));
 
         item.recycle();
         assertEquals(item, emptyItem);
 
-        LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo,
-                config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
-                procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, assistToken,
-                null /* fixedRotationAdjustments */);
+        LaunchActivityItem item2 = itemSupplier.get();
         assertSame(item, item2);
         assertFalse(item2.equals(emptyItem));
     }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index d125fe7..7e9933c 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -18,11 +18,19 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 
+import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.PersistableBundle;
 import android.util.MergedConfiguration;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
 
 import java.util.ArrayList;
@@ -81,4 +89,117 @@
 
         return referrerIntents;
     }
+
+    static class LaunchActivityItemBuilder {
+        private Intent mIntent;
+        private int mIdent;
+        private ActivityInfo mInfo;
+        private Configuration mCurConfig;
+        private Configuration mOverrideConfig;
+        private CompatibilityInfo mCompatInfo;
+        private String mReferrer;
+        private IVoiceInteractor mVoiceInteractor;
+        private int mProcState;
+        private Bundle mState;
+        private PersistableBundle mPersistentState;
+        private List<ResultInfo> mPendingResults;
+        private List<ReferrerIntent> mPendingNewIntents;
+        private boolean mIsForward;
+        private ProfilerInfo mProfilerInfo;
+        private IBinder mAssistToken;
+        private FixedRotationAdjustments mFixedRotationAdjustments;
+
+        LaunchActivityItemBuilder setIntent(Intent intent) {
+            mIntent = intent;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setIdent(int ident) {
+            mIdent = ident;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setInfo(ActivityInfo info) {
+            mInfo = info;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setCurConfig(Configuration curConfig) {
+            mCurConfig = curConfig;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setOverrideConfig(Configuration overrideConfig) {
+            mOverrideConfig = overrideConfig;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setCompatInfo(CompatibilityInfo compatInfo) {
+            mCompatInfo = compatInfo;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setReferrer(String referrer) {
+            mReferrer = referrer;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setVoiceInteractor(IVoiceInteractor voiceInteractor) {
+            mVoiceInteractor = voiceInteractor;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setProcState(int procState) {
+            mProcState = procState;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setState(Bundle state) {
+            mState = state;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setPersistentState(PersistableBundle persistentState) {
+            mPersistentState = persistentState;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setPendingResults(List<ResultInfo> pendingResults) {
+            mPendingResults = pendingResults;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setPendingNewIntents(List<ReferrerIntent> pendingNewIntents) {
+            mPendingNewIntents = pendingNewIntents;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setIsForward(boolean isForward) {
+            mIsForward = isForward;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setProfilerInfo(ProfilerInfo profilerInfo) {
+            mProfilerInfo = profilerInfo;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setAssistToken(IBinder assistToken) {
+            mAssistToken = assistToken;
+            return this;
+        }
+
+        LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) {
+            mFixedRotationAdjustments = fra;
+            return this;
+        }
+
+        LaunchActivityItem build() {
+            return LaunchActivityItem.obtain(mIntent, mIdent, mInfo,
+                    mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
+                    mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
+                    mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */,
+                    mFixedRotationAdjustments);
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 0ae789a..32f8929 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -41,6 +41,7 @@
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
 import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
+import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -263,13 +264,7 @@
         // A previous queued launch transaction runs on main thread (execute).
         final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */,
                 token /* activityToken */);
-        final LaunchActivityItem launchItem = spy(LaunchActivityItem.obtain(
-                null /* intent */, 0 /* ident */, null /* info */, null /* curConfig */,
-                null, /* overrideConfig */ null /* compatInfo */, null /* referrer */ ,
-                null /* voiceInteractor */, 0 /* procState */, null /* state */,
-                null /* persistentState */, null /* pendingResults */,
-                null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */,
-                null /* assistToken */, null /* fixedRotationAdjustments */));
+        final LaunchActivityItem launchItem = spy(new LaunchActivityItemBuilder().build());
         launchTransaction.addCallback(launchItem);
         mExecutor.execute(launchTransaction);
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 7e99298..e1c7146 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -29,6 +29,7 @@
 import android.app.IInstrumentationWatcher;
 import android.app.IUiAutomationConnection;
 import android.app.ProfilerInfo;
+import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder;
 import android.content.AutofillOptions;
 import android.content.ComponentName;
 import android.content.ContentCaptureOptions;
@@ -195,11 +196,14 @@
         FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments(
                 Surface.ROTATION_90, 1920, 1080, DisplayCutout.NO_CUTOUT);
 
-        LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
-                config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
-                procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, new Binder(),
-                fixedRotationAdjustments);
+        LaunchActivityItem item = new LaunchActivityItemBuilder()
+                .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config())
+                .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer)
+                .setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
+                .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
+                .setIsForward(true).setAssistToken(new Binder())
+                .setFixedRotationAdjustments(fixedRotationAdjustments).build();
+
         writeAndPrepareForReading(item);
 
         // Read from parcel and assert
diff --git a/core/tests/coretests/src/android/app/time/OWNERS b/core/tests/coretests/src/android/app/time/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/time/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
new file mode 100644
index 0000000..e248010
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.timedetector;
+
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.TimestampedValue;
+
+import org.junit.Test;
+
+public class GnssTimeSuggestionTest {
+
+    private static final TimestampedValue<Long> ARBITRARY_TIME =
+            new TimestampedValue<>(1111L, 2222L);
+
+    @Test
+    public void testEquals() {
+        GnssTimeSuggestion one = new GnssTimeSuggestion(ARBITRARY_TIME);
+        assertEquals(one, one);
+
+        GnssTimeSuggestion two = new GnssTimeSuggestion(ARBITRARY_TIME);
+        assertEquals(one, two);
+        assertEquals(two, one);
+
+        TimestampedValue<Long> differentTime = new TimestampedValue<>(
+                ARBITRARY_TIME.getReferenceTimeMillis() + 1,
+                ARBITRARY_TIME.getValue());
+        GnssTimeSuggestion three = new GnssTimeSuggestion(differentTime);
+        assertNotEquals(one, three);
+        assertNotEquals(three, one);
+
+        // DebugInfo must not be considered in equals().
+        one.addDebugInfo("Debug info 1");
+        two.addDebugInfo("Debug info 2");
+        assertEquals(one, two);
+    }
+
+    @Test
+    public void testParcelable() {
+        GnssTimeSuggestion suggestion = new GnssTimeSuggestion(ARBITRARY_TIME);
+        assertRoundTripParcelable(suggestion);
+
+        // DebugInfo should also be stored (but is not checked by equals()
+        suggestion.addDebugInfo("This is debug info");
+        GnssTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
+        assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/OWNERS b/core/tests/coretests/src/android/app/timedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timezone/OWNERS b/core/tests/coretests/src/android/app/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timezonedetector/OWNERS b/core/tests/coretests/src/android/app/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/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/coretests/src/android/database/OWNERS b/core/tests/coretests/src/android/database/OWNERS
new file mode 100644
index 0000000..bb9a2ca
--- /dev/null
+++ b/core/tests/coretests/src/android/database/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/database/OWNERS
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
new file mode 100644
index 0000000..b319886
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+import android.view.InputDevice;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.annotations.GuardedBy;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for {@link InputDeviceSensorManager}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:InputDeviceSensorManagerTest
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class InputDeviceSensorManagerTest {
+    private static final String TAG = "InputDeviceSensorManagerTest";
+
+    private static final int DEVICE_ID = 1000;
+
+    @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+
+    private TestLooper mTestLooper;
+    private ContextWrapper mContextSpy;
+    private InputManager mInputManager;
+    private InputDeviceSensorManager mSensorManager;
+    private IInputSensorEventListener mIInputSensorEventListener;
+    private final Object mLock = new Object();
+
+    @Mock private IInputManager mIInputManagerMock;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestLooper = new TestLooper();
+        mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+        InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
+
+        when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
+
+        when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
+
+        when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
+                createInputDeviceWithSensor(DEVICE_ID));
+
+        when(mIInputManagerMock.getSensorList(eq(DEVICE_ID))).thenReturn(new InputSensorInfo[] {
+                createInputSensorInfo(DEVICE_ID, Sensor.TYPE_ACCELEROMETER),
+                createInputSensorInfo(DEVICE_ID, Sensor.TYPE_GYROSCOPE)});
+
+        when(mIInputManagerMock.enableSensor(eq(DEVICE_ID), anyInt(), anyInt(), anyInt()))
+                .thenReturn(true);
+
+        when(mIInputManagerMock.registerSensorListener(any())).thenReturn(true);
+
+        mInputManager = mContextSpy.getSystemService(InputManager.class);
+    }
+
+    @After
+    public void tearDown() {
+        InputManager.clearInstance();
+    }
+
+    private class InputTestSensorEventListener implements SensorEventListener {
+        @GuardedBy("mLock")
+        private final BlockingQueue<SensorEvent> mEvents = new LinkedBlockingQueue<>();
+        InputTestSensorEventListener() {
+            super();
+        }
+
+        public SensorEvent waitForSensorEvent() {
+            try {
+                return mEvents.poll(5, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                fail("unexpectedly interrupted while waiting for SensorEvent");
+                return null;
+            }
+        }
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            synchronized (mLock) {
+                try {
+                    mEvents.put(event);
+                } catch (InterruptedException ex) {
+                    fail("interrupted while adding a SensorEvent to the queue");
+                }
+            }
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+    }
+
+    private InputDevice createInputDeviceWithSensor(int id) {
+        InputDevice d = new InputDevice(id, 0 /* generation */, 0 /* controllerNumber */, "name",
+                0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+                0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
+                false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
+                true /* hasSensor */);
+        assertTrue(d.hasSensor());
+        return d;
+    }
+
+    private InputSensorInfo createInputSensorInfo(int id, int type) {
+        InputSensorInfo info = new InputSensorInfo("name", "vendor", 0 /* version */,
+                0 /* handle */, type, 100.0f /*maxRange */, 0.02f /* resolution */,
+                0.8f /* power */, 1000 /* minDelay */, 0 /* fifoReservedEventCount */,
+                0 /* fifoMaxEventCount */, "" /* stringType */, "" /* requiredPermission */,
+                0 /* maxDelay */, 0 /* flags */, id);
+        return info;
+    }
+
+    private InputDevice getSensorDevice(int[] deviceIds) {
+        for (int i = 0; i < deviceIds.length; i++) {
+            InputDevice device = mInputManager.getInputDevice(deviceIds[i]);
+            if (device.hasSensor()) {
+                return device;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void getInputDeviceSensors_withExpectedType() throws Exception {
+        InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+        assertTrue(device != null);
+
+        SensorManager sensorManager = device.getSensorManager();
+        List<Sensor> accelList = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
+        verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+        assertEquals(1, accelList.size());
+        assertEquals(DEVICE_ID, accelList.get(0).getId());
+        assertEquals(Sensor.TYPE_ACCELEROMETER, accelList.get(0).getType());
+
+        List<Sensor> gyroList = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
+        verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+        assertEquals(1, gyroList.size());
+        assertEquals(DEVICE_ID, gyroList.get(0).getId());
+        assertEquals(Sensor.TYPE_GYROSCOPE, gyroList.get(0).getType());
+
+    }
+
+    @Test
+    public void getInputDeviceSensors_withUnexpectedType() throws Exception {
+        InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+
+        assertTrue(device != null);
+        SensorManager sensorManager = device.getSensorManager();
+
+        List<Sensor> gameRotationList = sensorManager.getSensorList(
+                Sensor.TYPE_GAME_ROTATION_VECTOR);
+        verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+        assertEquals(0, gameRotationList.size());
+
+        List<Sensor> gravityList = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
+        verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+        assertEquals(0, gravityList.size());
+    }
+
+    @Test
+    public void testInputDeviceSensorListener() throws Exception {
+        InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+        assertTrue(device != null);
+
+        SensorManager sensorManager = device.getSensorManager();
+        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+        assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
+
+        doAnswer(invocation -> {
+            mIInputSensorEventListener = invocation.getArgument(0);
+            assertNotNull(mIInputSensorEventListener);
+            return true;
+        }).when(mIInputManagerMock).registerSensorListener(any());
+
+        InputTestSensorEventListener listener = new InputTestSensorEventListener();
+        assertTrue(sensorManager.registerListener(listener, sensor,
+                SensorManager.SENSOR_DELAY_NORMAL));
+        verify(mIInputManagerMock).registerSensorListener(any());
+        verify(mIInputManagerMock).enableSensor(eq(DEVICE_ID), eq(sensor.getType()),
+                anyInt(), anyInt());
+
+        float[] values = new float[] {0.12f, 9.8f, 0.2f};
+        mIInputSensorEventListener.onInputSensorChanged(DEVICE_ID, Sensor.TYPE_ACCELEROMETER,
+                SensorManager.SENSOR_STATUS_ACCURACY_HIGH,  /* timestamp */ 0x1234abcd, values);
+
+        SensorEvent event = listener.waitForSensorEvent();
+        assertNotNull(event);
+        assertEquals(0x1234abcd, event.timestamp);
+        assertEquals(values.length, event.values.length);
+        for (int i = 0; i < values.length; i++) {
+            assertEquals(values[i], event.values[i], 0.001f);
+        }
+
+        sensorManager.unregisterListener(listener);
+        verify(mIInputManagerMock).disableSensor(eq(DEVICE_ID), eq(sensor.getType()));
+    }
+
+}
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 5bce227c..1a86678 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import static android.os.FileUtils.convertToModernFd;
 import static android.os.FileUtils.roundStorageSize;
 import static android.os.FileUtils.translateModeAccessToPosix;
 import static android.os.FileUtils.translateModePfdToPosix;
@@ -45,6 +46,8 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -67,6 +70,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.util.Arrays;
@@ -562,6 +566,55 @@
         assertEquals(O_RDWR, translateModeAccessToPosix(R_OK | W_OK | X_OK));
     }
 
+    @Test
+    public void testConvertToModernFd() throws Exception {
+        final String nonce = String.valueOf(System.nanoTime());
+
+        final File cameraDir = new File("/storage/emulated/0/DCIM/Camera");
+        final File nonCameraDir = new File("/storage/emulated/0/Pictures");
+        cameraDir.mkdirs();
+        nonCameraDir.mkdirs();
+
+        final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
+        final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
+        final File invalidVideoCameraDir = new File(cameraDir, ".invalidVideo-" + nonce + ".mp4");
+
+        final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
+        final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
+
+        try {
+            FileDescriptor pfdValidVideoCameraDir =
+                    ParcelFileDescriptor.open(validVideoCameraDir,
+                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+            FileDescriptor pfdValidImageCameraDir =
+                    ParcelFileDescriptor.open(validImageCameraDir,
+                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+            FileDescriptor pfdInvalidVideoCameraDir =
+                    ParcelFileDescriptor.open(invalidVideoCameraDir,
+                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+
+            FileDescriptor pfdValidVideoNonCameraDir =
+                    ParcelFileDescriptor.open(validVideoNonCameraDir,
+                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+            FileDescriptor pfdValidImageNonCameraDir =
+                    ParcelFileDescriptor.open(validImageNonCameraDir,
+                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+
+            assertNotNull(convertToModernFd(pfdValidVideoCameraDir));
+
+            assertNull(convertToModernFd(pfdValidImageCameraDir));
+            assertNull(convertToModernFd(pfdInvalidVideoCameraDir));
+            assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
+            assertNull(convertToModernFd(pfdValidImageNonCameraDir));
+        } finally {
+            validVideoCameraDir.delete();
+            validImageCameraDir.delete();
+            invalidVideoCameraDir.delete();
+            validVideoNonCameraDir.delete();
+            validImageNonCameraDir.delete();
+        }
+    }
+
     private static void assertTranslate(String string, int posix, int pfd) {
         assertEquals(posix, translateModeStringToPosix(string));
         assertEquals(string, translateModePosixToString(posix));
diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java
new file mode 100644
index 0000000..8941190
--- /dev/null
+++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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 static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@Presubmit
+@RunWith(JUnit4.class)
+public class VibratorInfoTest {
+
+    @Test
+    public void testHasAmplitudeControl() {
+        assertFalse(createInfo(/* capabilities= */ 0).hasAmplitudeControl());
+        assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS
+                | VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL).hasAmplitudeControl());
+    }
+
+    @Test
+    public void testHasCapabilities() {
+        assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)
+                .hasCapability(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS));
+        assertFalse(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)
+                .hasCapability(VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL));
+    }
+
+    @Test
+    public void testIsEffectSupported() {
+        VibratorInfo info = new VibratorInfo(/* id= */ 0, /* capabilities= */0,
+                new int[]{VibrationEffect.EFFECT_CLICK}, null);
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN,
+                createInfo(/* capabilities= */ 0).isEffectSupported(VibrationEffect.EFFECT_CLICK));
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
+                info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
+                info.isEffectSupported(VibrationEffect.EFFECT_TICK));
+    }
+
+    @Test
+    public void testIsPrimitiveSupported() {
+        VibratorInfo info = new VibratorInfo(/* id= */ 0, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
+                null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+        assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
+        assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
+
+        // Returns false when there is no compose capability.
+        info = new VibratorInfo(/* id= */ 0, /* capabilities= */ 0,
+                null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+        assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
+    }
+
+    @Test
+    public void testEquals() {
+        VibratorInfo empty = new VibratorInfo(1, 0, null, null);
+        VibratorInfo complete = new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
+                new int[]{VibrationEffect.EFFECT_CLICK},
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+
+        assertEquals(complete, complete);
+        assertEquals(complete, new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
+                new int[]{VibrationEffect.EFFECT_CLICK},
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}));
+
+        assertFalse(empty.equals(new VibratorInfo(1, 0, new int[]{}, new int[]{})));
+        assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
+                new int[]{VibrationEffect.EFFECT_CLICK},
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
+        assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
+                new int[]{}, new int[]{})));
+        assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
+                null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
+        assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL,
+                new int[]{VibrationEffect.EFFECT_CLICK}, null)));
+    }
+
+    @Test
+    public void testSerialization() {
+        VibratorInfo original = new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS,
+                new int[]{VibrationEffect.EFFECT_CLICK}, null);
+
+        Parcel parcel = Parcel.obtain();
+        original.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        VibratorInfo restored = VibratorInfo.CREATOR.createFromParcel(parcel);
+        assertEquals(original, restored);
+    }
+
+    private static VibratorInfo createInfo(long capabilities) {
+        return new VibratorInfo(/* id= */ 0, capabilities, null, null);
+    }
+}
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index c3d84ec..575a1be 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -55,6 +55,26 @@
     }
 
     @Test
+    public void areEffectsSupported_returnsArrayOfSameSize() {
+        assertEquals(0, mVibratorSpy.areEffectsSupported(new int[0]).length);
+        assertEquals(1,
+                mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}).length);
+        assertEquals(2,
+                mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK,
+                        VibrationEffect.EFFECT_TICK}).length);
+    }
+
+    @Test
+    public void arePrimitivesSupported_returnsArrayOfSameSize() {
+        assertEquals(0, mVibratorSpy.arePrimitivesSupported(new int[0]).length);
+        assertEquals(1, mVibratorSpy.arePrimitivesSupported(
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}).length);
+        assertEquals(2, mVibratorSpy.arePrimitivesSupported(
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK,
+                        VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length);
+    }
+
+    @Test
     public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() {
         VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
         AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(
diff --git a/core/tests/coretests/src/android/os/storage/OWNERS b/core/tests/coretests/src/android/os/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/core/tests/coretests/src/android/os/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java b/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
new file mode 100644
index 0000000..777bda9
--- /dev/null
+++ b/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.reflect.Field;
+
+/** Utility methods related to {@link Parcelable} objects used in several tests. */
+final class ParcelableTestSupport {
+
+    private ParcelableTestSupport() {}
+
+    /** Returns the result of parceling and unparceling the argument. */
+    @SuppressWarnings("unchecked")
+    public static <T extends Parcelable> T roundTripParcelable(T parcelable) {
+        Parcel parcel = Parcel.obtain();
+        parcel.writeTypedObject(parcelable, 0);
+        parcel.setDataPosition(0);
+
+        Parcelable.Creator<T> creator;
+        try {
+            Field creatorField = parcelable.getClass().getField("CREATOR");
+            creator = (Parcelable.Creator<T>) creatorField.get(null);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new AssertionError(e);
+        }
+        T toReturn = parcel.readTypedObject(creator);
+        parcel.recycle();
+        return toReturn;
+    }
+
+    public static <T extends Parcelable> void assertRoundTripParcelable(T instance) {
+        assertEquals(instance, roundTripParcelable(instance));
+    }
+}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
new file mode 100644
index 0000000..f805555
--- /dev/null
+++ b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.service.timezone;
+
+import static android.service.timezone.ParcelableTestSupport.assertRoundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import static java.util.Collections.singletonList;
+
+import org.junit.Test;
+
+import java.util.List;
+
+public class TimeZoneProviderSuggestionTest {
+
+    private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 9999;
+
+    private static final List<String> ARBITRARY_TIME_ZONE_IDS = singletonList("Europe/London");
+
+    @Test(expected = RuntimeException.class)
+    public void testInvalidTimeZoneIds() {
+        new TimeZoneProviderSuggestion.Builder()
+                .setTimeZoneIds(null);
+    }
+
+    @Test
+    public void testEquals() {
+        TimeZoneProviderSuggestion.Builder builder1 = new TimeZoneProviderSuggestion.Builder()
+                .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            assertEquals(one, one);
+        }
+
+        TimeZoneProviderSuggestion.Builder builder2 = new TimeZoneProviderSuggestion.Builder()
+                .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            TimeZoneProviderSuggestion two = builder2.build();
+            assertEquals(one, two);
+            assertEquals(two, one);
+        }
+
+        builder1.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            TimeZoneProviderSuggestion two = builder2.build();
+            assertNotEquals(one, two);
+            assertNotEquals(two, one);
+        }
+
+        builder2.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            TimeZoneProviderSuggestion two = builder2.build();
+            assertEquals(one, two);
+            assertEquals(two, one);
+        }
+
+        builder2.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            TimeZoneProviderSuggestion two = builder2.build();
+            assertNotEquals(one, two);
+            assertNotEquals(two, one);
+        }
+
+        builder1.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+        {
+            TimeZoneProviderSuggestion one = builder1.build();
+            TimeZoneProviderSuggestion two = builder2.build();
+            assertEquals(one, two);
+            assertEquals(two, one);
+        }
+    }
+
+    @Test
+    public void testParcelable_noTimeZoneIds() {
+        TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
+                .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+        assertRoundTripParcelable(builder.build());
+    }
+
+    @Test
+    public void testParcelable_withTimeZoneIds() {
+        TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
+                .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
+                .setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+        assertRoundTripParcelable(builder.build());
+    }
+}
diff --git a/core/tests/coretests/src/android/util/BinaryXmlTest.java b/core/tests/coretests/src/android/util/BinaryXmlTest.java
index 6fa5a23..fd625dce 100644
--- a/core/tests/coretests/src/android/util/BinaryXmlTest.java
+++ b/core/tests/coretests/src/android/util/BinaryXmlTest.java
@@ -66,7 +66,7 @@
         final TypedXmlPullParser in = Xml.newBinaryPullParser();
         final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
         in.setInput(is, StandardCharsets.UTF_8.name());
-        assertNext(in, START_TAG, "tag", 1);
+        assertNext(in, START_TAG, "tag");
         assertEquals(count, in.getAttributeCount());
     }
 
@@ -140,7 +140,12 @@
                 doVerifyWrite(xml);
                 data = os.toByteArray();
             }
-            try (InputStream is = new ByteArrayInputStream(data)) {
+            try (InputStream is = new ByteArrayInputStream(data) {
+                @Override
+                public boolean markSupported() {
+                    return false;
+                }
+            }) {
                 doVerifyRead(Xml.resolvePullParser(is));
             }
         }
@@ -152,7 +157,12 @@
                 doVerifyWrite(xml);
                 data = os.toByteArray();
             }
-            try (InputStream is = new ByteArrayInputStream(data)) {
+            try (InputStream is = new ByteArrayInputStream(data) {
+                @Override
+                public boolean markSupported() {
+                    return false;
+                }
+            }) {
                 doVerifyRead(Xml.resolvePullParser(is));
             }
         }
diff --git a/core/tests/coretests/src/android/util/XmlTest.java b/core/tests/coretests/src/android/util/XmlTest.java
index a8fc6f9..4e10ea9 100644
--- a/core/tests/coretests/src/android/util/XmlTest.java
+++ b/core/tests/coretests/src/android/util/XmlTest.java
@@ -53,6 +53,14 @@
     }
 
     @Test
+    public void testLargeValues_FastIndenting() throws Exception {
+        final TypedXmlSerializer out = Xml.newFastSerializer();
+        out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+        doLargeValues(out,
+                Xml.newFastPullParser());
+    }
+
+    @Test
     public void testLargeValues_Binary() throws Exception {
         doLargeValues(Xml.newBinarySerializer(),
                 Xml.newBinaryPullParser());
@@ -81,7 +89,7 @@
 
         final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
         in.setInput(is, StandardCharsets.UTF_8.name());
-        assertNext(in, START_TAG, "tag", 1);
+        assertNext(in, START_TAG, "tag");
         assertEquals(2, in.getAttributeCount());
         assertEquals(string, in.getAttributeValue(null, "string"));
         assertArrayEquals(bytes, in.getAttributeBytesBase64(null, "bytes"));
@@ -100,6 +108,14 @@
     }
 
     @Test
+    public void testPersistableBundle_FastIndenting() throws Exception {
+        final TypedXmlSerializer out = Xml.newFastSerializer();
+        out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+        doPersistableBundle(out,
+                Xml.newFastPullParser());
+    }
+
+    @Test
     public void testPersistableBundle_Binary() throws Exception {
         doPersistableBundle(Xml.newBinarySerializer(),
                 Xml.newBinaryPullParser());
@@ -180,6 +196,14 @@
     }
 
     @Test
+    public void testVerify_FastIndenting() throws Exception {
+        final TypedXmlSerializer out = Xml.newFastSerializer();
+        out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+        doVerify(out,
+                Xml.newFastPullParser());
+    }
+
+    @Test
     public void testVerify_Binary() throws Exception {
         doVerify(Xml.newBinarySerializer(),
                 Xml.newBinaryPullParser());
@@ -246,9 +270,12 @@
 
     static void doVerifyRead(TypedXmlPullParser in) throws Exception {
         assertEquals(START_DOCUMENT, in.getEventType());
-        assertNext(in, START_TAG, "one", 1);
+        assertDepth(in, 0);
+        assertNext(in, START_TAG, "one");
+        assertDepth(in, 1);
         {
-            assertNext(in, START_TAG, "two", 2);
+            assertNext(in, START_TAG, "two");
+            assertDepth(in, 2);
             {
                 assertEquals(14, in.getAttributeCount());
                 assertEquals(TEST_STRING,
@@ -285,27 +312,36 @@
                 assertEquals("49", in.getAttributeValue(null, "stringNumber"));
                 assertEquals(49, in.getAttributeInt(null, "stringNumber"));
             }
-            assertNext(in, END_TAG, "two", 2);
+            assertNext(in, END_TAG, "two");
+            assertDepth(in, 2);
 
-            assertNext(in, START_TAG, "three", 2);
+            assertNext(in, START_TAG, "three");
+            assertDepth(in, 2);
             {
-                assertNext(in, TEXT);
+                assertNext(in, TEXT, null);
+                assertDepth(in, 2);
                 assertEquals("foo", in.getText().trim());
-                assertNext(in, START_TAG, "four", 3);
+                assertNext(in, START_TAG, "four");
+                assertDepth(in, 3);
                 {
                     assertEquals(0, in.getAttributeCount());
                 }
-                assertNext(in, END_TAG, "four", 3);
-                assertNext(in, TEXT);
+                assertNext(in, END_TAG, "four");
+                assertDepth(in, 3);
+                assertNext(in, TEXT, null);
+                assertDepth(in, 2);
                 assertEquals("barbaz", in.getText().trim());
             }
-            assertNext(in, END_TAG, "three", 2);
+            assertNext(in, END_TAG, "three");
+            assertDepth(in, 2);
         }
-        assertNext(in, END_TAG, "one", 1);
-        assertNext(in, END_DOCUMENT);
+        assertNext(in, END_TAG, "one");
+        assertDepth(in, 1);
+        assertNext(in, END_DOCUMENT, null);
+        assertDepth(in, 0);
     }
 
-    static void assertNext(TypedXmlPullParser in, int token) throws Exception {
+    static void assertNext(TypedXmlPullParser in, int token, String name) throws Exception {
         // We're willing to skip over empty text regions, which some
         // serializers emit transparently
         int event;
@@ -313,12 +349,10 @@
         }
         assertEquals("next", token, event);
         assertEquals("getEventType", token, in.getEventType());
+        assertEquals("getName", name, in.getName());
     }
 
-    static void assertNext(TypedXmlPullParser in, int token, String name, int depth)
-            throws Exception {
-        assertNext(in, token);
-        assertEquals("getName", name, in.getName());
+    static void assertDepth(TypedXmlPullParser in, int depth) throws Exception {
         assertEquals("getDepth", depth, in.getDepth());
     }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index ab24f89..7e1e7f4 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -33,9 +33,6 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 
-import java.util.Arrays;
-import java.util.List;
-
 /**
  * Tests for AccessibilityInteractionClient
  */
@@ -65,7 +62,7 @@
         final long accessibilityNodeId = 0x4321L;
         AccessibilityNodeInfo nodeFromConnection = AccessibilityNodeInfo.obtain();
         nodeFromConnection.setSourceNodeId(accessibilityNodeId, windowId);
-        mMockConnection.mInfosToReturn = Arrays.asList(nodeFromConnection);
+        mMockConnection.mInfoToReturn = nodeFromConnection;
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         AccessibilityNodeInfo node = client.findAccessibilityNodeInfoByAccessibilityId(
                 MOCK_CONNECTION_ID, windowId, accessibilityNodeId, true, 0, null);
@@ -75,7 +72,7 @@
     }
 
     private static class MockConnection extends AccessibilityServiceConnectionImpl {
-        List<AccessibilityNodeInfo> mInfosToReturn;
+        AccessibilityNodeInfo mInfoToReturn;
 
         @Override
         public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
@@ -83,7 +80,7 @@
                 IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
                 Bundle arguments) {
             try {
-                callback.setFindAccessibilityNodeInfosResult(mInfosToReturn, interactionId);
+                callback.setFindAccessibilityNodeInfoResult(mInfoToReturn, interactionId);
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 40ecf9a..66fdfff 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,6 +16,9 @@
 
 package android.widget;
 
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -30,6 +33,7 @@
 import android.text.Layout;
 import android.text.PrecomputedText;
 import android.view.View;
+import android.view.inputmethod.EditorInfo;
 import android.widget.TextView.BufferType;
 
 import androidx.test.InstrumentationRegistry;
@@ -254,6 +258,24 @@
         assertEquals("", mTextView.getTransformed().toString());
     }
 
+    @Test
+    @UiThreadTest
+    public void testPortraitDoesntSupportFullscreenIme() {
+        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        mTextView = new NullSetTextTextView(mActivity);
+        mTextView.requestFocus();
+        assertEquals("IME_FLAG_NO_FULLSCREEN should be set",
+                mTextView.getImeOptions(),
+                mTextView.getImeOptions() & EditorInfo.IME_FLAG_NO_FULLSCREEN);
+
+        mTextView.clearFocus();
+        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mTextView = new NullSetTextTextView(mActivity);
+        mTextView.requestFocus();
+        assertEquals("IME_FLAG_NO_FULLSCREEN should not be set",
+                0, mTextView.getImeOptions() & EditorInfo.IME_FLAG_NO_FULLSCREEN);
+    }
+
     private String createLongText() {
         int size = 600 * 1000;
         final StringBuilder builder = new StringBuilder(size);
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/OWNERS b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/jank/OWNERS b/core/tests/coretests/src/com/android/internal/jank/OWNERS
new file mode 100644
index 0000000..faece08
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/OWNERS
@@ -0,0 +1 @@
+include /core/java/com/android/internal/jank/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 8f5dfc5..97c07ea 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -30,6 +30,7 @@
 
 import com.android.internal.os.BatteryStatsImpl.DualTimer;
 import com.android.internal.os.BatteryStatsImpl.Uid;
+import com.android.internal.power.MeasuredEnergyStats;
 
 import junit.framework.TestCase;
 
@@ -497,4 +498,116 @@
         t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
         assertFalse(t.isRunningLocked());
     }
+
+    @SmallTest
+    public void testUpdateDisplayEnergyLocked() {
+        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+        final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+        clocks.realtime = 0;
+        int screen = Display.STATE_OFF;
+        boolean battery = false;
+
+        final int uid1 = 10500;
+        final int uid2 = 10501;
+        long blame1 = 0;
+        long blame2 = 0;
+        long globalDoze = 0;
+
+        // Case A: uid1 off, uid2 off, battery off, screen off
+        bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+        bi.setOnBatteryInternal(battery);
+        bi.updateDisplayEnergyLocked(500_000, screen, clocks.realtime);
+        checkMeasuredEnergy("A", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case B: uid1 off, uid2 off, battery ON,  screen off
+        clocks.realtime += 17;
+        battery = true;
+        bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+        bi.setOnBatteryInternal(battery);
+        clocks.realtime += 19;
+        bi.updateDisplayEnergyLocked(510_000, screen, clocks.realtime);
+        checkMeasuredEnergy("B", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case C: uid1 ON,  uid2 off, battery on,  screen off
+        clocks.realtime += 18;
+        setFgState(uid1, true, bi);
+        clocks.realtime += 18;
+        bi.updateDisplayEnergyLocked(520_000, screen, clocks.realtime);
+        checkMeasuredEnergy("C", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case D: uid1 on,  uid2 off, battery on,  screen ON
+        clocks.realtime += 17;
+        screen = Display.STATE_ON;
+        bi.updateDisplayEnergyLocked(521_000, screen, clocks.realtime);
+        blame1 += 0; // Screen had been off during the measurement period
+        checkMeasuredEnergy("D.1", uid1, blame1, uid2, blame2, globalDoze, bi);
+        clocks.realtime += 101;
+        bi.updateDisplayEnergyLocked(530_000, screen, clocks.realtime);
+        blame1 += 530_000;
+        checkMeasuredEnergy("D.2", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case E: uid1 on,  uid2 ON,  battery on,  screen on
+        clocks.realtime += 20;
+        setFgState(uid2, true, bi);
+        clocks.realtime += 40;
+        bi.updateDisplayEnergyLocked(540_000, screen, clocks.realtime);
+        // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100
+        blame1 += 540_000 * (20 + 40) / (20 + 40 + 40);
+        blame2 += 540_000 * ( 0 + 40) / (20 + 40 + 40);
+        checkMeasuredEnergy("E", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case F: uid1 on,  uid2 OFF, battery on,  screen on
+        clocks.realtime += 40;
+        setFgState(uid2, false, bi);
+        clocks.realtime += 120;
+        bi.updateDisplayEnergyLocked(550_000, screen, clocks.realtime);
+        // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it.
+        blame1 += 550_000 * (40 + 120) / (40 + 40 + 120);
+        blame2 += 550_000 * (40 + 0  ) / (40 + 40 + 120);
+        checkMeasuredEnergy("F", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case G: uid1 on,  uid2 off,  battery on, screen DOZE
+        clocks.realtime += 5;
+        screen = Display.STATE_DOZE;
+        bi.updateDisplayEnergyLocked(570_000, screen, clocks.realtime);
+        blame1 += 570_000; // All of this pre-doze time is blamed on uid1.
+        checkMeasuredEnergy("G", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+        // Case H: uid1 on,  uid2 off,  battery on, screen ON
+        clocks.realtime += 6;
+        screen = Display.STATE_ON;
+        bi.updateDisplayEnergyLocked(580_000, screen, clocks.realtime);
+        blame1 += 0; // The screen had been doze during the energy period
+        globalDoze += 580_000;
+        checkMeasuredEnergy("H", uid1, blame1, uid2, blame2, globalDoze, bi);
+    }
+
+    private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
+        // Note that noteUidProcessStateLocked uses ActivityManager process states.
+        if (fgOn) {
+            bi.noteActivityResumedLocked(uid);
+            bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_TOP);
+        } else {
+            bi.noteActivityPausedLocked(uid);
+            bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+        }
+    }
+
+    private void checkMeasuredEnergy(String caseName, int uid1, long blame1, int uid2, long blame2,
+            long globalDoze, MockBatteryStatsImpl bi) {
+        final int bucket = MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON;
+
+        assertEquals("Wrong uid1 blame for Case " + caseName, blame1,
+                bi.getUidStatsLocked(uid1).getMeasuredEnergyMicroJoules(bucket));
+
+        assertEquals("Wrong uid2 blame for Case " + caseName, blame2,
+                bi.getUidStatsLocked(uid2).getMeasuredEnergyMicroJoules(bucket));
+
+        assertEquals("Wrong total blame for Case " + caseName, blame1 + blame2,
+                bi.getScreenOnEnergy());
+
+        assertEquals("Wrong doze for Case " + caseName, globalDoze,
+                bi.getScreenDozeEnergy());
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index bef27e2..bd41542 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -38,7 +38,9 @@
         BatteryStatsTimeBaseTest.class,
         BatteryStatsTimerTest.class,
         BatteryStatsUidTest.class,
+        BatteryUsageStatsTest.class,
         BatteryStatsUserLifecycleTests.class,
+        BluetoothPowerCalculatorTest.class,
         BstatsCpuTimesValidationTest.class,
         KernelCpuProcStringReaderTest.class,
         KernelCpuUidActiveTimeReaderTest.class,
@@ -52,7 +54,9 @@
         LongSamplingCounterTest.class,
         LongSamplingCounterArrayTest.class,
         PowerCalculatorTest.class,
-        PowerProfileTest.class
+        PowerProfileTest.class,
+
+        com.android.internal.power.MeasuredEnergyStatsTest.class
     })
 public class BatteryStatsTests {
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
new file mode 100644
index 0000000..96e9c4a
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.os.Parcel;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryUsageStatsTest {
+
+    @Test
+    public void testBuilder() {
+        BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+        validateBatteryUsageStats(batteryUsageStats);
+    }
+
+    @Test
+    public void testParcelability() {
+        final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats();
+        final Parcel outParcel = Parcel.obtain();
+        outParcel.writeParcelable(outBatteryUsageStats, 0);
+        final byte[] bytes = outParcel.marshall();
+        outParcel.recycle();
+
+        final Parcel inParcel = Parcel.obtain();
+        inParcel.unmarshall(bytes, 0, bytes.length);
+        inParcel.setDataPosition(0);
+        final BatteryUsageStats inBatteryUsageStats =
+                inParcel.readParcelable(getClass().getClassLoader());
+        assertThat(inBatteryUsageStats).isNotNull();
+        validateBatteryUsageStats(inBatteryUsageStats);
+    }
+
+    private BatteryUsageStats buildBatteryUsageStats() {
+        final MockClocks clocks = new MockClocks();
+        final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
+        final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
+
+        final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(1, 1, true);
+        builder.setConsumedPower(100);
+        builder.setDischargePercentage(20);
+
+        final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
+                builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
+        uidBatteryConsumerBuilder.setPackageWithHighestDrain("foo");
+        uidBatteryConsumerBuilder.setConsumedPower(200);
+        uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, 300);
+        uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400);
+        uidBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 500);
+        uidBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                        + BatteryConsumer.POWER_COMPONENT_CPU, 510);
+        uidBatteryConsumerBuilder.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, 600);
+        uidBatteryConsumerBuilder.setUsageDurationMillis(
+                BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, 700);
+        uidBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
+                BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 800);
+
+        final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+                builder.getOrCreateSystemBatteryConsumerBuilder(
+                        SystemBatteryConsumer.DRAIN_TYPE_CAMERA);
+        systemBatteryConsumerBuilder.setConsumedPower(10000);
+        systemBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 10100);
+        systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200);
+        systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+                BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                        + BatteryConsumer.POWER_COMPONENT_CPU, 10210);
+        systemBatteryConsumerBuilder.setUsageDurationMillis(
+                BatteryConsumer.TIME_COMPONENT_CPU, 10300);
+        systemBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
+                BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 10400);
+
+        return builder.build();
+    }
+
+    public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
+        assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(100);
+        assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20);
+
+        final List<UidBatteryConsumer> uidBatteryConsumers =
+                batteryUsageStats.getUidBatteryConsumers();
+        for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) {
+            if (uidBatteryConsumer.getUid() == 2000) {
+                assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo("foo");
+                assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(200);
+                assertThat(uidBatteryConsumer.getConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_USAGE)).isEqualTo(300);
+                assertThat(uidBatteryConsumer.getConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(400);
+                assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(500);
+                assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                                + BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(510);
+                assertThat(uidBatteryConsumer.getUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU)).isEqualTo(600);
+                assertThat(uidBatteryConsumer.getUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND)).isEqualTo(700);
+                assertThat(uidBatteryConsumer.getUsageDurationForCustomComponentMillis(
+                        BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID)).isEqualTo(800);
+            } else {
+                fail("Unexpected UID " + uidBatteryConsumer.getUid());
+            }
+        }
+
+        final List<SystemBatteryConsumer> systemBatteryConsumers =
+                batteryUsageStats.getSystemBatteryConsumers();
+        for (SystemBatteryConsumer systemBatteryConsumer : systemBatteryConsumers) {
+            if (systemBatteryConsumer.getDrainType() == SystemBatteryConsumer.DRAIN_TYPE_CAMERA) {
+                assertThat(systemBatteryConsumer.getConsumedPower()).isEqualTo(10000);
+                assertThat(systemBatteryConsumer.getConsumedPower(
+                        BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10100);
+                assertThat(systemBatteryConsumer.getConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10200);
+                assertThat(systemBatteryConsumer.getConsumedPowerForCustomComponent(
+                        BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+                                + BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10210);
+                assertThat(systemBatteryConsumer.getUsageDurationMillis(
+                        BatteryConsumer.TIME_COMPONENT_CPU)).isEqualTo(10300);
+                assertThat(systemBatteryConsumer.getUsageDurationForCustomComponentMillis(
+                        BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID)).isEqualTo(10400);
+            } else {
+                fail("Unexpected drain type " + systemBatteryConsumer.getDrainType());
+            }
+        }
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
new file mode 100644
index 0000000..96eb8da
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothPowerCalculatorTest {
+    private static final double PRECISION = 0.00001;
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+    @Mock
+    private PowerProfile mMockPowerProfile;
+    private MockBatteryStatsImpl mMockBatteryStats;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mMockBatteryStats = new MockBatteryStatsImpl(new MockClocks()) {
+            @Override
+            public boolean hasBluetoothActivityReporting() {
+                return true;
+            }
+        };
+        mMockBatteryStats.getOnBatteryTimeBase().setRunning(true, 100_000, 100_000);
+        when(mMockPowerProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE)).thenReturn(10.0);
+        when(mMockPowerProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX)).thenReturn(50.0);
+        when(mMockPowerProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX)).thenReturn(100.0);
+    }
+
+    @Test
+    public void testTimerBasedModel() {
+        setDurationsAndPower(
+                mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
+                        .getOrCreateBluetoothControllerActivityLocked(),
+                1000, 2000, 3000, 0);
+
+        setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
+                        .getOrCreateBluetoothControllerActivityLocked(),
+                4000, 5000, 6000, 0);
+
+        setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
+                        mMockBatteryStats.getBluetoothControllerActivity(),
+                6000, 8000, 10000, 0);
+
+        BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+
+        assertBluetoothPowerAndDuration(
+                getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
+                0.11388, 6000);
+        assertBluetoothPowerAndDuration(
+                getUidBatteryConsumer(batteryUsageStats, APP_UID),
+                0.24722, 15000);
+        assertBluetoothPowerAndDuration(
+                getBluetoothSystemBatteryConsumer(batteryUsageStats,
+                        SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
+                0.15833, 9000);
+    }
+
+    @Test
+    public void testReportedPowerBasedModel() {
+        setDurationsAndPower(
+                mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
+                        .getOrCreateBluetoothControllerActivityLocked(),
+                1000, 2000, 3000, 360000);
+
+        setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
+                        .getOrCreateBluetoothControllerActivityLocked(),
+                4000, 5000, 6000, 720000);
+
+        setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
+                        mMockBatteryStats.getBluetoothControllerActivity(),
+                6000, 8000, 10000, 1260000);
+
+        BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+
+        assertBluetoothPowerAndDuration(
+                getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
+                0.1, 6000);
+        assertBluetoothPowerAndDuration(
+                getUidBatteryConsumer(batteryUsageStats, APP_UID),
+                0.2, 15000);
+        assertBluetoothPowerAndDuration(
+                getBluetoothSystemBatteryConsumer(batteryUsageStats,
+                        SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
+                0.15, 9000);
+    }
+
+    private void setDurationsAndPower(
+            BatteryStatsImpl.ControllerActivityCounterImpl controllerActivity, int idleDurationMs,
+            int rxDurationMs, int txDurationMs, long powerMaMs) {
+        controllerActivity.getIdleTimeCounter().addCountLocked(idleDurationMs);
+        controllerActivity.getRxTimeCounter().addCountLocked(rxDurationMs);
+        controllerActivity.getTxTimeCounters()[0].addCountLocked(txDurationMs);
+        controllerActivity.getPowerCounter().addCountLocked(powerMaMs);
+    }
+
+    private BatteryUsageStats buildBatteryUsageStats() {
+        BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0, false);
+        builder.getOrCreateUidBatteryConsumerBuilder(
+                mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID));
+        builder.getOrCreateUidBatteryConsumerBuilder(
+                mMockBatteryStats.getUidStatsLocked(APP_UID));
+
+        BluetoothPowerCalculator bpc = new BluetoothPowerCalculator(mMockPowerProfile);
+        bpc.calculate(builder, mMockBatteryStats, 200_000, 200_000, BatteryUsageStatsQuery.DEFAULT,
+                null);
+        return builder.build();
+    }
+
+    private UidBatteryConsumer getUidBatteryConsumer(BatteryUsageStats batteryUsageStats, int uid) {
+        for (UidBatteryConsumer ubc : batteryUsageStats.getUidBatteryConsumers()) {
+            if (ubc.getUid() == uid) {
+                return ubc;
+            }
+        }
+        return null;
+    }
+
+    private SystemBatteryConsumer getBluetoothSystemBatteryConsumer(
+            BatteryUsageStats batteryUsageStats, int drainType) {
+        for (SystemBatteryConsumer sbc : batteryUsageStats.getSystemBatteryConsumers()) {
+            if (sbc.getDrainType() == drainType) {
+                return sbc;
+            }
+        }
+        return null;
+    }
+
+    private void assertBluetoothPowerAndDuration(@Nullable BatteryConsumer batteryConsumer,
+            double powerMah, int durationMs) {
+        assertThat(batteryConsumer).isNotNull();
+
+        double consumedPower = batteryConsumer.getConsumedPower(
+                BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
+        assertThat(consumedPower).isWithin(PRECISION).of(powerMah);
+
+        long usageDurationMillis = batteryConsumer.getUsageDurationMillis(
+                BatteryConsumer.TIME_COMPONENT_BLUETOOTH);
+
+        assertThat(usageDurationMillis).isEqualTo(durationMs);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index ff1d965c..c775137 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -16,17 +16,19 @@
 
 package com.android.internal.os;
 
+import android.location.GnssSignalQuality;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.SparseIntArray;
 
-import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
+import com.android.internal.power.MeasuredEnergyStats;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Queue;
 import java.util.concurrent.Future;
 
@@ -45,13 +47,18 @@
         mScreenDozeTimer = new BatteryStatsImpl.StopwatchTimer(clocks, null, -1, null,
                 mOnBatteryTimeBase);
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
+        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, 1);
         setExternalStatsSyncLocked(new DummyExternalStatsSync());
 
-        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+        for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
             mGpsSignalQualityTimer[i] = new StopwatchTimer(clocks, null, -1000 - i, null,
                     mOnBatteryTimeBase);
         }
 
+        final boolean[] supportedBuckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
+        Arrays.fill(supportedBuckets, true);
+        mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedBuckets);
+
         // A no-op handler.
         mHandler = new Handler(Looper.getMainLooper()) {
         };
diff --git a/core/tests/coretests/src/com/android/internal/os/MockClocks.java b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
index f750c37..d0fa756 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockClocks.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
@@ -17,7 +17,9 @@
 package com.android.internal.os;
 
 public class MockClocks implements BatteryStatsImpl.Clocks {
+    /** ElapsedRealtime in ms */
     public long realtime;
+    /** Uptime in ms */
     public long uptime;
 
     @Override
diff --git a/core/tests/coretests/src/com/android/internal/os/OWNERS b/core/tests/coretests/src/com/android/internal/os/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/policy/OWNERS b/core/tests/coretests/src/com/android/internal/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
index 88295ef..2ede751 100644
--- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
@@ -16,18 +16,22 @@
 
 package com.android.internal.power;
 
-import static com.android.internal.power.MeasuredEnergyArray.NUMBER_SUBSYSTEMS;
-import static com.android.internal.power.MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
+import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
+
 import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE;
 import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON;
+import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER;
 import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
 import android.view.Display;
 
-import org.junit.Before;
+import androidx.test.filters.SmallTest;
+
 import org.junit.Test;
 
 /**
@@ -36,243 +40,225 @@
  * To run the tests, use
  * atest FrameworksCoreTests:com.android.internal.power.MeasuredEnergyStatsTest
  */
+@SmallTest
 public class MeasuredEnergyStatsTest {
-    private MeasuredEnergyStats mStats;
-    private int[] mAllSubsystems = new int[NUMBER_SUBSYSTEMS];
-    private long[] mCurrentSubsystemEnergyUJ = new long[NUMBER_SUBSYSTEMS];
 
-    MeasuredEnergyArray mMeasuredEnergyArray = new MeasuredEnergyArray() {
-        @Override
-        public int getSubsystem(int index) {
-            return mAllSubsystems[index];
+    @Test
+    public void testConstruction() {
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+
+        for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+            if (supportedEnergyBuckets[i]) {
+                assertTrue(stats.isEnergyBucketSupported(i));
+                assertEquals(0L, stats.getAccumulatedBucketEnergy(i));
+            } else {
+                assertFalse(stats.isEnergyBucketSupported(i));
+                assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
+            }
         }
+    }
 
-        @Override
-        public long getEnergy(int index) {
-            return mCurrentSubsystemEnergyUJ[index];
+    @Test
+    public void testCreateFromTemplate() {
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+
+        final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
+
+        for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+            if (supportedEnergyBuckets[i]) {
+                assertTrue(newStats.isEnergyBucketSupported(i));
+                assertEquals(0, newStats.getAccumulatedBucketEnergy(i));
+            } else {
+                assertFalse(newStats.isEnergyBucketSupported(i));
+                assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+            }
         }
-
-        @Override
-        public int size() {
-            return NUMBER_SUBSYSTEMS;
-        }
-    };
-
-    @Before
-    public void setUp() {
-        // Populate all supported subsystems indexes and arbitrary starting energy values.
-        mAllSubsystems[SUBSYSTEM_DISPLAY] = SUBSYSTEM_DISPLAY;
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] = 111;
-
-        mStats = new MeasuredEnergyStats(mMeasuredEnergyArray, Display.STATE_UNKNOWN);
     }
 
     @Test
     public void testReadWriteParcel() {
-        // update with some arbitrary data
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
 
         final Parcel parcel = Parcel.obtain();
-        mStats.writeToParcel(parcel);
+        stats.writeToParcel(parcel);
 
         parcel.setDataPosition(0);
-        MeasuredEnergyStats stats = new MeasuredEnergyStats(parcel);
+        MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel);
 
         for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            assertEquals(mStats.getAccumulatedBucketEnergy(i), stats.getAccumulatedBucketEnergy(i));
+            assertEquals(stats.getAccumulatedBucketEnergy(i),
+                    newStats.getAccumulatedBucketEnergy(i));
         }
         parcel.recycle();
     }
 
     @Test
     public void testReadWriteSummaryParcel() {
-        // update with some arbitrary data
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
 
         final Parcel parcel = Parcel.obtain();
-        MeasuredEnergyStats.writeSummaryToParcel(mStats, parcel);
+        MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
 
+
+        final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false
+        MeasuredEnergyStats newStats = new MeasuredEnergyStats(newSupportedEnergyBuckets);
         parcel.setDataPosition(0);
-        MeasuredEnergyStats stats = new MeasuredEnergyStats(mMeasuredEnergyArray,
-                Display.STATE_UNKNOWN);
-        MeasuredEnergyStats.readSummaryFromParcel(stats, parcel);
+        MeasuredEnergyStats.readSummaryFromParcel(newStats, parcel);
 
         for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            assertEquals(mStats.getAccumulatedBucketEnergy(i), stats.getAccumulatedBucketEnergy(i));
+            if (!newSupportedEnergyBuckets[i]) {
+                assertFalse(newStats.isEnergyBucketSupported(i));
+                assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+            } else if (!supportedEnergyBuckets[i]) {
+                assertTrue(newStats.isEnergyBucketSupported(i));
+                assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
+            } else {
+                assertTrue(newStats.isEnergyBucketSupported(i));
+                assertEquals(stats.getAccumulatedBucketEnergy(i),
+                        newStats.getAccumulatedBucketEnergy(i));
+            }
         }
         parcel.recycle();
     }
 
     @Test
-    public void testDisplayStateEnergyAttribution() {
-        long expectedScreenOnEnergy = 0;
-        long expectedScreenDozeEnergy = 0;
+    public void testCreateAndReadSummaryFromParcel() {
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
 
-        // Display energy should be attributed to the previous screen state.
-        mStats.update(mMeasuredEnergyArray, Display.STATE_UNKNOWN, true);
+        final MeasuredEnergyStats template = new MeasuredEnergyStats(supportedEnergyBuckets);
+        template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        template.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
 
-        incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 7, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true);
 
-        expectedScreenOnEnergy += 321;
-        incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        final Parcel parcel = Parcel.obtain();
+        MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
 
-        expectedScreenDozeEnergy += 456;
-        incrementDisplayState(456, Display.STATE_OFF, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true
+        newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false
+        final MeasuredEnergyStats newTemplate = new MeasuredEnergyStats(newSupportedEnergyBuckets);
+        parcel.setDataPosition(0);
 
-        incrementDisplayState(1111, Display.STATE_DOZE_SUSPEND, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        final MeasuredEnergyStats newStats =
+                MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
 
-        expectedScreenDozeEnergy += 2345;
-        incrementDisplayState(2345, Display.STATE_ON_SUSPEND, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        expectedScreenOnEnergy += 767;
-        incrementDisplayState(767, Display.STATE_VR, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        expectedScreenOnEnergy += 999;
-        incrementDisplayState(999, Display.STATE_UNKNOWN, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+            if (!newSupportedEnergyBuckets[i]) {
+                assertFalse(newStats.isEnergyBucketSupported(i));
+                assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+            } else if (!supportedEnergyBuckets[i]) {
+                assertTrue(newStats.isEnergyBucketSupported(i));
+                assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
+            } else {
+                assertTrue(newStats.isEnergyBucketSupported(i));
+                assertEquals(stats.getAccumulatedBucketEnergy(i),
+                        newStats.getAccumulatedBucketEnergy(i));
+            }
+        }
+        parcel.recycle();
     }
 
     @Test
-    public void testDisplayStateEnergyAttribution_notRunning() {
-        long expectedScreenOnEnergy = 0;
-        long expectedScreenDozeEnergy = 0;
+    public void testUpdateBucket() {
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
 
-        // Display energy should be attributed to the previous screen state.
-        mStats.update(mMeasuredEnergyArray, Display.STATE_UNKNOWN, true);
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_DOZE, 30, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
 
-        incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        expectedScreenOnEnergy += 321;
-        incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        // Updates after this point should not result in energy accumulation.
-        incrementDisplayState(456, Display.STATE_OFF, false, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        incrementDisplayState(1111, Display.STATE_DOZE_SUSPEND, false, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        incrementDisplayState(2345, Display.STATE_ON_SUSPEND, false, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        incrementDisplayState(767, Display.STATE_VR, false, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        // Resume energy accumulation.
-        expectedScreenOnEnergy += 999;
-        incrementDisplayState(999, Display.STATE_UNKNOWN, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        assertEquals(15, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
+        assertEquals(ENERGY_DATA_UNAVAILABLE,
+                stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
+        assertEquals(40, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_OTHER));
     }
 
     @Test
     public void testReset() {
-        // update with some arbitrary data.
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
-        mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+        final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+        supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
 
-        mStats.reset();
+        final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+
+        MeasuredEnergyStats.resetIfNotNull(stats);
         // All energy should be reset to 0
         for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            assertEquals(mStats.getAccumulatedBucketEnergy(i), 0);
+            if (supportedEnergyBuckets[i]) {
+                assertTrue(stats.isEnergyBucketSupported(i));
+                assertEquals(0, stats.getAccumulatedBucketEnergy(i));
+            } else {
+                assertFalse(stats.isEnergyBucketSupported(i));
+                assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
+            }
         }
 
-        // Increment all subsystem energy by some arbitrary amount and update
-        for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
-            mCurrentSubsystemEnergyUJ[i] += 100 * i;
-        }
-        mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
-
-        // All energy should still be 0 after the first post-reset update.
-        for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
-            assertEquals(mStats.getAccumulatedBucketEnergy(i), 0);
-        }
-
-        // Energy accumulation should continue like normal.
-        long expectedScreenOnEnergy = 0;
-        long expectedScreenDozeEnergy = 0;
-        incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        expectedScreenOnEnergy += 321;
-        incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
-
-        expectedScreenDozeEnergy += 456;
-        incrementDisplayState(456, Display.STATE_OFF, true, expectedScreenOnEnergy,
-                expectedScreenDozeEnergy);
+        // Values should increase as usual.
+        stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 70, true);
+        assertEquals(70L, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
     }
 
+    /** Test that states are mapped to the expected energy buckets. Beware of mapping changes. */
     @Test
-    public void testHasSubsystem() {
-        for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
-            assertEquals(mStats.hasSubsystem(i), true);
-        }
-    }
+    public void testEnergyBucketMapping() {
+        int exp;
 
-    @Test
-    public void testHasSubsystem_unavailable() {
-        // Setup MeasuredEnergyStats with not available subsystems.
-        int[] subsystems = new int[0];
-        long[] energies = new long[0];
-        MeasuredEnergyArray measuredEnergyArray = new MeasuredEnergyArray() {
-            @Override
-            public int getSubsystem(int index) {
-                return subsystems[index];
-            }
+        exp = ENERGY_BUCKET_SCREEN_ON;
+        assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON));
+        assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_VR));
+        assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON_SUSPEND));
 
-            @Override
-            public long getEnergy(int index) {
-                return energies[index];
-            }
-
-            @Override
-            public int size() {
-                return 0;
-            }
-        };
-        MeasuredEnergyStats stats = new MeasuredEnergyStats(measuredEnergyArray,
-                Display.STATE_UNKNOWN);
-
-        for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
-            assertEquals(stats.hasSubsystem(i), false);
-        }
-
-        stats.reset();
-        // a reset should not change the state of an unavailable subsystem.
-        for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
-            assertEquals(stats.hasSubsystem(i), false);
-        }
-    }
-
-    private void incrementDisplayState(long deltaEnergy, int nextState, boolean accumulate,
-            long expectScreenEnergy, long expectedDozeEnergy) {
-        mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += deltaEnergy;
-        mStats.update(mMeasuredEnergyArray, nextState, accumulate);
-        assertEquals(expectScreenEnergy,
-                mStats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
-        assertEquals(expectedDozeEnergy,
-                mStats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
+        exp = ENERGY_BUCKET_SCREEN_DOZE;
+        assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE));
+        assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE_SUSPEND));
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/power/OWNERS b/core/tests/coretests/src/com/android/internal/power/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/power/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/OWNERS b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
index d026735..e8793a9 100644
--- a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -118,4 +118,89 @@
         assertEquals(3, ArrayUtils.unstableRemoveIf(collection, isNull));
         assertEquals(0, collection.size());
     }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_passesWhenRangeInsideArray() {
+        ArrayUtils.throwsIfOutOfBounds(10, 2, 6);
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_passesWhenRangeIsWholeArray() {
+        ArrayUtils.throwsIfOutOfBounds(10, 0, 10);
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtStart() {
+        ArrayUtils.throwsIfOutOfBounds(10, 0, 0);
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtEnd() {
+        ArrayUtils.throwsIfOutOfBounds(10, 10, 0);
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_passesWhenEmptyArray() {
+        ArrayUtils.throwsIfOutOfBounds(0, 0, 0);
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenRangeStartNegative() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(10, -1, 5);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenCountNegative() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(10, 5, -1);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenRangeStartTooHigh() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(10, 11, 0);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenRangeEndTooHigh() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(10, 5, 6);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenLengthNegative() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(-1, 0, 0);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
+
+    @SmallTest
+    public void testThrowsIfOutOfBounds_failsWhenOverflowRangeEndTooHigh() {
+        try {
+            ArrayUtils.throwsIfOutOfBounds(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+            fail();
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // expected
+        }
+    }
 }
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/core/tests/hdmitests/OWNERS b/core/tests/hdmitests/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/core/tests/hdmitests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 306388f..9531181d 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -195,6 +195,11 @@
         }
 
         @Override
+        public boolean shouldHandleTvPowerKey() {
+            return false;
+        }
+
+        @Override
         public void queryDisplayStatus(final IHdmiControlCallback callback) {
         }
 
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
index 4c0de62..4ce072c 100755
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
@@ -37,6 +37,7 @@
         int deviceType = 0;
         int vendorId = 0x123456;
         String displayName = "test device";
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
         int powerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
         int deviceId = 3;
         int adopterId = 2;
@@ -70,6 +71,16 @@
                                 vendorId,
                                 displayName,
                                 powerStatus))
+                .addEqualityGroup(
+                        new HdmiDeviceInfo(
+                                logicalAddr,
+                                phyAddr,
+                                portId,
+                                deviceType,
+                                vendorId,
+                                displayName,
+                                powerStatus,
+                                cecVersion))
                 .testEquals();
     }
 }
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java
new file mode 100755
index 0000000..d8dc1ea
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link HdmiPortInfo} */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiPortInfoTest {
+
+    @Test
+    public void testEquals() {
+        int portId = 1;
+        int portType = 0;
+        int address = 0x123456;
+        boolean isCec = true;
+        boolean isMhl = false;
+        boolean isArcSupported = false;
+
+        new EqualsTester()
+                .addEqualityGroup(
+                        new HdmiPortInfo(portId, portType, address, isCec, isMhl, isArcSupported),
+                        new HdmiPortInfo(portId, portType, address, isCec, isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(
+                                portId + 1, portType, address, isCec, isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(
+                                portId, portType + 1, address, isCec, isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(
+                                portId, portType, address + 1, isCec, isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(portId, portType, address, !isCec, isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(portId, portType, address, isCec, !isMhl, isArcSupported))
+                .addEqualityGroup(
+                        new HdmiPortInfo(portId, portType, address, isCec, isMhl, !isArcSupported))
+                .testEquals();
+    }
+}
diff --git a/core/tests/hosttests/test-apps/OWNERS b/core/tests/hosttests/test-apps/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/hosttests/test-apps/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/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/core/tests/notificationtests/OWNERS b/core/tests/notificationtests/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/core/tests/notificationtests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/core/tests/overlaytests/OWNERS b/core/tests/overlaytests/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/core/tests/overlaytests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/core/tests/packagemanagertests/OWNERS b/core/tests/packagemanagertests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/core/tests/packagemanagertests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/core/tests/powertests/PowerStatsLoadTests/Android.bp b/core/tests/powertests/PowerStatsLoadTests/Android.bp
deleted file mode 100644
index 66c91ad..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/Android.bp
+++ /dev/null
@@ -1,13 +0,0 @@
-android_test {
-    name: "PowerStatsLoadTests",
-    srcs: ["src/**/*.java"],
-    static_libs: [
-        "androidx.test.rules",
-        "androidx.test.ext.junit",
-        "compatibility-device-util-axt",
-        "junit",
-    ],
-    libs: ["android.test.runner"],
-    platform_apis: true,
-    certificate: "platform",
-}
diff --git a/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml b/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml
deleted file mode 100644
index 9cecaed..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.frameworks.core.powerstatsloadtests">
-
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-    <uses-permission android:name="android.permission.BATTERY_STATS"/>
-    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
-    <uses-permission android:name="android.permission.DEVICE_POWER"/>
-    <uses-permission android:name="android.permission.INTERNET"/>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.frameworks.core.powerstatsloadtests"
-        android:label="Power Stats Load Tests" />
-
-    <queries>
-        <!-- The load test resolves http://... intents. Let it do so. -->
-        <package android:name="com.android.chrome"/>
-    </queries>
-</manifest>
diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java
deleted file mode 100644
index ca29426..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsloadtests;
-
-import static org.junit.Assert.assertEquals;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.SystemUtil;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class ConnectivitySetupRule implements TestRule {
-
-    private final boolean mWifiEnabled;
-    private final ConnectivityManager mConnectivityManager;
-    private final WifiManager mWifiManager;
-    private boolean mInitialWifiState;
-
-    public ConnectivitySetupRule(boolean wifiEnabled) {
-        mWifiEnabled = wifiEnabled;
-
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        Context context = instrumentation.getContext();
-        mConnectivityManager = context.getSystemService(ConnectivityManager.class);
-        mWifiManager = context.getSystemService(WifiManager.class);
-    }
-
-    @Override
-    public Statement apply(Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                try {
-                    mInitialWifiState = isWiFiConnected();
-                    setWiFiState(mWifiEnabled);
-                    base.evaluate();
-                } finally {
-                    setWiFiState(mInitialWifiState);
-                }
-            }
-        };
-    }
-
-    private void setWiFiState(final boolean enable) throws InterruptedException {
-        boolean wiFiConnected = isWiFiConnected();
-        if (enable == wiFiConnected) {
-            return;
-        }
-
-        NetworkTracker tracker = new NetworkTracker(!mWifiEnabled);
-        mConnectivityManager.registerNetworkCallback(
-                new NetworkRequest.Builder()
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED).build(),
-                tracker);
-
-        if (enable) {
-            SystemUtil.runShellCommand("svc wifi enable");
-            //noinspection deprecation
-            SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
-                    android.Manifest.permission.NETWORK_SETTINGS);
-        } else {
-            SystemUtil.runShellCommand("svc wifi disable");
-        }
-
-        tracker.waitForExpectedState();
-
-        assertEquals("Wifi must be " + (enable ? "connected to" : "disconnected from")
-                + " an access point for this test.", enable, isWiFiConnected());
-
-        mConnectivityManager.unregisterNetworkCallback(tracker);
-    }
-
-    private boolean isWiFiConnected() {
-        return mWifiManager.isWifiEnabled() && mConnectivityManager.getActiveNetwork() != null
-                && !mConnectivityManager.isActiveNetworkMetered();
-    }
-
-    private class NetworkTracker extends ConnectivityManager.NetworkCallback {
-        private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
-
-        private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
-        private final boolean mExpectedMetered;
-
-        private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-            @Override
-            public void handleMessage(Message msg) {
-                if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
-                    checkActiveNetwork();
-                }
-            }
-        };
-
-        private NetworkTracker(boolean expectedMetered) {
-            mExpectedMetered = expectedMetered;
-        }
-
-        @Override
-        public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
-                LinkProperties linkProperties, boolean blocked) {
-            checkActiveNetwork();
-        }
-
-        @Override
-        public void onLost(Network network) {
-            checkActiveNetwork();
-        }
-
-        boolean waitForExpectedState() throws InterruptedException {
-            checkActiveNetwork();
-            return mReceiveLatch.await(60, TimeUnit.SECONDS);
-        }
-
-        private void checkActiveNetwork() {
-            if (mReceiveLatch.getCount() == 0) {
-                return;
-            }
-
-            if (mConnectivityManager.getActiveNetwork() != null
-                    && mConnectivityManager.isActiveNetworkMetered() == mExpectedMetered) {
-                mReceiveLatch.countDown();
-            } else {
-                mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
-            }
-        }
-    }
-}
diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java
deleted file mode 100644
index 88cb719..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsloadtests;
-
-import android.os.Process;
-
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PowerMetrics {
-    private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
-    private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
-    private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
-    private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
-            PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
-
-    enum MetricKind {
-        POWER,
-        DURATION,
-    }
-
-    public static final String METRIC_APP_POWER = "appPower";
-    public static final String METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL = "appPowerExcludeSystem";
-    public static final String METRIC_APP_POWER_EXCLUDE_SMEARED = "appPowerExcludeSmeared";
-    public static final String METRIC_SCREEN_POWER = "screenPower";
-    public static final String METRIC_WIFI_POWER = "wifiPower";
-    public static final String METRIC_SYSTEM_SERVICE_CPU_POWER = "systemService";
-    public static final String METRIC_OTHER_POWER = "otherPower";
-    public static final String METRIC_CPU_POWER = "cpuPower";
-    public static final String METRIC_RAM_POWER = "ramPower";
-    public static final String METRIC_WAKELOCK_POWER = "wakelockPower";
-    public static final String METRIC_MOBILE_RADIO_POWER = "mobileRadioPower";
-    public static final String METRIC_BLUETOOTH_POWER = "bluetoothPower";
-    public static final String METRIC_GPS_POWER = "gpsPower";
-    public static final String METRIC_CAMERA_POWER = "cameraPower";
-    public static final String METRIC_FLASHLIGHT_POWER = "flashlightPower";
-    public static final String METRIC_SENSORS_POWER = "sensorsPower";
-    public static final String METRIC_AUDIO_POWER = "audioPower";
-    public static final String METRIC_VIDEO_POWER = "videoPower";
-    public static final String METRIC_CPU_TIME = "cpuTime";
-    public static final String METRIC_CPU_FOREGROUND_TIME = "cpuForegroundTime";
-    public static final String METRIC_WAKELOCK_TIME = "wakelockTime";
-    public static final String METRIC_WIFI_RUNNING_TIME = "wifiRunningTime";
-    public static final String METRIC_BLUETOOTH_RUNNING_TIME = "bluetoothRunningTime";
-    public static final String METRIC_GPS_TIME = "gpsTime";
-    public static final String METRIC_CAMERA_TIME = "cameraTime";
-    public static final String METRIC_FLASHLIGHT_TIME = "flashlightTime";
-    public static final String METRIC_AUDIO_TIME = "audioTime";
-    public static final String METRIC_VIDEO_TIME = "videoTime";
-
-    public static class Metric {
-        public String metricType;
-        public MetricKind metricKind;
-        public String title;
-        public double value;
-        public double total;
-    }
-
-    private final double mMinDrainedPower;
-    private final double mMaxDrainedPower;
-
-    private List<Metric> mMetrics = new ArrayList<>();
-
-    public PowerMetrics(BatteryStatsHelper batteryStatsHelper, int uid) {
-        mMinDrainedPower = batteryStatsHelper.getMinDrainedPower();
-        mMaxDrainedPower = batteryStatsHelper.getMaxDrainedPower();
-
-        List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
-
-        double totalPowerMah = 0;
-        double totalSmearedPowerMah = 0;
-        double totalPowerExcludeSystemMah = 0;
-        double totalScreenPower = 0;
-        double totalProportionalSmearMah = 0;
-        double totalCpuPowerMah = 0;
-        double totalSystemServiceCpuPowerMah = 0;
-        double totalUsagePowerMah = 0;
-        double totalWakeLockPowerMah = 0;
-        double totalMobileRadioPowerMah = 0;
-        double totalWifiPowerMah = 0;
-        double totalBluetoothPowerMah = 0;
-        double totalGpsPowerMah = 0;
-        double totalCameraPowerMah = 0;
-        double totalFlashlightPowerMah = 0;
-        double totalSensorPowerMah = 0;
-        double totalAudioPowerMah = 0;
-        double totalVideoPowerMah = 0;
-
-        long totalCpuTimeMs = 0;
-        long totalCpuFgTimeMs = 0;
-        long totalWakeLockTimeMs = 0;
-        long totalWifiRunningTimeMs = 0;
-        long totalBluetoothRunningTimeMs = 0;
-        long totalGpsTimeMs = 0;
-        long totalCameraTimeMs = 0;
-        long totalFlashlightTimeMs = 0;
-        long totalAudioTimeMs = 0;
-        long totalVideoTimeMs = 0;
-
-        BatterySipper uidSipper = null;
-        for (BatterySipper sipper : usageList) {
-            if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
-                totalScreenPower = sipper.sumPower();
-            }
-
-            if (isHiddenDrainType(sipper.drainType)) {
-                continue;
-            }
-
-            if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) {
-                uidSipper = sipper;
-            }
-
-            totalPowerMah += sipper.sumPower();
-            totalSmearedPowerMah += sipper.totalSmearedPowerMah;
-            totalProportionalSmearMah += sipper.proportionalSmearMah;
-
-            if (!isSystemSipper(sipper)) {
-                totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
-            }
-
-            totalCpuPowerMah += sipper.cpuPowerMah;
-            totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
-            totalUsagePowerMah += sipper.usagePowerMah;
-            totalWakeLockPowerMah += sipper.wakeLockPowerMah;
-            totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
-            totalWifiPowerMah += sipper.wifiPowerMah;
-            totalBluetoothPowerMah += sipper.bluetoothPowerMah;
-            totalGpsPowerMah += sipper.gpsPowerMah;
-            totalCameraPowerMah += sipper.cameraPowerMah;
-            totalFlashlightPowerMah += sipper.flashlightPowerMah;
-            totalSensorPowerMah += sipper.sensorPowerMah;
-            totalAudioPowerMah += sipper.audioPowerMah;
-            totalVideoPowerMah += sipper.videoPowerMah;
-
-            totalCpuTimeMs += sipper.cpuTimeMs;
-            totalCpuFgTimeMs += sipper.cpuFgTimeMs;
-            totalWakeLockTimeMs += sipper.wakeLockTimeMs;
-            totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
-            totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
-            totalGpsTimeMs += sipper.gpsTimeMs;
-            totalCameraTimeMs += sipper.cameraTimeMs;
-            totalFlashlightTimeMs += sipper.flashlightTimeMs;
-            totalAudioTimeMs += sipper.audioTimeMs;
-            totalVideoTimeMs += sipper.videoTimeMs;
-        }
-
-        if (uidSipper == null) {
-            return;
-        }
-
-        addMetric(METRIC_APP_POWER, MetricKind.POWER, "Total power",
-                uidSipper.totalSmearedPowerMah, totalSmearedPowerMah);
-        addMetric(METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL, MetricKind.POWER,
-                "Total power excluding system",
-                uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah);
-        addMetric(METRIC_SCREEN_POWER, MetricKind.POWER, "Screen, smeared",
-                uidSipper.screenPowerMah, totalScreenPower);
-        addMetric(METRIC_OTHER_POWER, MetricKind.POWER, "Other, smeared",
-                uidSipper.proportionalSmearMah, totalProportionalSmearMah);
-        addMetric(METRIC_APP_POWER_EXCLUDE_SMEARED, MetricKind.POWER, "Excluding smeared",
-                uidSipper.totalPowerMah, totalPowerMah);
-        addMetric(METRIC_CPU_POWER, MetricKind.POWER, "CPU",
-                uidSipper.cpuPowerMah, totalCpuPowerMah);
-        addMetric(METRIC_SYSTEM_SERVICE_CPU_POWER, MetricKind.POWER, "System services",
-                uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
-        addMetric(METRIC_RAM_POWER, MetricKind.POWER, "RAM",
-                uidSipper.usagePowerMah, totalUsagePowerMah);
-        addMetric(METRIC_WAKELOCK_POWER, MetricKind.POWER, "Wake lock",
-                uidSipper.wakeLockPowerMah, totalWakeLockPowerMah);
-        addMetric(METRIC_MOBILE_RADIO_POWER, MetricKind.POWER, "Mobile radio",
-                uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah);
-        addMetric(METRIC_WIFI_POWER, MetricKind.POWER, "WiFi",
-                uidSipper.wifiPowerMah, totalWifiPowerMah);
-        addMetric(METRIC_BLUETOOTH_POWER, MetricKind.POWER, "Bluetooth",
-                uidSipper.bluetoothPowerMah, totalBluetoothPowerMah);
-        addMetric(METRIC_GPS_POWER, MetricKind.POWER, "GPS",
-                uidSipper.gpsPowerMah, totalGpsPowerMah);
-        addMetric(METRIC_CAMERA_POWER, MetricKind.POWER, "Camera",
-                uidSipper.cameraPowerMah, totalCameraPowerMah);
-        addMetric(METRIC_FLASHLIGHT_POWER, MetricKind.POWER, "Flashlight",
-                uidSipper.flashlightPowerMah, totalFlashlightPowerMah);
-        addMetric(METRIC_SENSORS_POWER, MetricKind.POWER, "Sensors",
-                uidSipper.sensorPowerMah, totalSensorPowerMah);
-        addMetric(METRIC_AUDIO_POWER, MetricKind.POWER, "Audio",
-                uidSipper.audioPowerMah, totalAudioPowerMah);
-        addMetric(METRIC_VIDEO_POWER, MetricKind.POWER, "Video",
-                uidSipper.videoPowerMah, totalVideoPowerMah);
-
-        addMetric(METRIC_CPU_TIME, MetricKind.DURATION, "CPU time",
-                uidSipper.cpuTimeMs, totalCpuTimeMs);
-        addMetric(METRIC_CPU_FOREGROUND_TIME, MetricKind.DURATION, "CPU foreground time",
-                uidSipper.cpuFgTimeMs, totalCpuFgTimeMs);
-        addMetric(METRIC_WAKELOCK_TIME, MetricKind.DURATION, "Wake lock time",
-                uidSipper.wakeLockTimeMs, totalWakeLockTimeMs);
-        addMetric(METRIC_WIFI_RUNNING_TIME, MetricKind.DURATION, "WiFi running time",
-                uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs);
-        addMetric(METRIC_BLUETOOTH_RUNNING_TIME, MetricKind.DURATION, "Bluetooth time",
-                uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
-        addMetric(METRIC_GPS_TIME, MetricKind.DURATION, "GPS time",
-                uidSipper.gpsTimeMs, totalGpsTimeMs);
-        addMetric(METRIC_CAMERA_TIME, MetricKind.DURATION, "Camera time",
-                uidSipper.cameraTimeMs, totalCameraTimeMs);
-        addMetric(METRIC_FLASHLIGHT_TIME, MetricKind.DURATION, "Flashlight time",
-                uidSipper.flashlightTimeMs, totalFlashlightTimeMs);
-        addMetric(METRIC_AUDIO_TIME, MetricKind.DURATION, "Audio time",
-                uidSipper.audioTimeMs, totalAudioTimeMs);
-        addMetric(METRIC_VIDEO_TIME, MetricKind.DURATION, "Video time",
-                uidSipper.videoTimeMs, totalVideoTimeMs);
-    }
-
-    public List<Metric> getMetrics() {
-        return mMetrics;
-    }
-
-    public double getMinDrainedPower() {
-        return mMinDrainedPower;
-    }
-
-    public double getMaxDrainedPower() {
-        return mMaxDrainedPower;
-    }
-
-    protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) {
-        return drainType == BatterySipper.DrainType.IDLE
-                || drainType == BatterySipper.DrainType.CELL
-                || drainType == BatterySipper.DrainType.SCREEN
-                || drainType == BatterySipper.DrainType.UNACCOUNTED
-                || drainType == BatterySipper.DrainType.OVERCOUNTED
-                || drainType == BatterySipper.DrainType.BLUETOOTH
-                || drainType == BatterySipper.DrainType.WIFI;
-    }
-
-    private boolean isSystemSipper(BatterySipper sipper) {
-        final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
-        if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
-            return true;
-        } else if (sipper.mPackages != null) {
-            for (final String packageName : sipper.mPackages) {
-                for (final String systemPackage : PACKAGES_SYSTEM) {
-                    if (systemPackage.equals(packageName)) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private void addMetric(String metricType, MetricKind metricKind, String title, double amount,
-            double totalAmount) {
-        Metric metric = new Metric();
-        metric.metricType = metricType;
-        metric.metricKind = metricKind;
-        metric.title = title;
-        metric.value = amount;
-        metric.total = totalAmount;
-        mMetrics.add(metric);
-    }
-}
diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java
deleted file mode 100644
index a71559b..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsloadtests;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.Instrumentation;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.SystemClock;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.TimeUtils;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.SystemUtil;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.internal.os.LoggingPrintStream;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class PowerMetricsCollector implements TestRule {
-    private final String mTag;
-    private final float mBatteryDrainThresholdPct;
-    private final int mTimeoutMillis;
-
-    private final Context mContext;
-    private final UserManager mUserManager;
-    private final int mUid;
-    private final BatteryStatsHelper mStatsHelper;
-    private final CountDownLatch mSuspendingBatteryInput = new CountDownLatch(1);
-
-    private long mStartTime;
-    private volatile float mInitialBatteryLevel;
-    private volatile float mCurrentBatteryLevel;
-    private int mIterations;
-    private PowerMetrics mInitialPowerMetrics;
-    private PowerMetrics mFinalPowerMetrics;
-    private List<PowerMetrics.Metric> mPowerMetricsDelta;
-    private Intent mBatteryStatus;
-
-    @Override
-    public Statement apply(Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                BroadcastReceiver batteryBroadcastReceiver = new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        handleBatteryStatus(intent);
-                    }
-                };
-                mBatteryStatus = mContext.registerReceiver(batteryBroadcastReceiver,
-                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-                disableCharger();
-                try {
-                    prepareBatteryLevelMonitor();
-                    mStartTime = SystemClock.uptimeMillis();
-                    base.evaluate();
-                    captureFinalPowerStatsData();
-                } finally {
-                    mContext.unregisterReceiver(batteryBroadcastReceiver);
-                    enableCharger();
-                }
-            }
-        };
-    }
-
-    public PowerMetricsCollector(String tag, float batteryDrainThresholdPct, int timeoutMillis) {
-        mTag = tag;
-        mBatteryDrainThresholdPct = batteryDrainThresholdPct;
-        mTimeoutMillis = timeoutMillis;
-
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        mContext = instrumentation.getContext();
-        mUid = Process.myUid();
-        mUserManager = mContext.getSystemService(UserManager.class);
-        mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */);
-        mStatsHelper.create((Bundle) null);
-    }
-
-    private void disableCharger() throws InterruptedException {
-        SystemUtil.runShellCommand("dumpsys battery suspend_input");
-        final boolean success = mSuspendingBatteryInput.await(10, TimeUnit.SECONDS);
-        assertTrue("Timed out waiting for battery input to be suspended", success);
-    }
-
-    private void enableCharger() {
-        SystemUtil.runShellCommand("dumpsys battery reset");
-    }
-
-    private PowerMetrics readBatteryStatsData() {
-        mStatsHelper.clearStats();
-        mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
-                mUserManager.getUserProfiles());
-        return new PowerMetrics(mStatsHelper, mUid);
-    }
-
-    protected void prepareBatteryLevelMonitor() {
-        handleBatteryStatus(mBatteryStatus);
-        mInitialBatteryLevel = mCurrentBatteryLevel;
-    }
-
-    protected void handleBatteryStatus(Intent intent) {
-        if (mFinalPowerMetrics != null) {
-            return;
-        }
-
-        final boolean isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
-
-        if (mSuspendingBatteryInput.getCount() > 0) {
-            if (!isCharging) {
-                mSuspendingBatteryInput.countDown();
-            }
-            return;
-        }
-
-        if (isCharging) {
-            fail("Device must remain disconnected from the power source "
-                    + "for the duration of the test");
-        }
-
-        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
-        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
-
-        mCurrentBatteryLevel = level * 100 / (float) scale;
-        Log.i(mTag, "Battery level = " + mCurrentBatteryLevel);
-
-        // We delay tracking until the battery level drops.  If the resolution of
-        // battery level is 1%, and the initially reported level is 73, we don't know whether
-        // it's 73.1 or 73.7. Once it drops to 72, we can be confident that the real battery
-        // level it is very close to 72.0 and can start tracking.
-        if (mInitialPowerMetrics == null && mCurrentBatteryLevel < mInitialBatteryLevel) {
-            mInitialBatteryLevel = mCurrentBatteryLevel;
-            mInitialPowerMetrics = readBatteryStatsData();
-        }
-    }
-
-    private void captureFinalPowerStatsData() {
-        if (mFinalPowerMetrics != null) {
-            return;
-        }
-
-        mFinalPowerMetrics = readBatteryStatsData();
-
-        mPowerMetricsDelta = new ArrayList<>();
-        List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
-        List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
-        for (PowerMetrics.Metric initialMetric : initialPowerMetrics) {
-            PowerMetrics.Metric finalMetric = null;
-            for (PowerMetrics.Metric metric : finalPowerMetrics) {
-                if (metric.title.equals(initialMetric.title)) {
-                    finalMetric = metric;
-                    break;
-                }
-            }
-
-            if (finalMetric != null) {
-                PowerMetrics.Metric delta = new PowerMetrics.Metric();
-                delta.metricType = initialMetric.metricType;
-                delta.metricKind = initialMetric.metricKind;
-                delta.title = initialMetric.title;
-                delta.total = finalMetric.total - initialMetric.total;
-                delta.value = finalMetric.value - initialMetric.value;
-                mPowerMetricsDelta.add(delta);
-            }
-        }
-    }
-
-    /**
-     * Returns false if sufficient data has been accumulated.
-     */
-    public boolean checkpoint() {
-        long elapsedTime = SystemClock.uptimeMillis() - mStartTime;
-        if (elapsedTime >= mTimeoutMillis) {
-            Log.i(mTag, "Timeout reached " + TimeUtils.formatDuration(elapsedTime));
-            captureFinalPowerStatsData();
-            return false;
-        }
-
-        if (mInitialPowerMetrics == null) {
-            return true;
-        }
-
-        if (mInitialBatteryLevel - mCurrentBatteryLevel >= mBatteryDrainThresholdPct) {
-            Log.i(mTag,
-                    "Battery drain reached " + (mInitialBatteryLevel - mCurrentBatteryLevel) + "%");
-            captureFinalPowerStatsData();
-            return false;
-        }
-
-        mIterations++;
-        return true;
-    }
-
-
-    public int getIterationCount() {
-        return mIterations;
-    }
-
-    public void dumpMetrics() {
-        dumpMetrics(new LoggingPrintStream() {
-            @Override
-            protected void log(String line) {
-                Log.i(mTag, line);
-            }
-        });
-    }
-
-    public void dumpMetrics(PrintStream out) {
-        List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
-        List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
-
-        out.println("== Power metrics at test start");
-        dumpPowerStatsData(out, initialPowerMetrics);
-
-        out.println("== Power metrics at test end");
-        dumpPowerStatsData(out, finalPowerMetrics);
-
-        out.println("== Power metrics delta");
-        dumpPowerStatsData(out, mPowerMetricsDelta);
-    }
-
-    protected void dumpPowerStatsData(PrintStream out, List<PowerMetrics.Metric> metrics) {
-        Locale locale = Locale.getDefault();
-        for (PowerMetrics.Metric metric : metrics) {
-            double proportion = metric.total != 0 ? metric.value * 100 / metric.total : 0;
-            switch (metric.metricKind) {
-                case POWER:
-                    out.println(
-                            String.format(locale, "    %-30s %7.1f mAh %4.1f%%", metric.title,
-                                    metric.value, proportion));
-                    break;
-                case DURATION:
-                    out.println(
-                            String.format(locale, "    %-30s %,7d ms  %4.1f%%", metric.title,
-                                    (long) metric.value, proportion));
-                    break;
-            }
-        }
-    }
-
-    public void dumpMetricAsPercentageOfDrainedPower(String metricType) {
-        double minDrainedPower =
-                mFinalPowerMetrics.getMinDrainedPower() - mInitialPowerMetrics.getMinDrainedPower();
-        double maxDrainedPower =
-                mFinalPowerMetrics.getMaxDrainedPower() - mInitialPowerMetrics.getMaxDrainedPower();
-
-        PowerMetrics.Metric metric = getMetric(metricType);
-        double metricDelta = metric.value;
-
-        if (maxDrainedPower - minDrainedPower < 0.1f) {
-            Log.i(mTag, String.format(Locale.getDefault(),
-                    "%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
-                    metric.title, metricDelta, maxDrainedPower,
-                    metricDelta / maxDrainedPower * 100));
-        } else {
-            Log.i(mTag, String.format(Locale.getDefault(),
-                    "%s power consumed by the test: %.1f of %.1f - %.1f mAh (%.1f%% - %.1f%%)",
-                    metric.title, metricDelta, minDrainedPower, maxDrainedPower,
-                    metricDelta / minDrainedPower * 100, metricDelta / maxDrainedPower * 100));
-        }
-    }
-
-    public PowerMetrics.Metric getMetric(String metricType) {
-        for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
-            if (metric.metricType.equals(metricType)) {
-                return metric;
-            }
-        }
-        return null;
-    }
-}
diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java
deleted file mode 100644
index 911ccba..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsloadtests;
-
-import static org.junit.Assert.assertNotNull;
-
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.util.Log;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class SystemServiceCallLoadTest {
-    private static final String TAG = "SystemServiceCallLoadTest";
-    private static final int TIMEOUT_MILLIS = 60 * 60 * 1000;
-    private static final float BATTERY_DRAIN_THRESHOLD_PCT = 2.99f;
-
-    @Rule
-    public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG,
-            BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS);
-
-    private PackageManager mPackageManager;
-
-    @Before
-    public void setup() {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        mPackageManager = instrumentation.getContext().getPackageManager();
-    }
-
-    @Test
-    public void test() {
-        while (mPowerMetricsCollector.checkpoint()) {
-            Intent intent = new Intent(Intent.ACTION_VIEW);
-            intent.setDataAndType(Uri.parse("http://example.com/"), "text/plain");
-            intent.addCategory(Intent.CATEGORY_BROWSABLE);
-            ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
-            assertNotNull(resolveInfo);
-        }
-
-        mPowerMetricsCollector.dumpMetrics();
-
-        Log.i(TAG, "==");
-        Log.i(TAG, "Total system server calls made " + mPowerMetricsCollector.getIterationCount());
-
-        mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
-                PowerMetrics.METRIC_SYSTEM_SERVICE_CPU_POWER);
-    }
-}
diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java
deleted file mode 100644
index 90627192..0000000
--- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsloadtests;
-
-import android.util.Log;
-
-import org.junit.Rule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-public class WiFiLoadTest {
-    private static final String TAG = "WiFiLoadTest";
-    private static final String DOWNLOAD_TEST_URL =
-            "https://i.ytimg.com/vi/l5mE3Tpjejs/maxresdefault.jpg";
-
-    private static final int TIMEOUT_MILLIS = 60 * 60 * 1000;
-    private static final float BATTERY_DRAIN_THRESHOLD_PCT = 0.99f;
-
-    @Rule
-    public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG,
-            BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS);
-
-    @Rule
-    public ConnectivitySetupRule mConnectivitySetupRule =
-            new ConnectivitySetupRule(/* WiFi enabled */true);
-
-    @Test
-    public void test() throws IOException {
-        long totalBytesRead = 0;
-        URL url = new URL(DOWNLOAD_TEST_URL);
-        byte[] buffer = new byte[131072];  // Large buffer to minimize CPU usage
-
-        while (mPowerMetricsCollector.checkpoint()) {
-            try (InputStream inputStream = url.openStream()) {
-                while (true) {
-                    int count = inputStream.read(buffer);
-                    if (count < 0) {
-                        break;
-                    }
-                    totalBytesRead += count;
-                }
-            }
-        }
-
-        mPowerMetricsCollector.dumpMetrics();
-
-        Log.i(TAG, "==");
-        Log.i(TAG, "WiFi running time: " + (long) mPowerMetricsCollector.getMetric(
-                PowerMetrics.METRIC_WIFI_RUNNING_TIME).value);
-        Log.i(TAG, "Total bytes read over WiFi: " + totalBytesRead);
-
-        mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
-                PowerMetrics.METRIC_WIFI_POWER);
-    }
-}
diff --git a/core/tests/powertests/PowerStatsViewer/Android.bp b/core/tests/powertests/PowerStatsViewer/Android.bp
deleted file mode 100644
index a3dc4fb..0000000
--- a/core/tests/powertests/PowerStatsViewer/Android.bp
+++ /dev/null
@@ -1,13 +0,0 @@
-android_test {
-    name: "PowerStatsViewer",
-    srcs: ["src/**/*.java"],
-    defaults: ["SettingsLibDefaults"],
-    static_libs: [
-        "androidx.appcompat_appcompat",
-        "androidx.cardview_cardview",
-        "androidx.recyclerview_recyclerview",
-        "com.google.android.material_material",
-    ],
-    platform_apis: true,
-    certificate: "platform",
-}
diff --git a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml b/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml
deleted file mode 100644
index 28ea05f..0000000
--- a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.frameworks.core.powerstatsviewer"
-          android:sharedUserId="android.uid.system">
-
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-    <uses-permission android:name="android.permission.BATTERY_STATS"/>
-
-    <application
-        android:theme="@style/Theme"
-        android:label="Power Stats Viewer">
-        <activity android:name=".PowerStatsViewerActivity"
-                  android:label="Power Stats Viewer"
-                  android:launchMode="singleTop"
-                  android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
-            </intent-filter>
-        </activity>
-
-        <activity android:name=".PowerConsumerPickerActivity"
-                  android:label="Select a power consumer"/>
-    </application>
-</manifest>
diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml b/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml
deleted file mode 100644
index 238e238..0000000
--- a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <androidx.cardview.widget.CardView
-            style="@style/LoadTestCardView"
-            android:id="@+id/app_card"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginEnd="10dp"
-            android:layout_marginBottom="10dp"
-            android:layout_marginStart="10dp"
-            android:padding="20dp">
-
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:minHeight="80dp"
-                android:paddingStart="10dp"
-                android:paddingEnd="10dp">
-
-                <include layout="@layout/power_consumer_info_layout"/>
-
-            </LinearLayout>
-        </androidx.cardview.widget.CardView>
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/power_stats_data_view"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1"/>
-
-        <TextView
-            android:id="@+id/empty_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center"
-            android:visibility="gone"
-            android:text="No power stats available"/>
-    </LinearLayout>
-
-    <FrameLayout
-        android:id="@+id/loading_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="#AAFFFFFF">
-        <ProgressBar
-            style="?android:attr/progressBarStyleLarge"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:indeterminate="true"/>
-    </FrameLayout>
-</FrameLayout>
diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java
deleted file mode 100644
index 6fec240..0000000
--- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsviewer;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Process;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.os.BatterySipper;
-
-import java.util.Locale;
-
-class PowerConsumerInfoHelper {
-
-    private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
-
-    public static class PowerConsumerInfo {
-        public String id;
-        public CharSequence label;
-        public double powerMah;
-        public ApplicationInfo iconInfo;
-        public CharSequence packages;
-        public CharSequence details;
-    }
-
-    @NonNull
-    public static PowerConsumerInfo makePowerConsumerInfo(PackageManager packageManager,
-            @NonNull BatterySipper sipper) {
-        PowerConsumerInfo info = new PowerConsumerInfo();
-        info.id = PowerStatsData.powerConsumerId(sipper);
-        sipper.sumPower();
-        info.powerMah = sipper.totalSmearedPowerMah;
-        switch (sipper.drainType) {
-            case APP: {
-                int uid = sipper.getUid();
-                info.details = String.format("UID: %d", uid);
-                String packageWithHighestDrain = sipper.packageWithHighestDrain;
-                if (uid == Process.ROOT_UID) {
-                    info.label = "<root>";
-                } else {
-                    String[] packages = packageManager.getPackagesForUid(uid);
-                    String primaryPackageName = null;
-                    if (uid == Process.SYSTEM_UID) {
-                        primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME;
-                    } else if (packages != null) {
-                        for (String name : packages) {
-                            primaryPackageName = name;
-                            if (name.equals(packageWithHighestDrain)) {
-                                break;
-                            }
-                        }
-                    }
-
-                    if (primaryPackageName != null) {
-                        try {
-                            ApplicationInfo applicationInfo =
-                                    packageManager.getApplicationInfo(primaryPackageName, 0);
-                            info.label = applicationInfo.loadLabel(packageManager);
-                            info.iconInfo = applicationInfo;
-                        } catch (PackageManager.NameNotFoundException e) {
-                            info.label = primaryPackageName;
-                        }
-                    } else if (packageWithHighestDrain != null) {
-                        info.label = packageWithHighestDrain;
-                    }
-
-                    if (packages != null && packages.length > 0) {
-                        StringBuilder sb = new StringBuilder();
-                        if (primaryPackageName != null) {
-                            sb.append(primaryPackageName);
-                        }
-                        for (String packageName : packages) {
-                            if (packageName.equals(primaryPackageName)) {
-                                continue;
-                            }
-
-                            if (sb.length() != 0) {
-                                sb.append(", ");
-                            }
-                            sb.append(packageName);
-                        }
-
-                        info.packages = sb;
-                    }
-                }
-                break;
-            }
-            case USER:
-                info.label = "User";
-                info.details = String.format(Locale.getDefault(), "User ID: %d", sipper.userId);
-                break;
-            case AMBIENT_DISPLAY:
-                info.label = "Ambient display";
-                break;
-            case BLUETOOTH:
-                info.label = "Bluetooth";
-                break;
-            case CAMERA:
-                info.label = "Camera";
-                break;
-            case CELL:
-                info.label = "Cell";
-                break;
-            case FLASHLIGHT:
-                info.label = "Flashlight";
-                break;
-            case IDLE:
-                info.label = "Idle";
-                break;
-            case MEMORY:
-                info.label = "Memory";
-                break;
-            case OVERCOUNTED:
-                info.label = "Overcounted";
-                break;
-            case PHONE:
-                info.label = "Phone";
-                break;
-            case SCREEN:
-                info.label = "Screen";
-                break;
-            case UNACCOUNTED:
-                info.label = "Unaccounted";
-                break;
-            case WIFI:
-                info.label = "WiFi";
-                break;
-        }
-        // Default the app icon to System Server. This includes root, dex2oat and other UIDs.
-        if (info.iconInfo == null) {
-            try {
-                info.iconInfo =
-                        packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0);
-            } catch (PackageManager.NameNotFoundException nameNotFoundException) {
-                // Won't happen
-            }
-        }
-        return info;
-    }
-}
diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java
deleted file mode 100644
index f56d113..0000000
--- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsviewer;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-
-import androidx.activity.result.contract.ActivityResultContract;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentStatePagerAdapter;
-import androidx.viewpager.widget.ViewPager;
-
-import com.google.android.material.tabs.TabLayout;
-
-/**
- * Picker, showing a sorted lists of applications and other types of entities consuming power.
- * Returns the selected entity ID or null.
- */
-public class PowerConsumerPickerActivity extends FragmentActivity {
-
-    public static final ActivityResultContract<Void, String> CONTRACT =
-            new ActivityResultContract<Void, String>() {
-                @NonNull
-                @Override
-                public Intent createIntent(@NonNull Context context, Void aVoid) {
-                    return new Intent(context, PowerConsumerPickerActivity.class);
-                }
-
-                @Override
-                public String parseResult(int resultCode, @Nullable Intent intent) {
-                    if (resultCode != RESULT_OK || intent == null) {
-                        return null;
-                    }
-                    return intent.getStringExtra(Intent.EXTRA_RETURN_RESULT);
-                }
-            };
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        getActionBar().setDisplayHomeAsUpEnabled(true);
-
-        setContentView(R.layout.power_consumer_picker_activity_layout);
-
-        ViewPager viewPager = findViewById(R.id.pager);
-
-        FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter(
-                getSupportFragmentManager()) {
-
-            @Override
-            public int getCount() {
-                return 2;
-            }
-
-            @NonNull
-            @Override
-            public Fragment getItem(int position) {
-                switch (position) {
-                    case 0:
-                        return new PowerConsumerPickerFragment(
-                                PowerConsumerPickerFragment.PICKER_TYPE_APP);
-                    case 1:
-                    default:
-                        return new PowerConsumerPickerFragment(
-                                PowerConsumerPickerFragment.PICKER_TYPE_DRAIN);
-                }
-            }
-
-            @Override
-            public CharSequence getPageTitle(int position) {
-                switch (position) {
-                    case 0:
-                        return "Apps";
-                    case 1:
-                        return "Drains";
-                }
-                return null;
-            }
-        };
-
-        viewPager.setAdapter(adapter);
-        TabLayout tabLayout = findViewById(R.id.tab_layout);
-        tabLayout.setupWithViewPager(viewPager);
-    }
-
-    public void setSelectedPowerConsumer(String id) {
-        Intent intent = new Intent();
-        intent.putExtra(Intent.EXTRA_RETURN_RESULT, id);
-        setResult(RESULT_OK, intent);
-        finish();
-    }
-
-    @Override
-    public boolean onNavigateUp() {
-        onBackPressed();
-        return true;
-    }
-}
diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java
deleted file mode 100644
index 25225b8..0000000
--- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.frameworks.core.powerstatsviewer;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.BatteryStats;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.frameworks.core.powerstatsviewer.PowerConsumerInfoHelper.PowerConsumerInfo;
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.settingslib.utils.AsyncLoaderCompat;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Picker, showing a sorted lists of applications or other types of entities consuming power.
- * Returns the selected entity ID or null.
- */
-public class PowerConsumerPickerFragment extends Fragment {
-    private static final String TAG = "AppPicker";
-
-    public static final String PICKER_TYPE = "pickertype";
-
-    public static final int PICKER_TYPE_APP = 0;
-    public static final int PICKER_TYPE_DRAIN = 1;
-
-    private PowerConsumerListAdapter mPowerConsumerListAdapter;
-    private RecyclerView mAppList;
-    private View mLoadingView;
-
-    private interface OnPowerConsumerSelectedListener {
-        void onPowerConsumerSelected(String uid);
-    }
-
-    public PowerConsumerPickerFragment(int pickerType) {
-        Bundle args = new Bundle();
-        args.putInt(PICKER_TYPE, pickerType);
-        setArguments(args);
-    }
-
-    public PowerConsumerPickerFragment() {
-    }
-
-    @Nullable
-    @Override
-    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.power_consumer_picker_layout, container, false);
-        mLoadingView = view.findViewById(R.id.loading_view);
-
-        mAppList = view.findViewById(R.id.list_view);
-        mAppList.setLayoutManager(new LinearLayoutManager(getContext()));
-        mPowerConsumerListAdapter = new PowerConsumerListAdapter(
-                PowerConsumerPickerFragment.this::setSelectedPowerConsumer);
-        mAppList.setAdapter(mPowerConsumerListAdapter);
-
-        LoaderManager.getInstance(this).initLoader(0, getArguments(),
-                new PowerConsumerListLoaderCallbacks());
-        return view;
-    }
-
-    public void setSelectedPowerConsumer(String id) {
-        ((PowerConsumerPickerActivity) getActivity()).setSelectedPowerConsumer(id);
-    }
-
-    private static class PowerConsumerListLoader extends
-            AsyncLoaderCompat<List<PowerConsumerInfo>> {
-        private final BatteryStatsHelper mStatsHelper;
-        private final int mPickerType;
-        private final UserManager mUserManager;
-        private final PackageManager mPackageManager;
-
-        PowerConsumerListLoader(Context context, int pickerType) {
-            super(context);
-            mUserManager = context.getSystemService(UserManager.class);
-            mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */);
-            mPickerType = pickerType;
-            mStatsHelper.create((Bundle) null);
-            mStatsHelper.clearStats();
-            mPackageManager = context.getPackageManager();
-        }
-
-        @Override
-        public List<PowerConsumerInfo> loadInBackground() {
-            List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList = new ArrayList<>();
-
-            mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
-
-            final List<BatterySipper> usageList = mStatsHelper.getUsageList();
-            for (BatterySipper sipper : usageList) {
-                switch (mPickerType) {
-                    case PICKER_TYPE_APP:
-                        if (sipper.drainType != BatterySipper.DrainType.APP) {
-                            continue;
-                        }
-                        break;
-                    case PICKER_TYPE_DRAIN:
-                    default:
-                        if (sipper.drainType == BatterySipper.DrainType.APP) {
-                            continue;
-                        }
-                }
-
-                powerConsumerList.add(
-                        PowerConsumerInfoHelper.makePowerConsumerInfo(mPackageManager, sipper));
-            }
-
-            powerConsumerList.sort(
-                    Comparator.comparing((PowerConsumerInfo a) -> a.powerMah).reversed());
-            return powerConsumerList;
-        }
-
-        @Override
-        protected void onDiscardResult(List<PowerConsumerInfo> result) {
-        }
-    }
-
-    private class PowerConsumerListLoaderCallbacks implements
-            LoaderManager.LoaderCallbacks<List<PowerConsumerInfo>> {
-
-        @NonNull
-        @Override
-        public Loader<List<PowerConsumerInfo>> onCreateLoader(int id, Bundle args) {
-            return new PowerConsumerListLoader(getContext(), args.getInt(PICKER_TYPE));
-        }
-
-        @Override
-        public void onLoadFinished(@NonNull Loader<List<PowerConsumerInfo>> loader,
-                List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList) {
-            mPowerConsumerListAdapter.setPowerConsumerList(powerConsumerList);
-            mAppList.setVisibility(View.VISIBLE);
-            mLoadingView.setVisibility(View.GONE);
-        }
-
-        @Override
-        public void onLoaderReset(
-                @NonNull Loader<List<PowerConsumerInfoHelper.PowerConsumerInfo>> loader) {
-        }
-    }
-
-    public class PowerConsumerListAdapter extends RecyclerView.Adapter<PowerConsumerViewHolder> {
-        private final OnPowerConsumerSelectedListener mListener;
-        private List<PowerConsumerInfo> mPowerConsumerList;
-
-        public PowerConsumerListAdapter(OnPowerConsumerSelectedListener listener) {
-            mListener = listener;
-        }
-
-        void setPowerConsumerList(List<PowerConsumerInfo> powerConsumerList) {
-            mPowerConsumerList = powerConsumerList;
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getItemCount() {
-            return mPowerConsumerList.size();
-        }
-
-        @NonNull
-        @Override
-        public PowerConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
-                int position) {
-            LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
-            View view = layoutInflater.inflate(R.layout.power_consumer_info_layout, viewGroup,
-                    false);
-            return new PowerConsumerViewHolder(view, mListener);
-        }
-
-        @Override
-        public void onBindViewHolder(@NonNull PowerConsumerViewHolder viewHolder, int position) {
-            PowerConsumerInfoHelper.PowerConsumerInfo item = mPowerConsumerList.get(position);
-            viewHolder.id = item.id;
-            viewHolder.titleView.setText(item.label);
-            if (item.details != null) {
-                viewHolder.detailsView.setText(item.details);
-                viewHolder.detailsView.setVisibility(View.VISIBLE);
-            } else {
-                viewHolder.detailsView.setVisibility(View.GONE);
-            }
-            viewHolder.powerView.setText(
-                    String.format(Locale.getDefault(), "%.1f mAh", item.powerMah));
-            viewHolder.iconView.setImageDrawable(
-                    item.iconInfo.loadIcon(getContext().getPackageManager()));
-            if (item.packages != null) {
-                viewHolder.packagesView.setText(item.packages);
-                viewHolder.packagesView.setVisibility(View.VISIBLE);
-            } else {
-                viewHolder.packagesView.setVisibility(View.GONE);
-            }
-        }
-    }
-
-    // View Holder used when displaying apps
-    public static class PowerConsumerViewHolder extends RecyclerView.ViewHolder
-            implements View.OnClickListener {
-        private final OnPowerConsumerSelectedListener mListener;
-
-        public String id;
-        public TextView titleView;
-        public TextView detailsView;
-        public ImageView iconView;
-        public TextView packagesView;
-        public TextView powerView;
-
-        PowerConsumerViewHolder(View view, OnPowerConsumerSelectedListener listener) {
-            super(view);
-            mListener = listener;
-            view.setOnClickListener(this);
-            titleView = view.findViewById(android.R.id.title);
-            detailsView = view.findViewById(R.id.details);
-            iconView = view.findViewById(android.R.id.icon);
-            packagesView = view.findViewById(R.id.packages);
-            powerView = view.findViewById(R.id.power_mah);
-            powerView.setVisibility(View.VISIBLE);
-        }
-
-        @Override
-        public void onClick(View v) {
-            mListener.onPowerConsumerSelected(id);
-        }
-    }
-}
diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java
deleted file mode 100644
index 7aeb86a..0000000
--- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsviewer;
-
-import android.content.Context;
-import android.os.BatteryStats;
-import android.os.Process;
-
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PowerStatsData {
-    private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
-    private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
-    private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
-    private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
-            PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
-
-    // Temporary placeholder voltage for converting energy to charge
-    // TODO: remove this when b/173765509 is resolved
-    private static final double MOCK_NOMINAL_VOLTAGE = 3.7;
-
-    // Unit conversion:
-    //   mAh = uWs * (1/1000)(milli/micro) * (1/Voltage) * (1/3600)(hours/second)
-    private static final double UJ_2_MAH =
-            (1.0 / 1000) * (1.0 / MOCK_NOMINAL_VOLTAGE) * (1.0 / 3600);
-
-    enum EntryType {
-        POWER,
-        DURATION,
-    }
-
-    public static class Entry {
-        public String title;
-        public EntryType entryType;
-        public double value;
-        public double total;
-    }
-
-    private final PowerConsumerInfoHelper.PowerConsumerInfo mPowerConsumerInfo;
-    private final List<Entry> mEntries = new ArrayList<>();
-
-    public PowerStatsData(Context context, BatteryStatsHelper batteryStatsHelper,
-            String powerConsumerId) {
-        List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
-        BatteryStats batteryStats = batteryStatsHelper.getStats();
-
-        double totalPowerMah = 0;
-        double totalSmearedPowerMah = 0;
-        double totalPowerExcludeSystemMah = 0;
-        double totalScreenPower = 0;
-        double totalProportionalSmearMah = 0;
-        double totalCpuPowerMah = 0;
-        double totalSystemServiceCpuPowerMah = 0;
-        double totalUsagePowerMah = 0;
-        double totalWakeLockPowerMah = 0;
-        double totalMobileRadioPowerMah = 0;
-        double totalWifiPowerMah = 0;
-        double totalBluetoothPowerMah = 0;
-        double totalGpsPowerMah = 0;
-        double totalCameraPowerMah = 0;
-        double totalFlashlightPowerMah = 0;
-        double totalSensorPowerMah = 0;
-        double totalAudioPowerMah = 0;
-        double totalVideoPowerMah = 0;
-
-        long totalCpuTimeMs = 0;
-        long totalCpuFgTimeMs = 0;
-        long totalWakeLockTimeMs = 0;
-        long totalWifiRunningTimeMs = 0;
-        long totalBluetoothRunningTimeMs = 0;
-        long totalGpsTimeMs = 0;
-        long totalCameraTimeMs = 0;
-        long totalFlashlightTimeMs = 0;
-        long totalAudioTimeMs = 0;
-        long totalVideoTimeMs = 0;
-
-        BatterySipper requestedPowerConsumer = null;
-        for (BatterySipper sipper : usageList) {
-            if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
-                totalScreenPower = sipper.sumPower();
-            }
-
-            if (powerConsumerId(sipper).equals(powerConsumerId)) {
-                requestedPowerConsumer = sipper;
-            }
-
-            totalPowerMah += sipper.sumPower();
-            totalSmearedPowerMah += sipper.totalSmearedPowerMah;
-            totalProportionalSmearMah += sipper.proportionalSmearMah;
-
-            if (!isSystemSipper(sipper)) {
-                totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
-            }
-
-            totalCpuPowerMah += sipper.cpuPowerMah;
-            totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
-            totalUsagePowerMah += sipper.usagePowerMah;
-            totalWakeLockPowerMah += sipper.wakeLockPowerMah;
-            totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
-            totalWifiPowerMah += sipper.wifiPowerMah;
-            totalBluetoothPowerMah += sipper.bluetoothPowerMah;
-            totalGpsPowerMah += sipper.gpsPowerMah;
-            totalCameraPowerMah += sipper.cameraPowerMah;
-            totalFlashlightPowerMah += sipper.flashlightPowerMah;
-            totalSensorPowerMah += sipper.sensorPowerMah;
-            totalAudioPowerMah += sipper.audioPowerMah;
-            totalVideoPowerMah += sipper.videoPowerMah;
-
-            totalCpuTimeMs += sipper.cpuTimeMs;
-            totalCpuFgTimeMs += sipper.cpuFgTimeMs;
-            totalWakeLockTimeMs += sipper.wakeLockTimeMs;
-            totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
-            totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
-            totalGpsTimeMs += sipper.gpsTimeMs;
-            totalCameraTimeMs += sipper.cameraTimeMs;
-            totalFlashlightTimeMs += sipper.flashlightTimeMs;
-            totalAudioTimeMs += sipper.audioTimeMs;
-            totalVideoTimeMs += sipper.videoTimeMs;
-        }
-
-        long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy();
-
-        if (requestedPowerConsumer == null) {
-            mPowerConsumerInfo = null;
-            return;
-        }
-
-        mPowerConsumerInfo = PowerConsumerInfoHelper.makePowerConsumerInfo(
-                context.getPackageManager(), requestedPowerConsumer);
-
-        addEntry("Total power", EntryType.POWER,
-                requestedPowerConsumer.totalSmearedPowerMah, totalSmearedPowerMah);
-        maybeAddMeasuredEnergyEntry(requestedPowerConsumer.drainType, batteryStats);
-
-        addEntry("... excluding system", EntryType.POWER,
-                requestedPowerConsumer.totalSmearedPowerMah, totalPowerExcludeSystemMah);
-        addEntry("Screen, smeared", EntryType.POWER,
-                requestedPowerConsumer.screenPowerMah, totalScreenPower);
-        if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
-            final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ;
-            final double ratio = measuredCharge / totalScreenPower;
-            addEntry("Screen, smeared (PowerStatsHal adjusted)", EntryType.POWER,
-                    requestedPowerConsumer.screenPowerMah * ratio, measuredCharge);
-        }
-        addEntry("Other, smeared", EntryType.POWER,
-                requestedPowerConsumer.proportionalSmearMah, totalProportionalSmearMah);
-        addEntry("Excluding smeared", EntryType.POWER,
-                requestedPowerConsumer.totalPowerMah, totalPowerMah);
-        addEntry("CPU", EntryType.POWER,
-                requestedPowerConsumer.cpuPowerMah, totalCpuPowerMah);
-        addEntry("System services", EntryType.POWER,
-                requestedPowerConsumer.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
-        addEntry("Usage", EntryType.POWER,
-                requestedPowerConsumer.usagePowerMah, totalUsagePowerMah);
-        addEntry("Wake lock", EntryType.POWER,
-                requestedPowerConsumer.wakeLockPowerMah, totalWakeLockPowerMah);
-        addEntry("Mobile radio", EntryType.POWER,
-                requestedPowerConsumer.mobileRadioPowerMah, totalMobileRadioPowerMah);
-        addEntry("WiFi", EntryType.POWER,
-                requestedPowerConsumer.wifiPowerMah, totalWifiPowerMah);
-        addEntry("Bluetooth", EntryType.POWER,
-                requestedPowerConsumer.bluetoothPowerMah, totalBluetoothPowerMah);
-        addEntry("GPS", EntryType.POWER,
-                requestedPowerConsumer.gpsPowerMah, totalGpsPowerMah);
-        addEntry("Camera", EntryType.POWER,
-                requestedPowerConsumer.cameraPowerMah, totalCameraPowerMah);
-        addEntry("Flashlight", EntryType.POWER,
-                requestedPowerConsumer.flashlightPowerMah, totalFlashlightPowerMah);
-        addEntry("Sensors", EntryType.POWER,
-                requestedPowerConsumer.sensorPowerMah, totalSensorPowerMah);
-        addEntry("Audio", EntryType.POWER,
-                requestedPowerConsumer.audioPowerMah, totalAudioPowerMah);
-        addEntry("Video", EntryType.POWER,
-                requestedPowerConsumer.videoPowerMah, totalVideoPowerMah);
-
-        addEntry("CPU time", EntryType.DURATION,
-                requestedPowerConsumer.cpuTimeMs, totalCpuTimeMs);
-        addEntry("CPU foreground time", EntryType.DURATION,
-                requestedPowerConsumer.cpuFgTimeMs, totalCpuFgTimeMs);
-        addEntry("Wake lock time", EntryType.DURATION,
-                requestedPowerConsumer.wakeLockTimeMs, totalWakeLockTimeMs);
-        addEntry("WiFi running time", EntryType.DURATION,
-                requestedPowerConsumer.wifiRunningTimeMs, totalWifiRunningTimeMs);
-        addEntry("Bluetooth time", EntryType.DURATION,
-                requestedPowerConsumer.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
-        addEntry("GPS time", EntryType.DURATION,
-                requestedPowerConsumer.gpsTimeMs, totalGpsTimeMs);
-        addEntry("Camera time", EntryType.DURATION,
-                requestedPowerConsumer.cameraTimeMs, totalCameraTimeMs);
-        addEntry("Flashlight time", EntryType.DURATION,
-                requestedPowerConsumer.flashlightTimeMs, totalFlashlightTimeMs);
-        addEntry("Audio time", EntryType.DURATION,
-                requestedPowerConsumer.audioTimeMs, totalAudioTimeMs);
-        addEntry("Video time", EntryType.DURATION,
-                requestedPowerConsumer.videoTimeMs, totalVideoTimeMs);
-    }
-
-    private boolean isSystemSipper(BatterySipper sipper) {
-        final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
-        if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
-            return true;
-        } else if (sipper.mPackages != null) {
-            for (final String packageName : sipper.mPackages) {
-                for (final String systemPackage : PACKAGES_SYSTEM) {
-                    if (systemPackage.equals(packageName)) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private void addEntry(String title, EntryType entryType, double amount, double totalAmount) {
-        Entry entry = new Entry();
-        entry.title = title;
-        entry.entryType = entryType;
-        entry.value = amount;
-        entry.total = totalAmount;
-        mEntries.add(entry);
-    }
-
-    private void maybeAddMeasuredEnergyEntry(BatterySipper.DrainType drainType,
-            BatteryStats batteryStats) {
-        switch (drainType) {
-            case AMBIENT_DISPLAY:
-                final long totalDozeMeasuredEnergyUJ = batteryStats.getScreenDozeEnergy();
-                if (totalDozeMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
-                    final double measuredCharge = UJ_2_MAH * totalDozeMeasuredEnergyUJ;
-                    addEntry("Measured ambient display power", EntryType.POWER, measuredCharge,
-                            measuredCharge);
-                }
-                break;
-            case SCREEN:
-                final long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy();
-                if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
-                    final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ;
-                    addEntry("Measured screen power", EntryType.POWER, measuredCharge,
-                            measuredCharge);
-                }
-                break;
-        }
-    }
-
-    public PowerConsumerInfoHelper.PowerConsumerInfo getPowerConsumerInfo() {
-        return mPowerConsumerInfo;
-    }
-
-    public List<Entry> getEntries() {
-        return mEntries;
-    }
-
-    public static String powerConsumerId(BatterySipper sipper) {
-        return sipper.drainType + "|" + sipper.userId + "|" + sipper.getUid();
-    }
-}
diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java
deleted file mode 100644
index 0567910..0000000
--- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.frameworks.core.powerstatsviewer;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.BatteryStats;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.activity.ComponentActivity;
-import androidx.activity.result.ActivityResultLauncher;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.app.LoaderManager.LoaderCallbacks;
-import androidx.loader.content.Loader;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.settingslib.utils.AsyncLoaderCompat;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-public class PowerStatsViewerActivity extends ComponentActivity {
-    private static final int POWER_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
-    public static final String PREF_SELECTED_POWER_CONSUMER = "powerConsumerId";
-    private static final String LOADER_ARG_POWER_CONSUMER_ID = "powerConsumerId";
-
-    private PowerStatsDataAdapter mPowerStatsDataAdapter;
-    private Runnable mPowerStatsRefresh = this::periodicPowerStatsRefresh;
-    private SharedPreferences mSharedPref;
-    private String mPowerConsumerId;
-    private TextView mTitleView;
-    private TextView mDetailsView;
-    private ImageView mIconView;
-    private TextView mPackagesView;
-    private RecyclerView mPowerStatsDataView;
-    private View mLoadingView;
-    private View mEmptyView;
-    private ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult(
-            PowerConsumerPickerActivity.CONTRACT, this::onApplicationSelected);
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mSharedPref = getPreferences(Context.MODE_PRIVATE);
-
-        setContentView(R.layout.power_stats_viewer_layout);
-
-        View appCard = findViewById(R.id.app_card);
-        appCard.setOnClickListener((e) -> startAppPicker());
-
-        mTitleView = findViewById(android.R.id.title);
-        mDetailsView = findViewById(R.id.details);
-        mIconView = findViewById(android.R.id.icon);
-        mPackagesView = findViewById(R.id.packages);
-
-        mPowerStatsDataView = findViewById(R.id.power_stats_data_view);
-        mPowerStatsDataView.setLayoutManager(new LinearLayoutManager(this));
-        mPowerStatsDataAdapter = new PowerStatsDataAdapter();
-        mPowerStatsDataView.setAdapter(mPowerStatsDataAdapter);
-
-        mLoadingView = findViewById(R.id.loading_view);
-        mEmptyView = findViewById(R.id.empty_view);
-
-        mPowerConsumerId = mSharedPref.getString(PREF_SELECTED_POWER_CONSUMER, null);
-        loadPowerStats();
-        if (mPowerConsumerId == null) {
-            startAppPicker();
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        periodicPowerStatsRefresh();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        getMainThreadHandler().removeCallbacks(mPowerStatsRefresh);
-    }
-
-    private void startAppPicker() {
-        mStartAppPicker.launch(null);
-    }
-
-    private void onApplicationSelected(String powerConsumerId) {
-        if (powerConsumerId == null) {
-            if (mPowerConsumerId == null) {
-                finish();
-            }
-        } else {
-            mPowerConsumerId = powerConsumerId;
-            mSharedPref.edit().putString(PREF_SELECTED_POWER_CONSUMER, mPowerConsumerId).apply();
-            mLoadingView.setVisibility(View.VISIBLE);
-            loadPowerStats();
-        }
-    }
-
-    private void periodicPowerStatsRefresh() {
-        loadPowerStats();
-        getMainThreadHandler().postDelayed(mPowerStatsRefresh, POWER_STATS_REFRESH_RATE_MILLIS);
-    }
-
-    private void loadPowerStats() {
-        Bundle args = new Bundle();
-        args.putString(LOADER_ARG_POWER_CONSUMER_ID, mPowerConsumerId);
-        LoaderManager.getInstance(this).restartLoader(0, args, new PowerStatsDataLoaderCallbacks());
-    }
-
-    private static class PowerStatsDataLoader extends AsyncLoaderCompat<PowerStatsData> {
-        private final String mPowerConsumerId;
-        private final BatteryStatsHelper mBatteryStatsHelper;
-        private final UserManager mUserManager;
-
-        PowerStatsDataLoader(Context context, String powerConsumerId) {
-            super(context);
-            mPowerConsumerId = powerConsumerId;
-            mUserManager = context.getSystemService(UserManager.class);
-            mBatteryStatsHelper = new BatteryStatsHelper(context,
-                    false /* collectBatteryBroadcast */);
-            mBatteryStatsHelper.create((Bundle) null);
-            mBatteryStatsHelper.clearStats();
-        }
-
-        @Override
-        public PowerStatsData loadInBackground() {
-            mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
-                    UserHandle.myUserId());
-            return new PowerStatsData(getContext(), mBatteryStatsHelper, mPowerConsumerId);
-        }
-
-        @Override
-        protected void onDiscardResult(PowerStatsData result) {
-        }
-    }
-
-    private class PowerStatsDataLoaderCallbacks implements LoaderCallbacks<PowerStatsData> {
-        @NonNull
-        @Override
-        public Loader<PowerStatsData> onCreateLoader(int id, Bundle args) {
-            return new PowerStatsDataLoader(PowerStatsViewerActivity.this,
-                    args.getString(LOADER_ARG_POWER_CONSUMER_ID));
-        }
-
-        @Override
-        public void onLoadFinished(@NonNull Loader<PowerStatsData> loader,
-                PowerStatsData powerStatsData) {
-
-            PowerConsumerInfoHelper.PowerConsumerInfo
-                    powerConsumerInfo = powerStatsData.getPowerConsumerInfo();
-            if (powerConsumerInfo == null) {
-                mTitleView.setText("Power consumer not found");
-                mPackagesView.setVisibility(View.GONE);
-            } else {
-                mTitleView.setText(powerConsumerInfo.label);
-                if (powerConsumerInfo.details != null) {
-                    mDetailsView.setText(powerConsumerInfo.details);
-                    mDetailsView.setVisibility(View.VISIBLE);
-                } else {
-                    mDetailsView.setVisibility(View.GONE);
-                }
-                mIconView.setImageDrawable(
-                        powerConsumerInfo.iconInfo.loadIcon(getPackageManager()));
-
-                if (powerConsumerInfo.packages != null) {
-                    mPackagesView.setText(powerConsumerInfo.packages);
-                    mPackagesView.setVisibility(View.VISIBLE);
-                } else {
-                    mPackagesView.setVisibility(View.GONE);
-                }
-            }
-
-            mPowerStatsDataAdapter.setEntries(powerStatsData.getEntries());
-            if (powerStatsData.getEntries().isEmpty()) {
-                mEmptyView.setVisibility(View.VISIBLE);
-                mPowerStatsDataView.setVisibility(View.GONE);
-            } else {
-                mEmptyView.setVisibility(View.GONE);
-                mPowerStatsDataView.setVisibility(View.VISIBLE);
-            }
-
-            mLoadingView.setVisibility(View.GONE);
-        }
-
-        @Override
-        public void onLoaderReset(@NonNull Loader<PowerStatsData> loader) {
-        }
-    }
-
-    private static class PowerStatsDataAdapter extends
-            RecyclerView.Adapter<PowerStatsDataAdapter.ViewHolder> {
-        public static class ViewHolder extends RecyclerView.ViewHolder {
-            public TextView titleTextView;
-            public TextView amountTextView;
-            public TextView percentTextView;
-
-            ViewHolder(View itemView) {
-                super(itemView);
-
-                titleTextView = itemView.findViewById(R.id.title);
-                amountTextView = itemView.findViewById(R.id.amount);
-                percentTextView = itemView.findViewById(R.id.percent);
-            }
-        }
-
-        private List<PowerStatsData.Entry> mEntries = Collections.emptyList();
-
-        public void setEntries(List<PowerStatsData.Entry> entries) {
-            mEntries = entries;
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getItemCount() {
-            return mEntries.size();
-        }
-
-        @NonNull
-        @Override
-        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
-            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
-            View itemView = layoutInflater.inflate(R.layout.power_stats_entry_layout, parent,
-                    false);
-            return new ViewHolder(itemView);
-        }
-
-        @Override
-        public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
-            PowerStatsData.Entry entry = mEntries.get(position);
-            switch (entry.entryType) {
-                case POWER:
-                    viewHolder.titleTextView.setText(entry.title);
-                    viewHolder.amountTextView.setText(
-                            String.format(Locale.getDefault(), "%.1f mAh", entry.value));
-                    break;
-                case DURATION:
-                    viewHolder.titleTextView.setText(entry.title);
-                    viewHolder.amountTextView.setText(
-                            String.format(Locale.getDefault(), "%,d ms", (long) entry.value));
-                    break;
-            }
-
-            double proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0;
-            viewHolder.percentTextView.setText(String.format(Locale.getDefault(), "%.1f%%",
-                    proportion));
-        }
-    }
-}
diff --git a/core/tests/uwbtests/OWNERS b/core/tests/uwbtests/OWNERS
new file mode 100644
index 0000000..c7b09a2
--- /dev/null
+++ b/core/tests/uwbtests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/uwb/OWNERS
diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java
index 077b08f..e0884e3 100644
--- a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java
+++ b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java
@@ -48,8 +48,8 @@
         builder.setAzimuthAngleMeasurement(azimuth);
         AngleOfArrivalMeasurement measurement = tryBuild(builder, true);
 
-        assertEquals(azimuth, measurement.getAzimuth());
-        assertEquals(altitude, measurement.getAltitude());
+        assertEquals(azimuth, measurement.getAzimuthAngleMeasurement());
+        assertEquals(altitude, measurement.getAltitudeAngleMeasurement());
     }
 
     private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) {
diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
new file mode 100644
index 0000000..6df1c3e
--- /dev/null
+++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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.uwb;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test of {@link AdapterStateListener}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RangingManagerTest {
+
+    private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
+    private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
+    private static final PersistableBundle PARAMS = new PersistableBundle();
+    private static final @CloseReason int CLOSE_REASON = CloseReason.UNKNOWN;
+
+    @Test
+    public void testOpenSession_StartRangingInvoked() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+        verify(ADAPTER, times(1)).startRanging(eq(rangingManager), eq(PARAMS));
+    }
+
+    @Test
+    public void testOpenSession_ErrorIfSameSessionHandleReturned() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+        // Calling openSession will cause the same session handle to be returned. The onClosed
+        // callback should be invoked
+        RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+        verify(callback, times(0)).onClosed(anyInt(), any());
+        verify(callback2, times(1)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingStarted_ValidSessionHandle() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+        rangingManager.onRangingStarted(handle, PARAMS);
+        verify(callback, times(1)).onOpenSuccess(any(), any());
+    }
+
+    @Test
+    public void testOnRangingStarted_InvalidSessionHandle() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+
+        rangingManager.onRangingStarted(new SessionHandle(2), PARAMS);
+        verify(callback, times(0)).onOpenSuccess(any(), any());
+    }
+
+    @Test
+    public void testOnRangingStarted_MultipleSessionsRegistered() throws RemoteException {
+        SessionHandle sessionHandle1 = new SessionHandle(1);
+        SessionHandle sessionHandle2 = new SessionHandle(2);
+        RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+        RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+        when(ADAPTER.startRanging(any(), any()))
+                .thenReturn(sessionHandle1)
+                .thenReturn(sessionHandle2);
+
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+
+        rangingManager.onRangingStarted(sessionHandle1, PARAMS);
+        verify(callback1, times(1)).onOpenSuccess(any(), any());
+        verify(callback2, times(0)).onOpenSuccess(any(), any());
+
+        rangingManager.onRangingStarted(sessionHandle2, PARAMS);
+        verify(callback1, times(1)).onOpenSuccess(any(), any());
+        verify(callback2, times(1)).onOpenSuccess(any(), any());
+    }
+
+    @Test
+    public void testOnRangingClosed_OnRangingClosedCalled() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+        rangingManager.onRangingClosed(handle, CLOSE_REASON, PARAMS);
+        verify(callback, times(1)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingClosed_MultipleSessionsRegistered() throws RemoteException {
+        // Verify that if multiple sessions are registered, only the session that is
+        // requested to close receives the associated callbacks
+        SessionHandle sessionHandle1 = new SessionHandle(1);
+        SessionHandle sessionHandle2 = new SessionHandle(2);
+        RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+        RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+        when(ADAPTER.startRanging(any(), any()))
+                .thenReturn(sessionHandle1)
+                .thenReturn(sessionHandle2);
+
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+
+        rangingManager.onRangingClosed(sessionHandle1, CLOSE_REASON, PARAMS);
+        verify(callback1, times(1)).onClosed(anyInt(), any());
+        verify(callback2, times(0)).onClosed(anyInt(), any());
+
+        rangingManager.onRangingClosed(sessionHandle2, CLOSE_REASON, PARAMS);
+        verify(callback1, times(1)).onClosed(anyInt(), any());
+        verify(callback2, times(1)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingReport_OnReportReceived() throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+        rangingManager.onRangingStarted(handle, PARAMS);
+
+        RangingReport report = UwbTestUtils.getRangingReports(1);
+        rangingManager.onRangingResult(handle, report);
+        verify(callback, times(1)).onReportReceived(eq(report));
+    }
+
+    @Test
+    public void testOnRangingReport_MultipleSessionsRegistered() throws RemoteException {
+        SessionHandle sessionHandle1 = new SessionHandle(1);
+        SessionHandle sessionHandle2 = new SessionHandle(2);
+        RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+        RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+        when(ADAPTER.startRanging(any(), any()))
+                .thenReturn(sessionHandle1)
+                .thenReturn(sessionHandle2);
+
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+        rangingManager.onRangingStarted(sessionHandle1, PARAMS);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+        rangingManager.onRangingStarted(sessionHandle2, PARAMS);
+
+        rangingManager.onRangingResult(sessionHandle1, UwbTestUtils.getRangingReports(1));
+        verify(callback1, times(1)).onReportReceived(any());
+        verify(callback2, times(0)).onReportReceived(any());
+
+        rangingManager.onRangingResult(sessionHandle2, UwbTestUtils.getRangingReports(1));
+        verify(callback1, times(1)).onReportReceived(any());
+        verify(callback2, times(1)).onReportReceived(any());
+    }
+
+    @Test
+    public void testOnClose_Reasons() throws RemoteException {
+        runOnClose_Reason(CloseReason.LOCAL_API,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API);
+
+        runOnClose_Reason(CloseReason.MAX_SESSIONS_REACHED,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+
+        runOnClose_Reason(CloseReason.PROTOCOL_SPECIFIC,
+                RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+
+        runOnClose_Reason(CloseReason.REMOTE_REQUEST,
+                RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST);
+
+        runOnClose_Reason(CloseReason.SYSTEM_POLICY,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+
+        runOnClose_Reason(CloseReason.UNKNOWN,
+                RangingSession.Callback.CLOSE_REASON_UNKNOWN);
+    }
+
+    private void runOnClose_Reason(@CloseReason int reasonIn,
+            @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+        rangingManager.onRangingClosed(handle, reasonIn, PARAMS);
+        verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
+    }
+
+    @Test
+    public void testStartFailureReasons() throws RemoteException {
+        runOnRangingStartFailed_Reason(StartFailureReason.BAD_PARAMETERS,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS);
+
+        runOnRangingStartFailed_Reason(StartFailureReason.MAX_SESSIONS_REACHED,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+
+        runOnRangingStartFailed_Reason(StartFailureReason.PROTOCOL_SPECIFIC,
+                RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+
+        runOnRangingStartFailed_Reason(StartFailureReason.SYSTEM_POLICY,
+                RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+
+        runOnRangingStartFailed_Reason(StartFailureReason.UNKNOWN,
+                RangingSession.Callback.CLOSE_REASON_UNKNOWN);
+    }
+
+    private void runOnRangingStartFailed_Reason(@StartFailureReason int reasonIn,
+            @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
+        RangingManager rangingManager = new RangingManager(ADAPTER);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        SessionHandle handle = new SessionHandle(1);
+        when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+        rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+        rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS);
+        verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
+    }
+}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java
index a7559d8..edd4d08 100644
--- a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java
+++ b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java
@@ -63,8 +63,8 @@
         assertEquals(status, measurement.getStatus());
         assertEquals(address, measurement.getRemoteDeviceAddress());
         assertEquals(time, measurement.getElapsedRealtimeNanos());
-        assertEquals(angleMeasurement, measurement.getAngleOfArrival());
-        assertEquals(distanceMeasurement, measurement.getDistance());
+        assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement());
+        assertEquals(distanceMeasurement, measurement.getDistanceMeasurement());
     }
 
     private RangingMeasurement tryBuild(RangingMeasurement.Builder builder,
diff --git a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
new file mode 100644
index 0000000..702c68e
--- /dev/null
+++ b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.uwb;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test of {@link RangingSession}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RangingSessionTest {
+    private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
+    private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
+    private static final PersistableBundle PARAMS = new PersistableBundle();
+    private static final @RangingSession.Callback.CloseReason int CLOSE_REASON =
+            RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR;
+
+    @Test
+    public void testOnRangingStarted_OnOpenSuccessCalled() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+        verifyOpenState(session, false);
+
+        session.onRangingStarted(PARAMS);
+        verifyOpenState(session, true);
+
+        // Verify that the onOpenSuccess callback was invoked
+        verify(callback, times(1)).onOpenSuccess(eq(session), any());
+        verify(callback, times(0)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingStarted_CannotOpenClosedSession() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+        session.onRangingStarted(PARAMS);
+        verifyOpenState(session, true);
+        verify(callback, times(1)).onOpenSuccess(eq(session), any());
+        verify(callback, times(0)).onClosed(anyInt(), any());
+
+        session.onRangingClosed(CLOSE_REASON, PARAMS);
+        verifyOpenState(session, false);
+        verify(callback, times(1)).onOpenSuccess(eq(session), any());
+        verify(callback, times(1)).onClosed(anyInt(), any());
+
+        // Now invoke the ranging started callback and ensure the session remains closed
+        session.onRangingStarted(PARAMS);
+        verifyOpenState(session, false);
+        verify(callback, times(1)).onOpenSuccess(eq(session), any());
+        verify(callback, times(1)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+        verifyOpenState(session, false);
+
+        session.onRangingClosed(CLOSE_REASON, PARAMS);
+        verifyOpenState(session, false);
+
+        // Verify that the onOpenSuccess callback was invoked
+        verify(callback, times(0)).onOpenSuccess(eq(session), any());
+        verify(callback, times(1)).onClosed(anyInt(), any());
+    }
+
+    @Test public void testOnRangingClosed_OnClosedCalled() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+        session.onRangingStarted(PARAMS);
+        session.onRangingClosed(CLOSE_REASON, PARAMS);
+        verify(callback, times(1)).onClosed(anyInt(), any());
+
+        verifyOpenState(session, false);
+        session.onRangingClosed(CLOSE_REASON, PARAMS);
+        verify(callback, times(2)).onClosed(anyInt(), any());
+    }
+
+    @Test
+    public void testOnRangingResult_OnReportReceivedCalled() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+        verifyOpenState(session, false);
+
+        session.onRangingStarted(PARAMS);
+        verifyOpenState(session, true);
+
+        RangingReport report = UwbTestUtils.getRangingReports(1);
+        session.onRangingResult(report);
+        verify(callback, times(1)).onReportReceived(eq(report));
+    }
+
+    @Test
+    public void testClose() throws RemoteException {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+        session.onRangingStarted(PARAMS);
+
+        // Calling close multiple times should invoke closeRanging until the session receives
+        // the onClosed callback.
+        int totalCallsBeforeOnRangingClosed = 3;
+        for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) {
+            session.close();
+            verifyOpenState(session, true);
+            verify(ADAPTER, times(i)).closeRanging(handle);
+            verify(callback, times(0)).onClosed(anyInt(), any());
+        }
+
+        // After onClosed is invoked, then the adapter should no longer be called for each call to
+        // the session's close.
+        final int totalCallsAfterOnRangingClosed = 2;
+        for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) {
+            session.onRangingClosed(CLOSE_REASON, PARAMS);
+            verifyOpenState(session, false);
+            verify(ADAPTER, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
+            verify(callback, times(i)).onClosed(anyInt(), any());
+        }
+    }
+
+    @Test
+    public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+        assertFalse(session.isOpen());
+        session.onRangingStarted(PARAMS);
+        assertTrue(session.isOpen());
+
+        // Verify that the onReportReceived callback was invoked
+        RangingReport report = UwbTestUtils.getRangingReports(1);
+        session.onRangingResult(report);
+        verify(callback, times(1)).onReportReceived(report);
+    }
+
+    @Test
+    public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
+        SessionHandle handle = new SessionHandle(123);
+        RangingSession.Callback callback = mock(RangingSession.Callback.class);
+        RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+        assertFalse(session.isOpen());
+
+        // Verify that the onReportReceived callback was invoked
+        RangingReport report = UwbTestUtils.getRangingReports(1);
+        session.onRangingResult(report);
+        verify(callback, times(0)).onReportReceived(report);
+    }
+
+    private void verifyOpenState(RangingSession session, boolean expected) {
+        assertEquals(expected, session.isOpen());
+    }
+}
diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
index fb75092..b4b2e30 100644
--- a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
+++ b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
@@ -22,6 +22,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 public class UwbTestUtils {
     private UwbTestUtils() {}
@@ -96,4 +97,13 @@
         }
         return UwbAddress.fromBytes(addressBytes);
     }
+
+    public static Executor getExecutor() {
+        return new Executor() {
+            @Override
+            public void execute(Runnable command) {
+                command.run();
+            }
+        };
+    }
 }
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 70d4678..5efd0bd 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1 +1,13 @@
-per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com, cbrubaker@google.com, jeffv@google.com, moltmann@google.com, lorenzo@google.com
+cbrubaker@google.com
+hackbod@android.com
+hackbod@google.com
+jeffv@google.com
+jsharkey@android.com
+jsharkey@google.com
+lorenzo@google.com
+moltmann@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+toddke@android.com
+toddke@google.com
+yamasani@google.com
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 3e3aefc..7f20b3b 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -159,6 +159,13 @@
 }
 
 prebuilt_etc {
+    name: "privapp_allowlist_com.google.android.car.networking.preferenceupdater",
+    sub_dir: "permissions",
+    src: "com.google.android.car.networking.preferenceupdater.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
     name: "allowed_privapp_com.android.carshell",
     sub_dir: "permissions",
     src: "com.android.car.shell.xml",
diff --git a/data/etc/car/OWNERS b/data/etc/car/OWNERS
new file mode 100644
index 0000000..09e257c
--- /dev/null
+++ b/data/etc/car/OWNERS
@@ -0,0 +1 @@
+include platform/packages/services/Car:/OWNERS
diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml
index 474cd54..4fd9cae 100644
--- a/data/etc/car/com.android.car.provision.xml
+++ b/data/etc/car/com.android.car.provision.xml
@@ -18,6 +18,8 @@
     <privapp-permissions package="com.android.car.provision">
         <permission name="android.car.permission.CAR_POWERTRAIN"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+        <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MASTER_CLEAR"/>
         <permission name="android.permission.QUERY_ALL_PACKAGES"/>
         <permission name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"/>
diff --git a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
new file mode 100644
index 0000000..489ce1b
--- /dev/null
+++ b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<permissions>
+    <privapp-permissions package="com.google.android.car.networking.preferenceupdater">
+        <permission name="android.permission.ACCESS_NETWORK_STATE"/>
+        <permission name="android.permission.ACCESS_WIFI_STATE"/>
+        <permission name="android.permission.ACTIVITY_EMBEDDING"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+        <permission name="android.permission.LOCATION_HARDWARE"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.cellbroadcastreceiver.xml b/data/etc/com.android.cellbroadcastreceiver.xml
index dd2df42..ef49bfa 100644
--- a/data/etc/com.android.cellbroadcastreceiver.xml
+++ b/data/etc/com.android.cellbroadcastreceiver.xml
@@ -19,6 +19,7 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
diff --git a/data/etc/com.android.documentsui.xml b/data/etc/com.android.documentsui.xml
index 1e570ba..d32cbec 100644
--- a/data/etc/com.android.documentsui.xml
+++ b/data/etc/com.android.documentsui.xml
@@ -22,5 +22,6 @@
         <permission name="android.permission.LOG_COMPAT_CHANGE"/>
         <permission name="android.permission.MODIFY_QUIET_MODE"/>
         <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+        <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 5f129fe..2e12795 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -49,6 +49,7 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
@@ -210,6 +211,7 @@
 
     <privapp-permissions package="com.android.providers.contacts">
         <permission name="android.permission.BIND_DIRECTORY_SEARCH"/>
+        <permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/>
         <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
@@ -245,6 +247,7 @@
         <permission name="android.permission.REGISTER_STATS_PULL_ATOM" />
         <!-- Permissions required for reading DeviceConfig -->
         <permission name="android.permission.READ_DEVICE_CONFIG" />
+        <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.providers.telephony">
@@ -450,6 +453,8 @@
         <permission name="android.permission.TEST_BIOMETRIC" />
         <!-- Permissions required for CTS test - CtsContactsProviderTestCases -->
         <permission name="android.contacts.permission.MANAGE_SIM_ACCOUNTS" />
+        <!-- Permissions required for CTS test - CtsHdmiCecHostTestCases -->
+        <permission name="android.permission.HDMI_CEC"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index a5667b2..faf4973 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -901,6 +901,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1069336896": {
+      "message": "onRootTaskOrderChanged(): rootTask=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
+    },
     "-1066383762": {
       "message": "Sleep still waiting to pause %s",
       "level": "VERBOSE",
@@ -1021,12 +1027,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-903853754": {
-      "message": "pauseBackStacks: stack=%s mResumedActivity=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_STATES",
-      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
-    },
     "-883738232": {
       "message": "Adding more than one toast window for UID at a time.",
       "level": "WARN",
@@ -1069,6 +1069,12 @@
       "group": "WM_DEBUG_TASKS",
       "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java"
     },
+    "-856590985": {
+      "message": "dcTarget: %s mImeRequester: %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
+    },
     "-856025122": {
       "message": "SURFACE transparentRegionHint=%s: %s",
       "level": "INFO",
@@ -1303,6 +1309,12 @@
       "group": "WM_DEBUG_CONFIGURATION",
       "at": "com\/android\/server\/am\/ActivityManagerService.java"
     },
+    "-592371899": {
+      "message": "Skipping rootTask: (mismatch activity\/rootTask) %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_TASKS",
+      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+    },
     "-583031528": {
       "message": "%s",
       "level": "INFO",
@@ -1717,12 +1729,6 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/Session.java"
     },
-    "-49129622": {
-      "message": "performLayout: Activity exiting now removed %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
-    },
     "-33096143": {
       "message": "applyAnimation: transition animation is disabled or skipped. container=%s",
       "level": "VERBOSE",
@@ -1777,6 +1783,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "44438983": {
+      "message": "performLayout: Activity exiting now removed %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "45285419": {
       "message": "startingWindow was set but startingSurface==null, couldn't remove",
       "level": "VERBOSE",
@@ -1837,12 +1849,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowContextListenerController.java"
     },
-    "91350919": {
-      "message": "Attempted to set IME flag to a display that does not exist: %d",
-      "level": "WARN",
-      "group": "WM_ERROR",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "94402792": {
       "message": "Moving to RESUMED: %s (in existing)",
       "level": "VERBOSE",
@@ -2161,6 +2167,12 @@
       "group": "WM_DEBUG_BOOT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "391189028": {
+      "message": "pauseBackTasks: task=%s mResumedActivity=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_STATES",
+      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+    },
     "397105698": {
       "message": "grantEmbeddedWindowFocus remove request for win=%s dropped since no candidate was found",
       "level": "VERBOSE",
@@ -2245,12 +2257,6 @@
       "group": "WM_DEBUG_WINDOW_ORGANIZER",
       "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
     },
-    "490877640": {
-      "message": "onStackOrderChanged(): stack=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
     "495032901": {
       "message": "Expected target stack=%s to restored behind stack=%s but it is behind stack=%s",
       "level": "WARN",
@@ -2383,12 +2389,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "632168013": {
-      "message": "dcTarget: %s mImeTargetFromIme: %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_IME",
-      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
-    },
     "633654009": {
       "message": "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s",
       "level": "INFO",
@@ -2581,12 +2581,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "875196661": {
-      "message": "Skipping stack: (mismatch activity\/stack) %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_TASKS",
-      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
-    },
     "883475718": {
       "message": "Report configuration: %s %s %s",
       "level": "VERBOSE",
diff --git a/data/fonts/OWNERS b/data/fonts/OWNERS
new file mode 100644
index 0000000..a538331
--- /dev/null
+++ b/data/fonts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/fonts/OWNERS
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index ba2e52a..2db4c5d 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -377,16 +377,44 @@
         </font>
     </family>
     <family lang="und-Deva" variant="elegant">
-        <font weight="400" style="normal">NotoSansDevanagari-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansDevanagari-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansDevanagari-Bold.otf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Deva" variant="compact">
-        <font weight="400" style="normal">NotoSansDevanagariUI-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansDevanagariUI-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansDevanagariUI-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansDevanagariUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansDevanagariUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansDevanagariUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansDevanagariUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
 
     <!-- All scripts of India should come after Devanagari, due to shared
@@ -395,78 +423,262 @@
     <family lang="und-Gujr" variant="elegant">
         <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-Bold.ttf</font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Gujr" variant="compact">
         <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
     </family>
     <family lang="und-Guru" variant="elegant">
-        <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.otf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Guru" variant="compact">
-        <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansGurmukhiUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansGurmukhiUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansGurmukhiUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansGurmukhiUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Taml" variant="elegant">
-        <font weight="400" style="normal">NotoSansTamil-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansTamil-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansTamil-Bold.otf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.otf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansTamil-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansTamil-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansTamil-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansTamil-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Taml" variant="compact">
-        <font weight="400" style="normal">NotoSansTamilUI-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansTamilUI-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansTamilUI-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansTamilUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansTamilUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansTamilUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansTamilUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Mlym" variant="elegant">
-        <font weight="400" style="normal">NotoSansMalayalam-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansMalayalam-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansMalayalam-Bold.otf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Mlym" variant="compact">
-        <font weight="400" style="normal">NotoSansMalayalamUI-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansMalayalamUI-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansMalayalamUI-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansMalayalamUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansMalayalamUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansMalayalamUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansMalayalamUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Beng" variant="elegant">
-        <font weight="400" style="normal">NotoSansBengali-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansBengali-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansBengali-Bold.otf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansBengali-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansBengali-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansBengali-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansBengali-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Beng" variant="compact">
-        <font weight="400" style="normal">NotoSansBengaliUI-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansBengaliUI-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansBengaliUI-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansBengaliUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansBengaliUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansBengaliUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansBengaliUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Telu" variant="elegant">
-        <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansTelugu-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansTelugu-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansTelugu-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansTelugu-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Telu" variant="compact">
-        <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansTeluguUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansTeluguUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansTeluguUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansTeluguUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Knda" variant="elegant">
-        <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansKannada-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansKannada-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansKannada-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansKannada-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Knda" variant="compact">
-        <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
+        <font weight="400" style="normal">NotoSansKannadaUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansKannadaUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansKannadaUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansKannadaUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Orya" variant="elegant">
         <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
@@ -476,18 +688,45 @@
         <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
     </family>
-
     <family lang="und-Sinh" variant="elegant">
-        <font weight="400" style="normal">NotoSansSinhala-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansSinhala-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansSinhala-Bold.otf</font>
-        <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.otf</font>
-        <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansSinhala-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansSinhala-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansSinhala-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansSinhala-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
+        <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Sinh" variant="compact">
-        <font weight="400" style="normal">NotoSansSinhalaUI-Regular.otf</font>
-        <font weight="500" style="normal">NotoSansSinhalaUI-Medium.otf</font>
-        <font weight="700" style="normal">NotoSansSinhalaUI-Bold.otf</font>
+        <font weight="400" style="normal">NotoSansSinhalaUI-VF.ttf
+            <axis tag="wght" stylevalue="400"/>
+        </font>
+        <font weight="500" style="normal">NotoSansSinhalaUI-VF.ttf
+            <axis tag="wght" stylevalue="500"/>
+        </font>
+        <font weight="600" style="normal">NotoSansSinhalaUI-VF.ttf
+            <axis tag="wght" stylevalue="600"/>
+        </font>
+        <font weight="700" style="normal">NotoSansSinhalaUI-VF.ttf
+            <axis tag="wght" stylevalue="700"/>
+        </font>
     </family>
     <family lang="und-Khmr" variant="elegant">
         <font weight="100" style="normal">NotoSansKhmer-VF.ttf
@@ -650,7 +889,7 @@
         <font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
     </family>
     <family lang="und-Java">
-        <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
     </family>
     <family lang="und-Kthi">
         <font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 6ac73b1..bd0e56a 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -445,3 +445,11 @@
 led 0x08 MISC
 led 0x09 MAIL
 led 0x0a CHARGING
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4.idc b/data/keyboards/Vendor_054c_Product_05c4.idc
new file mode 100644
index 0000000..2cb3f7b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4.idc
@@ -0,0 +1,35 @@
+# 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.
+
+#
+# Sony DS4 motion sensor configuration file.
+#
+
+# reporting mode 0 - continuous
+sensor.accelerometer.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.accelerometer.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.accelerometer.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.accelerometer.power = 1.5
+
+# reporting mode 0 - continuous
+sensor.gyroscope.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.gyroscope.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.gyroscope.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.gyroscope.power = 0.8
diff --git a/data/keyboards/Vendor_054c_Product_05c4.kl b/data/keyboards/Vendor_054c_Product_05c4.kl
index cd7ab1f..c8b4fc3 100644
--- a/data/keyboards/Vendor_054c_Product_05c4.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4.kl
@@ -68,3 +68,11 @@
 # and this button will be equivalent to left mouse button
 # Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
 key 0x13d   BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
index d38bdec..1473c4e 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc.idc b/data/keyboards/Vendor_054c_Product_09cc.idc
new file mode 100644
index 0000000..2cb3f7b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc.idc
@@ -0,0 +1,35 @@
+# 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.
+
+#
+# Sony DS4 motion sensor configuration file.
+#
+
+# reporting mode 0 - continuous
+sensor.accelerometer.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.accelerometer.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.accelerometer.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.accelerometer.power = 1.5
+
+# reporting mode 0 - continuous
+sensor.gyroscope.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.gyroscope.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.gyroscope.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.gyroscope.power = 0.8
diff --git a/data/keyboards/Vendor_054c_Product_09cc.kl b/data/keyboards/Vendor_054c_Product_09cc.kl
index cd7ab1f..c8b4fc3 100644
--- a/data/keyboards/Vendor_054c_Product_09cc.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc.kl
@@ -68,3 +68,11 @@
 # and this button will be equivalent to left mouse button
 # Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
 key 0x13d   BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
index d38bdec..1473c4e 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
@@ -66,3 +66,11 @@
 
 # In kernel versions >= 4.10, the touchpad is a separate input device,
 # so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/keyboards.mk b/data/keyboards/keyboards.mk
index 68cbd29..c7ce8cd 100644
--- a/data/keyboards/keyboards.mk
+++ b/data/keyboards/keyboards.mk
@@ -14,13 +14,9 @@
 
 # Warning: this is actually a product definition, to be inherited from
 
-include $(LOCAL_PATH)/common.mk
+PRODUCT_COPY_FILES := \
+  $(call find-copy-subdir-files,*.kl,$(LOCAL_PATH),system/usr/keylayout) \
+  $(call find-copy-subdir-files,*.kcm,$(LOCAL_PATH),system/usr/keychars) \
+  $(call find-copy-subdir-files,*.idc,$(LOCAL_PATH),system/usr/idc)
 
-PRODUCT_COPY_FILES := $(foreach file,$(framework_keylayouts),\
-    $(file):system/usr/keylayout/$(notdir $(file)))
 
-PRODUCT_COPY_FILES += $(foreach file,$(framework_keycharmaps),\
-    $(file):system/usr/keychars/$(notdir $(file)))
-
-PRODUCT_COPY_FILES += $(foreach file,$(framework_keyconfigs),\
-    $(file):system/usr/idc/$(notdir $(file)))
diff --git a/drm/java/android/drm/DrmOutputStream.java b/drm/java/android/drm/DrmOutputStream.java
index 73e7f23..2a3f530 100644
--- a/drm/java/android/drm/DrmOutputStream.java
+++ b/drm/java/android/drm/DrmOutputStream.java
@@ -25,9 +25,10 @@
 import android.system.Os;
 import android.util.Log;
 
+import com.android.internal.util.ArrayUtils;
+
 import libcore.io.IoBridge;
 import libcore.io.Streams;
-import libcore.util.ArrayUtils;
 
 import java.io.FileDescriptor;
 import java.io.FilterOutputStream;
diff --git a/drm/java/android/drm/OWNERS b/drm/java/android/drm/OWNERS
new file mode 100644
index 0000000..4387100
--- /dev/null
+++ b/drm/java/android/drm/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+
+jtinker@google.com
+robertshih@google.com
diff --git a/errorprone/OWNERS b/errorprone/OWNERS
new file mode 100644
index 0000000..bddbdb3
--- /dev/null
+++ b/errorprone/OWNERS
@@ -0,0 +1,2 @@
+jsharkey@android.com
+jsharkey@google.com
diff --git a/graphics/OWNERS b/graphics/OWNERS
new file mode 100644
index 0000000..a6d1bc3
--- /dev/null
+++ b/graphics/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/OWNERS
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 1cb5912..e6ff187 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -31,6 +31,23 @@
     private int mTileX;
     private int mTileY;
 
+    /*
+     *  This is cache of the last value from the Paint of bitmap-filtering.
+     *  In the future, BitmapShaders will carry their own (expanded) data for this
+     *  (e.g. including mipmap options, or bicubic weights)
+     *
+     *  When that happens, this bool will become those extended values, and we will
+     *  need to track whether this Shader was created with those new constructors,
+     *  or from the current "legacy" constructor, which (for compatibility) will
+     *  still need to know the Paint's setting.
+     *
+     *  When the filter Paint setting is finally gone, we will be able to remove
+     *  the filterFromPaint parameter currently being passed to createNativeInstance()
+     *  and shouldDiscardNativeInstance(), as shaders will always know their filter
+     *  settings.
+     */
+    private boolean mFilterFromPaint;
+
     /**
      * Call this to create a new shader that will draw with a bitmap.
      *
@@ -49,14 +66,24 @@
         mBitmap = bitmap;
         mTileX = tileX;
         mTileY = tileY;
+        mFilterFromPaint = false;
     }
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY);
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mFilterFromPaint = filterFromPaint;
+        return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
+                            mFilterFromPaint);
+    }
+
+    /** @hide */
+    @Override
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        return mFilterFromPaint != filterFromPaint;
     }
 
     private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
-            int shaderTileModeX, int shaderTileModeY);
+            int shaderTileModeX, int shaderTileModeY, boolean filter);
 }
+
diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java
index 3bc8119..2e4bd7d 100644
--- a/graphics/java/android/graphics/BlurShader.java
+++ b/graphics/java/android/graphics/BlurShader.java
@@ -69,16 +69,18 @@
 
     /** @hide **/
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        mNativeInputShader = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mNativeInputShader = mInputShader != null
+                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
         return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
                 mEdgeTreatment.nativeInt);
     }
 
     /** @hide **/
     @Override
-    protected boolean shouldDiscardNativeInstance() {
-        long currentNativeInstance = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        long currentNativeInstance = mInputShader != null
+                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
         return mNativeInputShader != currentNativeInstance;
     }
 
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index b840f3f..977aeaa 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -86,18 +86,18 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        mNativeInstanceShaderA = mShaderA.getNativeInstance();
-        mNativeInstanceShaderB = mShaderB.getNativeInstance();
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mNativeInstanceShaderA = mShaderA.getNativeInstance(filterFromPaint);
+        mNativeInstanceShaderB = mShaderB.getNativeInstance(filterFromPaint);
         return nativeCreate(nativeMatrix,
                 mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
     }
 
     /** @hide */
     @Override
-    protected boolean shouldDiscardNativeInstance() {
-        return mShaderA.getNativeInstance() != mNativeInstanceShaderA
-                || mShaderB.getNativeInstance() != mNativeInstanceShaderB;
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        return mShaderA.getNativeInstance(filterFromPaint) != mNativeInstanceShaderA
+                || mShaderB.getNativeInstance(filterFromPaint) != mNativeInstanceShaderB;
     }
 
     private static native long nativeCreate(long nativeMatrix,
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 4eedbf5..56d912b 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -154,7 +154,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1,
                 mColorLongs, mPositions, mTileMode.nativeInt,
                 colorSpace().getNativeInstance());
diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS
new file mode 100644
index 0000000..9fa8f1b
--- /dev/null
+++ b/graphics/java/android/graphics/OWNERS
@@ -0,0 +1,13 @@
+# Bug component: 24939
+
+romainguy@google.com
+jreck@google.com
+njawad@google.com
+sumir@google.com
+djsollen@google.com
+scroggo@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/Paint.java b/graphics/java/android/graphics/Paint.java
index 4b6e4d1..f1f9a5f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -698,7 +698,8 @@
      */
     @UnsupportedAppUsage
     public synchronized long getNativeInstance() {
-        long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
+        boolean filter = isFilterBitmap();
+        long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance(filter);
         if (newNativeShader != mNativeShader) {
             mNativeShader = newNativeShader;
             nSetShader(mNativePaint, mNativeShader);
diff --git a/graphics/java/android/graphics/ParcelableColorSpace.java b/graphics/java/android/graphics/ParcelableColorSpace.java
index 3260849..748d66c 100644
--- a/graphics/java/android/graphics/ParcelableColorSpace.java
+++ b/graphics/java/android/graphics/ParcelableColorSpace.java
@@ -22,18 +22,19 @@
 import android.os.Parcelable;
 
 /**
- * A {@link Parcelable} {@link ColorSpace}. In order to enable parceling, the ColorSpace
- * must be either a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb} instance
- * that has an ICC parametric transfer function as returned by {@link Rgb#getTransferParameters()}.
+ * A {@link Parcelable} wrapper for a {@link ColorSpace}. In order to enable parceling, the
+ * ColorSpace must be either a {@link ColorSpace.Named Named} ColorSpace or a
+ * {@link ColorSpace.Rgb} instance that has an ICC parametric transfer function as returned by
+ * {@link ColorSpace.Rgb#getTransferParameters()}.
  */
-public final class ParcelableColorSpace extends ColorSpace implements Parcelable {
+public final class ParcelableColorSpace implements Parcelable {
     private final ColorSpace mColorSpace;
 
     /**
      * Checks if the given ColorSpace is able to be parceled. A ColorSpace can only be
      * parceled if it is a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb}
      * instance that has an ICC parametric transfer function as returned by
-     * {@link Rgb#getTransferParameters()}
+     * {@link ColorSpace.Rgb#getTransferParameters()}
      */
     public static boolean isParcelable(@NonNull ColorSpace colorSpace) {
         if (colorSpace.getId() == ColorSpace.MIN_ID) {
@@ -57,7 +58,6 @@
      * to be parceled. See {@link #isParcelable(ColorSpace)}.
      */
     public ParcelableColorSpace(@NonNull ColorSpace colorSpace) {
-        super(colorSpace.getName(), colorSpace.getModel(), colorSpace.getId());
         mColorSpace = colorSpace;
 
         if (mColorSpace.getId() == ColorSpace.MIN_ID) {
@@ -139,31 +139,6 @@
     };
 
     @Override
-    public boolean isWideGamut() {
-        return mColorSpace.isWideGamut();
-    }
-
-    @Override
-    public float getMinValue(int component) {
-        return mColorSpace.getMinValue(component);
-    }
-
-    @Override
-    public float getMaxValue(int component) {
-        return mColorSpace.getMaxValue(component);
-    }
-
-    @Override
-    public @NonNull float[] toXyz(@NonNull float[] v) {
-        return mColorSpace.toXyz(v);
-    }
-
-    @Override
-    public @NonNull float[] fromXyz(@NonNull float[] v) {
-        return mColorSpace.fromXyz(v);
-    }
-
-    @Override
     public boolean equals(@Nullable Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
@@ -175,10 +150,4 @@
     public int hashCode() {
         return mColorSpace.hashCode();
     }
-
-    /** @hide */
-    @Override
-    long getNativeInstance() {
-        return mColorSpace.getNativeInstance();
-    }
 }
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index dd1be15..199365e 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -207,7 +207,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
                 mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
     }
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/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 63089e2..fb0983a 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -105,10 +105,10 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
         for (int i = 0; i < mInputShaders.length; i++) {
-            nativeShaders[i] = mInputShaders[i].getNativeInstance();
+            nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
         }
 
         return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 7651d01..4d6bead 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -148,7 +148,7 @@
     /**
      *  @hide Only to be used by subclasses in the graphics package.
      */
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return 0;
     }
 
@@ -173,7 +173,7 @@
      * constructed native instance is still valid.
      *  @hide Only to be used by subclasses in the graphics package.
      */
-    protected boolean shouldDiscardNativeInstance() {
+    protected boolean shouldDiscardNativeInstance(boolean filterBitmap) {
         return false;
     }
 
@@ -182,14 +182,14 @@
      * @hide so it can be called by android.graphics.drawable but must not be called from outside
      * the module.
      */
-    public synchronized final long getNativeInstance() {
-        if (shouldDiscardNativeInstance()) {
+    public final synchronized long getNativeInstance(boolean filterFromPaint) {
+        if (shouldDiscardNativeInstance(filterFromPaint)) {
             discardNativeInstanceLocked();
         }
 
         if (mNativeInstance == 0) {
             mNativeInstance = createNativeInstance(mLocalMatrix == null
-                    ? 0 : mLocalMatrix.ni());
+                    ? 0 : mLocalMatrix.ni(), filterFromPaint);
             if (mNativeInstance != 0) {
                 mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
                         this, mNativeInstance);
@@ -199,6 +199,15 @@
     }
 
     /**
+     * @hide so it can be called by android.graphics.drawable but must not be called from outside
+     * the module.
+     */
+    public final long getNativeInstance() {
+        // If the caller has no paint flag for filtering bitmaps, we just pass false
+        return getNativeInstance(false);
+    }
+
+    /**
      * @hide Only to be called by subclasses in the android.graphics package.
      */
     protected static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) {
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 2280780..3a29395 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -133,7 +133,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mCx, mCy, mColorLongs, mPositions,
                 colorSpace().getNativeInstance());
     }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index d6b4f18..48b474d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,6 +25,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UiThread;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.fonts.Font;
@@ -149,8 +150,8 @@
     static final Map<String, Typeface> sSystemFontMap = new HashMap<>();
 
     // DirectByteBuffer object to hold sSystemFontMap's backing memory mapping.
-    @GuardedBy("SYSTEM_FONT_MAP_LOCK")
     static ByteBuffer sSystemFontMapBuffer = null;
+    static SharedMemory sSystemFontMapSharedMemory = null;
 
     // Lock to guard sSystemFontMap and derived default or public typefaces.
     // sStyledCacheLock may be held while this lock is held. Holding them in the reverse order may
@@ -1252,14 +1253,27 @@
      * per process.
      */
     /** @hide */
-    public static void setSystemFontMap(SharedMemory sharedMemory)
+    @UiThread
+    public static void setSystemFontMap(@Nullable SharedMemory sharedMemory)
             throws IOException, ErrnoException {
         if (sSystemFontMapBuffer != null) {
+            // Apps can re-send BIND_APPLICATION message from their code. This is a work around to
+            // detect it and avoid crashing.
+            if (sharedMemory == null || sharedMemory == sSystemFontMapSharedMemory) {
+                return;
+            }
             throw new UnsupportedOperationException(
                     "Once set, buffer-based system font map cannot be updated");
         }
+        sSystemFontMapSharedMemory = sharedMemory;
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setSystemFontMap");
         try {
+            if (sharedMemory == null) {
+                // FontManagerService is not started. This may happen in FACTORY_TEST_LOW_LEVEL
+                // mode for example.
+                loadPreinstalledSystemFontMap();
+                return;
+            }
             sSystemFontMapBuffer = sharedMemory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
             Map<String, Typeface> systemFontMap = deserializeFontMap(sSystemFontMapBuffer);
             setSystemFontMap(systemFontMap);
@@ -1319,6 +1333,7 @@
                 SharedMemory.unmap(sSystemFontMapBuffer);
             }
             sSystemFontMapBuffer = null;
+            sSystemFontMapSharedMemory = null;
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/OWNERS b/graphics/java/android/graphics/drawable/OWNERS
new file mode 100644
index 0000000..6196889
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24939
+
+romainguy@google.com
+jreck@google.com
+njawad@google.com
+sumir@google.com
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6dcc251..9298d9fc 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -84,10 +84,10 @@
  * <dd>Defines the name of this vector drawable.</dd>
  * <dt><code>android:width</code></dt>
  * <dd>Used to define the intrinsic width of the drawable.
- * This support all the dimension units, normally specified with dp.</dd>
+ * This supports all the dimension units, normally specified with dp.</dd>
  * <dt><code>android:height</code></dt>
- * <dd>Used to define the intrinsic height the drawable.
- * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Used to define the intrinsic height of the drawable.
+ * This supports all the dimension units, normally specified with dp.</dd>
  * <dt><code>android:viewportWidth</code></dt>
  * <dd>Used to define the width of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
diff --git a/graphics/java/android/graphics/drawable/shapes/OWNERS b/graphics/java/android/graphics/drawable/shapes/OWNERS
new file mode 100644
index 0000000..6196889
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/shapes/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24939
+
+romainguy@google.com
+jreck@google.com
+njawad@google.com
+sumir@google.com
diff --git a/graphics/java/android/graphics/fonts/OWNERS b/graphics/java/android/graphics/fonts/OWNERS
new file mode 100644
index 0000000..e0a354e
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 24939
+
+romainguy@google.com
+nona@google.com
+siyamed@google.com
diff --git a/graphics/java/android/graphics/pdf/OWNERS b/graphics/java/android/graphics/pdf/OWNERS
new file mode 100644
index 0000000..f04e200
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 24939
+
+romainguy@google.com
+djsollen@google.com
+sumir@google.com
+svetoslavganov@android.com
+svetoslavganov@google.com
+moltmann@google.com
diff --git a/graphics/java/android/graphics/text/OWNERS b/graphics/java/android/graphics/text/OWNERS
new file mode 100644
index 0000000..e0a354e
--- /dev/null
+++ b/graphics/java/android/graphics/text/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 24939
+
+romainguy@google.com
+nona@google.com
+siyamed@google.com
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index add52fa..a9d4094 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -49,6 +49,7 @@
         in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid);
     boolean removeKeyPair(String alias);
     boolean containsKeyPair(String alias);
+    int[] getGrants(String alias);
 
     // APIs used by Settings
     boolean deleteCaCertificate(String alias);
diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java
index 49a4887..7ea9e14 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -17,7 +17,7 @@
 package android.security;
 
 import android.annotation.NonNull;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.security.keymaster.KeymasterDefs;
diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java
index 7c3de8b..3ef4aa5 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.app.compat.CompatChanges;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.security.keystore.BackendBusyException;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
index 69c7a25..56f7ea8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
@@ -17,7 +17,7 @@
 package android.security.keystore2;
 
 import android.annotation.NonNull;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.ArrayUtils;
 import android.security.keystore.KeyProperties;
@@ -41,7 +41,7 @@
  *
  * @hide
  */
-public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+public abstract class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
 
     private static final int BLOCK_SIZE_BYTES = 8;
 
@@ -73,12 +73,22 @@
             public NoPadding() {
                 super(KeymasterDefs.KM_PAD_NONE);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "DESede/ECB/NoPadding";
+            }
         }
 
         public static class PKCS7Padding extends ECB {
             public PKCS7Padding() {
                 super(KeymasterDefs.KM_PAD_PKCS7);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "DESede/ECB/PKCS7Padding";
+            }
         }
     }
 
@@ -91,12 +101,23 @@
             public NoPadding() {
                 super(KeymasterDefs.KM_PAD_NONE);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "DESede/CBC/NoPadding";
+            }
+
         }
 
         public static class PKCS7Padding extends CBC {
             public PKCS7Padding() {
                 super(KeymasterDefs.KM_PAD_PKCS7);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "DESede/CBC/PKCS7Padding";
+            }
         }
     }
 
@@ -288,7 +309,7 @@
         if (parameters != null) {
             for (KeyParameter p : parameters) {
                 if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
-                    returnedIv = p.blob;
+                    returnedIv = p.value.getBlob();
                     break;
                 }
             }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index 2b5f6c3..64da837 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
@@ -64,6 +64,11 @@
         }
 
         @Override
+        protected final String getTransform() {
+            return "AES/GCM/NoPadding";
+        }
+
+        @Override
         protected final void resetAll() {
             mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
             super.resetAll();
@@ -325,7 +330,7 @@
         if (parameters != null) {
             for (KeyParameter p : parameters) {
                 if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
-                    returnedIv = p.blob;
+                    returnedIv = p.value.getBlob();
                     break;
                 }
             }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
index dd943d4..9ad6f3a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
@@ -254,13 +254,13 @@
     private void putAsymmetricCipherImpl(String transformation, String implClass) {
         put("Cipher." + transformation, implClass);
         put("Cipher." + transformation + " SupportedKeyClasses",
-                KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+                KEYSTORE_PRIVATE_KEY_CLASS_NAME);
     }
 
     private void putSignatureImpl(String algorithm, String implClass) {
         put("Signature." + algorithm, implClass);
         put("Signature." + algorithm + " SupportedKeyClasses",
-                KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+                KEYSTORE_PRIVATE_KEY_CLASS_NAME);
     }
 
     public static String[] getSupportedEcdsaSignatureDigests() {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index 18d2692..2ee952c 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -19,7 +19,7 @@
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
@@ -43,6 +43,7 @@
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidKeySpecException;
+import java.security.spec.MGF1ParameterSpec;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
@@ -57,6 +58,8 @@
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.ShortBufferException;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
 import javax.crypto.spec.SecretKeySpec;
 
 /**
@@ -99,6 +102,8 @@
      */
     private Exception mCachedException;
 
+    private Cipher mCipher;
+
     AndroidKeyStoreCipherSpiBase() {
         mOperation = null;
         mEncrypting = false;
@@ -110,6 +115,7 @@
         mAdditionalAuthenticationDataStreamer = null;
         mAdditionalAuthenticationDataStreamerClosed = false;
         mCachedException = null;
+        mCipher = null;
     }
 
     @Override
@@ -117,6 +123,45 @@
             throws InvalidKeyException {
         resetAll();
 
+        if (!(key instanceof AndroidKeyStorePrivateKey
+                || key instanceof AndroidKeyStoreSecretKey)) {
+            try {
+                mCipher = Cipher.getInstance(getTransform());
+                String transform = getTransform();
+
+                if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) {
+                    OAEPParameterSpec spec =
+                            new OAEPParameterSpec("SHA-224", "MGF1",
+                                    new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+                    mCipher.init(opmode, key, spec, random);
+                } else if ("RSA/ECB/OAEPWithSHA-256AndMGF1Padding".equals(transform)) {
+                    OAEPParameterSpec spec =
+                            new OAEPParameterSpec("SHA-256", "MGF1",
+                                    new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+                    mCipher.init(opmode, key, spec, random);
+
+                } else if ("RSA/ECB/OAEPWithSHA-384AndMGF1Padding".equals(transform)) {
+                    OAEPParameterSpec spec =
+                            new OAEPParameterSpec("SHA-384", "MGF1",
+                                    new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+                    mCipher.init(opmode, key, spec, random);
+
+                } else if ("RSA/ECB/OAEPWithSHA-512AndMGF1Padding".equals(transform)) {
+                    OAEPParameterSpec spec =
+                            new OAEPParameterSpec("SHA-512", "MGF1",
+                                    new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+                    mCipher.init(opmode, key, spec, random);
+                } else {
+                    mCipher.init(opmode, key, random);
+                }
+                return;
+            } catch (NoSuchAlgorithmException
+                    | NoSuchPaddingException
+                    | InvalidAlgorithmParameterException e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
         boolean success = false;
         try {
             init(opmode, key, random);
@@ -139,6 +184,17 @@
             SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
         resetAll();
 
+        if (!(key instanceof AndroidKeyStorePrivateKey
+                || key instanceof AndroidKeyStoreSecretKey)) {
+            try {
+                mCipher = Cipher.getInstance(getTransform());
+                mCipher.init(opmode, key, params, random);
+                return;
+            } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
         boolean success = false;
         try {
             init(opmode, key, random);
@@ -157,6 +213,17 @@
             SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
         resetAll();
 
+        if (!(key instanceof AndroidKeyStorePrivateKey
+                || key instanceof AndroidKeyStoreSecretKey)) {
+            try {
+                mCipher = Cipher.getInstance(getTransform());
+                mCipher.init(opmode, key, params, random);
+                return;
+            } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
         boolean success = false;
         try {
             init(opmode, key, random);
@@ -214,6 +281,7 @@
         mAdditionalAuthenticationDataStreamer = null;
         mAdditionalAuthenticationDataStreamerClosed = false;
         mCachedException = null;
+        mCipher = null;
     }
 
     /**
@@ -320,6 +388,10 @@
 
     @Override
     protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+        if (mCipher != null) {
+            return mCipher.update(input, inputOffset, inputLen);
+        }
+
         if (mCachedException != null) {
             return null;
         }
@@ -371,6 +443,9 @@
     @Override
     protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
             int outputOffset) throws ShortBufferException {
+        if (mCipher != null) {
+            return mCipher.update(input, inputOffset, inputLen, output);
+        }
         byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
         if (outputCopy == null) {
             return 0;
@@ -387,6 +462,10 @@
     @Override
     protected final int engineUpdate(ByteBuffer input, ByteBuffer output)
             throws ShortBufferException {
+        if (mCipher != null) {
+            return mCipher.update(input, output);
+        }
+
         if (input == null) {
             throw new NullPointerException("input == null");
         }
@@ -423,6 +502,11 @@
 
     @Override
     protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+        if (mCipher != null) {
+            mCipher.updateAAD(input, inputOffset, inputLen);
+            return;
+        }
+
         if (mCachedException != null) {
             return;
         }
@@ -459,6 +543,11 @@
 
     @Override
     protected final void engineUpdateAAD(ByteBuffer src) {
+        if (mCipher != null) {
+            mCipher.updateAAD(src);
+            return;
+        }
+
         if (src == null) {
             throw new IllegalArgumentException("src == null");
         }
@@ -486,6 +575,10 @@
     @Override
     protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
             throws IllegalBlockSizeException, BadPaddingException {
+        if (mCipher != null) {
+            return mCipher.doFinal(input, inputOffset, inputLen);
+        }
+
         if (mCachedException != null) {
             throw (IllegalBlockSizeException)
                     new IllegalBlockSizeException().initCause(mCachedException);
@@ -522,6 +615,10 @@
     protected final int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
             int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
             BadPaddingException {
+        if (mCipher != null) {
+            return mCipher.doFinal(input, inputOffset, inputLen, output);
+        }
+
         byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
         if (outputCopy == null) {
             return 0;
@@ -538,6 +635,10 @@
     @Override
     protected final int engineDoFinal(ByteBuffer input, ByteBuffer output)
             throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+        if (mCipher != null) {
+            return mCipher.doFinal(input, output);
+        }
+
         if (input == null) {
             throw new NullPointerException("input == null");
         }
@@ -575,6 +676,10 @@
     @Override
     protected final byte[] engineWrap(Key key)
             throws IllegalBlockSizeException, InvalidKeyException {
+        if (mCipher != null) {
+            return mCipher.wrap(key);
+        }
+
         if (mKey == null) {
             throw new IllegalStateException("Not initilized");
         }
@@ -656,6 +761,10 @@
     @Override
     protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
             int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
+        if (mCipher != null) {
+            return mCipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
+        }
+
         if (mKey == null) {
             throw new IllegalStateException("Not initilized");
         }
@@ -902,4 +1011,6 @@
      */
     protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
             KeyParameter[] parameters);
+
+    protected abstract String getTransform();
 }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index 2250c89..8289671 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -17,7 +17,7 @@
 package android.security.keystore2;
 
 import android.annotation.NonNull;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
@@ -44,6 +44,11 @@
         }
 
         @Override
+        protected String getAlgorithm() {
+            return "NONEwithECDSA";
+        }
+
+        @Override
         protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
                 KeyStoreOperation operation) {
             return new TruncateToFieldSizeMessageStreamer(
@@ -113,30 +118,50 @@
         public SHA1() {
             super(KeymasterDefs.KM_DIGEST_SHA1);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA1withECDSA";
+        }
     }
 
     public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
         public SHA224() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA224withECDSA";
+        }
     }
 
     public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
         public SHA256() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA256withECDSA";
+        }
     }
 
     public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
         public SHA384() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA384withECDSA";
+        }
     }
 
     public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
         public SHA512() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA512withECDSA";
+        }
     }
 
     private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
index eea45c2..8475ad9 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
@@ -16,7 +16,7 @@
 
 package android.security.keystore2;
 
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
index 479fd8a..233f352 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
@@ -16,8 +16,8 @@
 
 package android.security.keystore2;
 
-import android.hardware.keymint.KeyParameter;
-import android.hardware.keymint.SecurityLevel;
+import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.SecurityLevel;
 import android.security.KeyStore2;
 import android.security.KeyStoreSecurityLevel;
 import android.security.keymaster.KeymasterArguments;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 61725e3..df0e146 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.keymint.KeyParameter;
-import android.hardware.keymint.SecurityLevel;
+import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.SecurityLevel;
 import android.os.Build;
 import android.security.KeyPairGeneratorSpec;
 import android.security.KeyStore2;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
index afb1054..0c6744f 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
@@ -22,11 +22,11 @@
 /**
  * @hide
  */
-class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
+public class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
 
     private final int mNamespace;
 
-    AndroidKeyStoreLoadStoreParameter(int namespace) {
+    public AndroidKeyStoreLoadStoreParameter(int namespace) {
         mNamespace = namespace;
     }
 
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index b2e32a3..403da18 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -31,9 +31,7 @@
 import android.system.keystore2.KeyMetadata;
 import android.system.keystore2.ResponseCode;
 
-import java.security.KeyFactory;
 import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 import java.security.ProviderException;
 import java.security.PublicKey;
@@ -42,8 +40,6 @@
 import java.security.UnrecoverableKeyException;
 import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
@@ -237,28 +233,11 @@
             throw new UnrecoverableKeyException("Failed to obtain X.509 form of public key."
                     + " Keystore has no public certificate stored.");
         }
-        final byte[] x509EncodedPublicKey = metadata.certificate;
+        final byte[] x509PublicCert = metadata.certificate;
 
-        String jcaKeyAlgorithm;
-        try {
-            jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
-                    algorithm);
-        } catch (IllegalArgumentException e) {
-            throw (UnrecoverableKeyException)
-                    new UnrecoverableKeyException("Failed to load private key")
-                            .initCause(e);
-        }
+        PublicKey publicKey = AndroidKeyStoreSpi.toCertificate(x509PublicCert).getPublicKey();
 
-        PublicKey publicKey;
-        try {
-            KeyFactory keyFactory = KeyFactory.getInstance(jcaKeyAlgorithm);
-            publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedPublicKey));
-        } catch (NoSuchAlgorithmException e) {
-            throw new ProviderException(
-                    "Failed to obtain " + jcaKeyAlgorithm + " KeyFactory", e);
-        } catch (InvalidKeySpecException e) {
-            throw new ProviderException("Invalid X.509 encoding of public key", e);
-        }
+        String jcaKeyAlgorithm = publicKey.getAlgorithm();
 
         KeyStoreSecurityLevel securityLevel = iSecurityLevel;
         if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
@@ -358,7 +337,7 @@
 
         KeyDescriptor descriptor = new KeyDescriptor();
         if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
-            descriptor.nspace = 0; // ignored;
+            descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
             descriptor.domain = Domain.APP;
         } else {
             descriptor.nspace = namespace;
@@ -387,10 +366,10 @@
         for (Authorization a : response.metadata.authorizations) {
             switch (a.keyParameter.tag) {
                 case KeymasterDefs.KM_TAG_ALGORITHM:
-                    keymasterAlgorithm = a.keyParameter.integer;
+                    keymasterAlgorithm = a.keyParameter.value.getAlgorithm();
                     break;
                 case KeymasterDefs.KM_TAG_DIGEST:
-                    if (keymasterDigest == -1) keymasterDigest = a.keyParameter.integer;
+                    if (keymasterDigest == -1) keymasterDigest = a.keyParameter.value.getDigest();
                     break;
             }
         }
@@ -407,7 +386,7 @@
                 keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
             return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
                     new KeyStoreSecurityLevel(response.iSecurityLevel),
-                    keymasterAlgorithm);
+                    keymasterAlgorithm).getPrivateKey();
         } else {
             throw new UnrecoverableKeyException("Key algorithm unknown");
         }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index 2686ddc..6ff9432 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeymasterUtils;
@@ -158,7 +158,7 @@
     }
 
     /**
-     * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
+     * RSA cipher with OAEP encryption padding.
      */
     abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
 
@@ -316,6 +316,25 @@
         protected final int getAdditionalEntropyAmountForFinish() {
             return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
         }
+
+        @Override
+        protected final String getTransform() {
+            switch (mKeymasterDigest) {
+                case KeymasterDefs.KM_DIGEST_SHA1:
+                    return "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
+                case KeymasterDefs.KM_DIGEST_SHA_2_224:
+                    return "RSA/ECB/OAEPWithSHA-224AndMGF1Padding";
+                case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                    return "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
+                case KeymasterDefs.KM_DIGEST_SHA_2_384:
+                    return "RSA/ECB/OAEPWithSHA-384AndMGF1Padding";
+                case KeymasterDefs.KM_DIGEST_SHA_2_512:
+                    return "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
+                default:
+                    return "RSA/ECB/OAEPPadding";
+            }
+        }
+
     }
 
     public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
@@ -358,6 +377,11 @@
     }
 
     @Override
+    protected String getTransform() {
+        return "RSA/ECB/" + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding);
+    }
+
+    @Override
     protected final void initKey(int opmode, Key key) throws InvalidKeyException {
         if (key == null) {
             throw new InvalidKeyException("Unsupported key: null");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
index 444dad4..931c2f8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
@@ -17,7 +17,7 @@
 package android.security.keystore2;
 
 import android.annotation.NonNull;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyProperties;
 
@@ -48,42 +48,70 @@
         public NONEWithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_NONE);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "NONEwithRSA";
+        }
     }
 
     public static final class MD5WithPKCS1Padding extends PKCS1Padding {
         public MD5WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_MD5);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "MD5withRSA";
+        }
     }
 
     public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
         public SHA1WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_SHA1);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA1withRSA";
+        }
     }
 
     public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
         public SHA224WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA224withRSA";
+        }
     }
 
     public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
         public SHA256WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA256withRSA";
+        }
     }
 
     public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
         public SHA384WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA384withRSA";
+        }
     }
 
     public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
         public SHA512WithPKCS1Padding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA512withRSA";
+        }
     }
 
     abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
@@ -103,30 +131,50 @@
         public SHA1WithPSSPadding() {
             super(KeymasterDefs.KM_DIGEST_SHA1);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA1withRSA/PSS";
+        }
     }
 
     public static final class SHA224WithPSSPadding extends PSSPadding {
         public SHA224WithPSSPadding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA224withRSA/PSS";
+        }
     }
 
     public static final class SHA256WithPSSPadding extends PSSPadding {
         public SHA256WithPSSPadding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA256withRSA/PSS";
+        }
     }
 
     public static final class SHA384WithPSSPadding extends PSSPadding {
         public SHA384WithPSSPadding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA384withRSA/PSS";
+        }
     }
 
     public static final class SHA512WithPSSPadding extends PSSPadding {
         public SHA512WithPSSPadding() {
             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
         }
+        @Override
+        protected String getAlgorithm() {
+            return "SHA512withRSA/PSS";
+        }
     }
 
     private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index 9d3b970..74503e1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -102,7 +102,8 @@
                         insideSecureHardware =
                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
                         securityLevel = a.securityLevel;
-                        origin = KeyProperties.Origin.fromKeymaster(a.keyParameter.integer);
+                        origin = KeyProperties.Origin.fromKeymaster(
+                                a.keyParameter.value.getOrigin());
                         break;
                     case KeymasterDefs.KM_TAG_KEY_SIZE:
                         long keySizeUnsigned = KeyStore2ParameterUtils.getUnsignedInt(a);
@@ -113,45 +114,51 @@
                         keySize = (int) keySizeUnsigned;
                         break;
                     case KeymasterDefs.KM_TAG_PURPOSE:
-                        purposes |= KeyProperties.Purpose.fromKeymaster(a.keyParameter.integer);
+                        purposes |= KeyProperties.Purpose.fromKeymaster(
+                                a.keyParameter.value.getKeyPurpose());
                         break;
                     case KeymasterDefs.KM_TAG_PADDING:
+                        int paddingMode = a.keyParameter.value.getPaddingMode();
                         try {
-                            if (a.keyParameter.integer == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN
-                                    || a.keyParameter.integer == KeymasterDefs.KM_PAD_RSA_PSS) {
+                            if (paddingMode == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN
+                                    || paddingMode == KeymasterDefs.KM_PAD_RSA_PSS) {
                                 @KeyProperties.SignaturePaddingEnum String padding =
                                         KeyProperties.SignaturePadding.fromKeymaster(
-                                                a.keyParameter.integer);
+                                                paddingMode);
                                 signaturePaddingsList.add(padding);
                             } else {
                                 @KeyProperties.EncryptionPaddingEnum String jcaPadding =
                                         KeyProperties.EncryptionPadding.fromKeymaster(
-                                                a.keyParameter.integer);
+                                                paddingMode);
                                 encryptionPaddingsList.add(jcaPadding);
                             }
                         } catch (IllegalArgumentException e) {
                             throw new ProviderException("Unsupported padding: "
-                                                + a.keyParameter.integer);
+                                                + paddingMode);
                         }
                         break;
                     case KeymasterDefs.KM_TAG_DIGEST:
-                        digestsList.add(KeyProperties.Digest.fromKeymaster(a.keyParameter.integer));
+                        digestsList.add(KeyProperties.Digest.fromKeymaster(
+                                a.keyParameter.value.getDigest()));
                         break;
                     case KeymasterDefs.KM_TAG_BLOCK_MODE:
                         blockModesList.add(
-                                KeyProperties.BlockMode.fromKeymaster(a.keyParameter.integer)
+                                KeyProperties.BlockMode.fromKeymaster(
+                                        a.keyParameter.value.getBlockMode())
                         );
                         break;
                     case KeymasterDefs.KM_TAG_USER_AUTH_TYPE:
+                        int authenticatorType = a.keyParameter.value.getHardwareAuthenticatorType();
                         if (KeyStore2ParameterUtils.isSecureHardware(a.securityLevel)) {
-                            keymasterHwEnforcedUserAuthenticators = a.keyParameter.integer;
+                            keymasterHwEnforcedUserAuthenticators = authenticatorType;
                         } else {
-                            keymasterSwEnforcedUserAuthenticators = a.keyParameter.integer;
+                            keymasterSwEnforcedUserAuthenticators = authenticatorType;
                         }
                         break;
                     case KeymasterDefs.KM_TAG_USER_SECURE_ID:
                         keymasterSecureUserIds.add(
-                                KeymasterArguments.toUint64(a.keyParameter.longInteger));
+                                KeymasterArguments.toUint64(
+                                        a.keyParameter.value.getLongInteger()));
                         break;
                     case KeymasterDefs.KM_TAG_ACTIVE_DATETIME:
                         keyValidityStart = KeyStore2ParameterUtils.getDate(a);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
index a168f8f..96da1e0 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
@@ -18,7 +18,7 @@
 
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
@@ -30,10 +30,12 @@
 import java.nio.ByteBuffer;
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.ProviderException;
 import java.security.PublicKey;
 import java.security.SecureRandom;
+import java.security.Signature;
 import java.security.SignatureException;
 import java.security.SignatureSpi;
 import java.util.ArrayList;
@@ -76,6 +78,13 @@
      */
     private Exception mCachedException;
 
+    /**
+     * This signature object is used for public key operations, i.e, signatrue verification.
+     * The Android Keystore backend does not perform public key operations and defers to the
+     * Highest priority provider.
+     */
+    private Signature mSignature;
+
     AndroidKeyStoreSignatureSpiBase() {
         mOperation = null;
         mOperationChallenge = 0;
@@ -84,6 +93,7 @@
         appRandom = null;
         mMessageStreamer = null;
         mCachedException = null;
+        mSignature = null;
     }
 
     @Override
@@ -123,27 +133,13 @@
     protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
         resetAll();
 
-        boolean success = false;
         try {
-            if (publicKey == null) {
-                throw new InvalidKeyException("Unsupported key: null");
-            }
-            AndroidKeyStoreKey keystoreKey;
-            if (publicKey instanceof AndroidKeyStorePublicKey) {
-                keystoreKey = (AndroidKeyStorePublicKey) publicKey;
-            } else {
-                throw new InvalidKeyException("Unsupported public key type: " + publicKey);
-            }
-            mSigning = false;
-            initKey(keystoreKey);
-            appRandom = null;
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
+            mSignature = Signature.getInstance(getAlgorithm());
+        } catch (NoSuchAlgorithmException e) {
+            throw new InvalidKeyException(e);
         }
+
+        mSignature.initVerify(publicKey);
     }
 
     /**
@@ -251,6 +247,11 @@
 
     @Override
     protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+        if (mSignature != null) {
+            mSignature.update(b, off, len);
+            return;
+        }
+
         if (mCachedException != null) {
             throw new SignatureException(mCachedException);
         }
@@ -337,39 +338,10 @@
 
     @Override
     protected final boolean engineVerify(byte[] signature) throws SignatureException {
-        if (mCachedException != null) {
-            throw new SignatureException(mCachedException);
+        if (mSignature != null) {
+            return mSignature.verify(signature);
         }
-
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException e) {
-            throw new SignatureException(e);
-        }
-
-        boolean verified;
-        try {
-            byte[] output = mMessageStreamer.doFinal(
-                    EmptyArray.BYTE, 0, 0,
-                    signature);
-            if (output.length != 0) {
-                throw new ProviderException(
-                        "Signature verification unexpected produced output: " + output.length
-                        + " bytes");
-            }
-            verified = true;
-        } catch (KeyStoreException e) {
-            switch (e.getErrorCode()) {
-                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
-                    verified = false;
-                    break;
-                default:
-                    throw new SignatureException(e);
-            }
-        }
-
-        resetWhilePreservingInitState();
-        return verified;
+        throw new IllegalStateException("Not initialised.");
     }
 
     @Override
@@ -392,6 +364,13 @@
     }
 
     /**
+     * Implementations need to report the algorithm they implement so that we can delegate to the
+     * highest priority provider.
+     * @return Algorithm string.
+     */
+    protected abstract String getAlgorithm();
+
+    /**
      * Returns {@code true} if this signature is initialized for signing, {@code false} if this
      * signature is initialized for verification.
      */
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 9790a4a..5e7f648 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -18,9 +18,9 @@
 
 import android.annotation.NonNull;
 import android.hardware.biometrics.BiometricManager;
-import android.hardware.keymint.HardwareAuthenticatorType;
-import android.hardware.keymint.KeyParameter;
-import android.hardware.keymint.SecurityLevel;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.SecurityLevel;
 import android.security.GateKeeper;
 import android.security.KeyStore2;
 import android.security.KeyStoreParameter;
@@ -219,7 +219,7 @@
         return null;
     }
 
-    private static X509Certificate toCertificate(byte[] bytes) {
+    static X509Certificate toCertificate(byte[] bytes) {
         try {
             final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
             return (X509Certificate) certFactory.generateCertificate(
@@ -250,13 +250,10 @@
             return null;
         }
 
-
-        // TODO add modification time to key metadata.
-        return null;
-        // if (response.metadata.modificationTime == -1) {
-        //     return null;
-        // }
-        // return new Date(response.metadata.modificationTime);
+        if (response.metadata.modificationTimeMs == -1) {
+            return null;
+        }
+        return new Date(response.metadata.modificationTimeMs);
     }
 
     @Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index a2d4528..5c048a1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameter;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.ArrayUtils;
 import android.security.keystore.KeyProperties;
@@ -42,7 +42,7 @@
  *
  * @hide
  */
-class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+abstract class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
 
     abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
         protected ECB(int keymasterPadding) {
@@ -53,12 +53,22 @@
             public NoPadding() {
                 super(KeymasterDefs.KM_PAD_NONE);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "AES/ECB/NoPadding";
+            }
         }
 
         public static class PKCS7Padding extends ECB {
             public PKCS7Padding() {
                 super(KeymasterDefs.KM_PAD_PKCS7);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "AES/ECB/PKCS7Padding";
+            }
         }
     }
 
@@ -71,12 +81,22 @@
             public NoPadding() {
                 super(KeymasterDefs.KM_PAD_NONE);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "AES/CBC/NoPadding";
+            }
         }
 
         public static class PKCS7Padding extends CBC {
             public PKCS7Padding() {
                 super(KeymasterDefs.KM_PAD_PKCS7);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "AES/CBC/PKCS7Padding";
+            }
         }
     }
 
@@ -89,6 +109,11 @@
             public NoPadding() {
                 super(KeymasterDefs.KM_PAD_NONE);
             }
+
+            @Override
+            protected final String getTransform() {
+                return "AES/CTR/NoPadding";
+            }
         }
     }
 
@@ -275,7 +300,7 @@
         if (parameters != null) {
             for (KeyParameter p : parameters) {
                 if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
-                    returnedIv = p.blob;
+                    returnedIv = p.value.getBlob();
                     break;
                 }
             }
diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
index 8fa532b..4c8ab8d 100644
--- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
+++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
@@ -18,8 +18,10 @@
 
 import android.annotation.NonNull;
 import android.hardware.biometrics.BiometricManager;
-import android.hardware.keymint.KeyParameter;
-import android.hardware.keymint.SecurityLevel;
+import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameterValue;
+import android.hardware.security.keymint.SecurityLevel;
+import android.hardware.security.keymint.Tag;
 import android.security.GateKeeper;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyProperties;
@@ -50,7 +52,7 @@
         }
         KeyParameter p = new KeyParameter();
         p.tag = tag;
-        p.boolValue = true;
+        p.value = KeyParameterValue.boolValue(true);
         return p;
     }
 
@@ -62,14 +64,40 @@
      * @hide
      */
     static @NonNull KeyParameter makeEnum(int tag, int v) {
-        int type = KeymasterDefs.getTagType(tag);
-        if (type != KeymasterDefs.KM_ENUM && type != KeymasterDefs.KM_ENUM_REP) {
-            throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag);
+        KeyParameter kp = new KeyParameter();
+        kp.tag = tag;
+        switch (tag) {
+            case Tag.PURPOSE:
+                kp.value = KeyParameterValue.keyPurpose(v);
+                break;
+            case Tag.ALGORITHM:
+                kp.value = KeyParameterValue.algorithm(v);
+                break;
+            case Tag.BLOCK_MODE:
+                kp.value = KeyParameterValue.blockMode(v);
+                break;
+            case Tag.DIGEST:
+                kp.value = KeyParameterValue.digest(v);
+                break;
+            case Tag.EC_CURVE:
+                kp.value = KeyParameterValue.ecCurve(v);
+                break;
+            case Tag.ORIGIN:
+                kp.value = KeyParameterValue.origin(v);
+                break;
+            case Tag.PADDING:
+                kp.value = KeyParameterValue.paddingMode(v);
+                break;
+            case Tag.USER_AUTH_TYPE:
+                kp.value = KeyParameterValue.hardwareAuthenticatorType(v);
+                break;
+            case Tag.HARDWARE_TYPE:
+                kp.value = KeyParameterValue.securityLevel(v);
+                break;
+            default:
+                throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag);
         }
-        KeyParameter p = new KeyParameter();
-        p.tag = tag;
-        p.integer = v;
-        return p;
+        return kp;
     }
 
     /**
@@ -86,7 +114,7 @@
         }
         KeyParameter p = new KeyParameter();
         p.tag = tag;
-        p.integer = v;
+        p.value = KeyParameterValue.integer(v);
         return p;
     }
 
@@ -104,7 +132,7 @@
         }
         KeyParameter p = new KeyParameter();
         p.tag = tag;
-        p.longInteger = v;
+        p.value = KeyParameterValue.longInteger(v);
         return p;
     }
 
@@ -121,7 +149,7 @@
         }
         KeyParameter p = new KeyParameter();
         p.tag = tag;
-        p.blob = b;
+        p.value = KeyParameterValue.blob(b);
         return p;
     }
 
@@ -138,9 +166,10 @@
         }
         KeyParameter p = new KeyParameter();
         p.tag = tag;
-        p.longInteger = date.getTime();
-        if (p.longInteger < 0) {
-            throw new IllegalArgumentException("Date tag value out of range: " + p.longInteger);
+        p.value = KeyParameterValue.dateTime(date.getTime());
+        if (p.value.getDateTime() < 0) {
+            throw new IllegalArgumentException("Date tag value out of range: "
+                    + p.value.getDateTime());
         }
         return p;
     }
@@ -160,24 +189,24 @@
             throw new IllegalArgumentException("Not an int tag: " + param.keyParameter.tag);
         }
         // KM_UINT is 32 bits wide so we must suppress sign extension.
-        return ((long) param.keyParameter.integer) & 0xffffffffL;
+        return ((long) param.keyParameter.value.getInteger()) & 0xffffffffL;
     }
 
     static @NonNull Date getDate(@NonNull Authorization param) {
         if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_DATE) {
             throw new IllegalArgumentException("Not a date tag: " + param.keyParameter.tag);
         }
-        if (param.keyParameter.longInteger < 0) {
+        if (param.keyParameter.value.getDateTime() < 0) {
             throw new IllegalArgumentException("Date Value too large: "
-                    + param.keyParameter.longInteger);
+                    + param.keyParameter.value.getDateTime());
         }
-        return new Date(param.keyParameter.longInteger);
+        return new Date(param.keyParameter.value.getDateTime());
     }
 
     static void forEachSetFlag(int flags, Consumer<Integer> consumer) {
         int offset = 0;
         while (flags != 0) {
-            if ((flags & 1) == 0) {
+            if ((flags & 1) == 1) {
                 consumer.accept(1 << offset);
             }
             offset += 1;
diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
index 3b11854..f87a3d2 100644
--- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
@@ -57,7 +57,7 @@
         for (Authorization p : key.getAuthorizations()) {
             switch(p.keyParameter.tag) {
                 case KeymasterDefs.KM_TAG_USER_SECURE_ID:
-                    keySids.add(p.keyParameter.longInteger);
+                    keySids.add(p.keyParameter.value.getLongInteger());
                     break;
                 default:
                     break;
diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS
index 063d459..2c61df9 100644
--- a/libs/WindowManager/OWNERS
+++ b/libs/WindowManager/OWNERS
@@ -1,3 +1,3 @@
 set noparent
 
-include ../../services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index ad87025..ed5d2e1 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"/>">
+        android:alpha="0"/>
 
-    <com.android.wm.shell.splitscreen.DividerHandleView
+    <com.android.wm.shell.common.split.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/layout/split_divider.xml b/libs/WindowManager/Shell/res/layout/split_divider.xml
index 341fe61..7f583f3 100644
--- a/libs/WindowManager/Shell/res/layout/split_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/split_divider.xml
@@ -24,4 +24,10 @@
         android:id="@+id/docked_divider_background"
         android:background="@color/docked_divider_background"/>
 
+    <com.android.wm.shell.common.split.DividerHandleView
+        style="@style/DockedDividerHandle"
+        android:id="@+id/docked_divider_handle"
+        android:contentDescription="@string/accessibility_divider"
+        android:background="@null"/>
+
 </com.android.wm.shell.common.split.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/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index f0eae97..807e5af 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -42,16 +42,4 @@
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
      when the PIP menu is shown in center. -->
     <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
-
-    <!-- Gravity of letterboxed apps in portrait screen orientation.
-         Can be Gravity.TOP, Gravity.CENTER or Gravity.BOTTOM.
-         Any other value will result in runtime exception for a letterboxed activity.
-         Default is Gravity.TOP. -->
-    <integer name="config_letterboxPortraitGravity">0x00000030</integer>
-
-    <!-- Gravity of letterboxed apps in landscape screen orientation.
-         Can be Gravity.LEFT, Gravity.CENTER or Gravity.RIGHT.
-         Any other value will result in runtime exception for a letterboxed activity.
-         Default is Gravity.CENTER. -->
-    <integer name="config_letterboxLandscapeGravity">0x00000011</integer>
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 4f13b83..63d3118 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -20,8 +20,9 @@
 import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
 
 import android.app.ActivityManager;
-import android.util.ArraySet;
+import android.graphics.Point;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.SurfaceControl;
 
 import androidx.annotation.NonNull;
@@ -40,7 +41,7 @@
 
     private final SyncTransactionQueue mSyncQueue;
 
-    private final ArraySet<Integer> mTasks = new ArraySet<>();
+    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
 
     public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
         mSyncQueue = syncQueue;
@@ -48,39 +49,44 @@
 
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
-        synchronized (mTasks) {
-            if (mTasks.contains(taskInfo.taskId)) {
-                throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
-            }
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
-                    taskInfo.taskId);
-            mTasks.add(taskInfo.taskId);
-            mSyncQueue.runInSync(t -> {
-                // Reset several properties back to fullscreen (PiP, for example, leaves all these
-                // properties in a bad state).
-                t.setWindowCrop(leash, null);
-                t.setPosition(leash, 0, 0);
-                // TODO(shell-transitions): Eventually set everything in transition so there's no
-                //                          SF Transaction here.
-                if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
-                    t.setAlpha(leash, 1f);
-                    t.setMatrix(leash, 1, 0, 0, 1);
-                    t.show(leash);
-                }
-            });
+        if (mLeashByTaskId.get(taskInfo.taskId) != null) {
+            throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
         }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
+                taskInfo.taskId);
+        mLeashByTaskId.put(taskInfo.taskId, leash);
+        final Point positionInParent = taskInfo.positionInParent;
+        mSyncQueue.runInSync(t -> {
+            // Reset several properties back to fullscreen (PiP, for example, leaves all these
+            // properties in a bad state).
+            t.setWindowCrop(leash, null);
+            t.setPosition(leash, positionInParent.x, positionInParent.y);
+            // TODO(shell-transitions): Eventually set everything in transition so there's no
+            //                          SF Transaction here.
+            if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
+                t.setAlpha(leash, 1f);
+                t.setMatrix(leash, 1, 0, 0, 1);
+                t.show(leash);
+            }
+        });
+    }
+
+    @Override
+    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+        final Point positionInParent = taskInfo.positionInParent;
+        mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
     }
 
     @Override
     public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
-        synchronized (mTasks) {
-            if (!mTasks.remove(taskInfo.taskId)) {
-                Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
-                return;
-            }
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
-                    taskInfo.taskId);
+        if (mLeashByTaskId.get(taskInfo.taskId) == null) {
+            Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+            return;
         }
+        mLeashByTaskId.remove(taskInfo.taskId);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
+                taskInfo.taskId);
     }
 
     @Override
@@ -88,7 +94,7 @@
         final String innerPrefix = prefix + "  ";
         final String childPrefix = innerPrefix + "  ";
         pw.println(prefix + this);
-        pw.println(innerPrefix + mTasks.size() + " Tasks");
+        pw.println(innerPrefix + mLeashByTaskId.size() + " Tasks");
     }
 
     @Override
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..4a8b450
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell;
+
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+import android.window.DisplayAreaAppearedInfo;
+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);
+        List<DisplayAreaAppearedInfo> infos = registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
+        for (int i = infos.size() - 1; i >= 0; --i) {
+            onDisplayAreaAppeared(infos.get(i).getDisplayAreaInfo(), infos.get(i).getLeash());
+        }
+    }
+
+    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 45948dd..2f2168f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
@@ -16,15 +16,12 @@
 
 package com.android.wm.shell;
 
-import android.view.Gravity;
-
 import com.android.wm.shell.apppairs.AppPairs;
 import com.android.wm.shell.common.annotations.ExternalThread;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
-import com.android.wm.shell.letterbox.LetterboxConfigController;
 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;
@@ -36,29 +33,26 @@
  */
 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;
     private final ShellTaskOrganizer mShellTaskOrganizer;
     private final Optional<AppPairs> mAppPairsOptional;
-    private final LetterboxConfigController mLetterboxConfigController;
 
     public ShellCommandHandler(
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<Pip> pipOptional,
             Optional<OneHanded> oneHandedOptional,
             Optional<HideDisplayCutout> hideDisplayCutout,
-            Optional<AppPairs> appPairsOptional,
-            LetterboxConfigController letterboxConfigController) {
+            Optional<AppPairs> appPairsOptional) {
         mShellTaskOrganizer = shellTaskOrganizer;
-        mSplitScreenOptional = splitScreenOptional;
+        mLegacySplitScreenOptional = legacySplitScreenOptional;
         mPipOptional = pipOptional;
         mOneHandedOptional = oneHandedOptional;
         mHideDisplayCutout = hideDisplayCutout;
         mAppPairsOptional = appPairsOptional;
-        mLetterboxConfigController = letterboxConfigController;
     }
 
     /** Dumps WM Shell internal state. */
@@ -68,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();
@@ -85,14 +79,6 @@
             return false;
         }
         switch (args[1]) {
-            case "set-letterbox-portrait-gravity":
-                return runSetLetterboxPortraitGravity(args, pw);
-            case "get-letterbox-portrait-gravity":
-                return runGetLetterboxPortraitGravity(pw);
-            case "set-letterbox-landscape-gravity":
-                return runSetLetterboxLandscapeGravity(args, pw);
-            case "get-letterbox-landscape-gravity":
-                return runGetLetterboxLandscapeGravity(pw);
             case "pair":
                 return runPair(args, pw);
             case "unpair":
@@ -104,92 +90,6 @@
         }
     }
 
-    private boolean runSetLetterboxPortraitGravity(String[] args, PrintWriter pw) {
-        if (args.length < 3) {
-            // First two arguments are "WMShell" and command name.
-            pw.println("Error: reset, TOP, CENTER or BOTTOM should be provided as an argument");
-            return true;
-        }
-        switch (args[2]) {
-            case "reset":
-                mLetterboxConfigController.resetPortraitGravity();
-                break;
-            case "TOP":
-                mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-                break;
-            case "CENTER":
-                mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
-                break;
-            case "BOTTOM":
-                mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
-                break;
-            default:
-                pw.println("Error: expected reset, TOP, CENTER or BOTTOM but got " + args[2]);
-        }
-        return true;
-    }
-
-    private boolean runGetLetterboxPortraitGravity(PrintWriter pw) {
-        final int gravity = mLetterboxConfigController.getPortraitGravity();
-        switch (gravity) {
-            case Gravity.TOP:
-                pw.println("TOP");
-                break;
-            case Gravity.CENTER:
-                pw.println("CENTER");
-                break;
-            case Gravity.BOTTOM:
-                pw.println("BOTTOM");
-                break;
-            default:
-                throw new AssertionError("Unexpected gravity: " + gravity);
-        }
-        return true;
-    }
-
-    private boolean runSetLetterboxLandscapeGravity(String[] args, PrintWriter pw) {
-        if (args.length < 3) {
-            // First two arguments are "WMShell" and command name.
-            pw.println("Error: reset, LEFT, CENTER or RIGHT should be provided as an argument");
-            return false;
-        }
-        switch (args[2]) {
-            case "reset":
-                mLetterboxConfigController.resetLandscapeGravity();
-                break;
-            case "LEFT":
-                mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
-                break;
-            case "CENTER":
-                mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
-                break;
-            case "RIGHT":
-                mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
-                break;
-            default:
-                pw.println(
-                        "Error: expected reset, LEFT, CENTER or RIGHT but got " + args[2]);
-        }
-        return true;
-    }
-
-    private boolean runGetLetterboxLandscapeGravity(PrintWriter pw) {
-        final int gravity = mLetterboxConfigController.getLandscapeGravity();
-        switch (gravity) {
-            case Gravity.LEFT:
-                pw.println("LEFT");
-                break;
-            case Gravity.CENTER:
-                pw.println("CENTER");
-                break;
-            case Gravity.RIGHT:
-                pw.println("RIGHT");
-                break;
-            default:
-                throw new AssertionError("Unexpected gravity: " + gravity);
-        }
-        return true;
-    }
 
     private boolean runPair(String[] args, PrintWriter pw) {
         if (args.length < 4) {
@@ -220,12 +120,6 @@
         pw.println("      Print this help text.");
         pw.println("  <no arguments provided>");
         pw.println("    Dump Window Manager Shell internal state");
-        pw.println("  set-letterbox-portrait-gravity [reset|TOP|CENTER|BOTTOM]");
-        pw.println("  get-letterbox-portrait-gravity");
-        pw.println("    Set, reset or print letterbox gravity for portrait screen mode.");
-        pw.println("  set-letterbox-landscape-gravity [reset|LEFT|CENTER|RIGHT]");
-        pw.println("  get-letterbox-landscape-gravity");
-        pw.println("    Set, reset or print letterbox gravity for landscape screen mode.");
         pw.println("  pair <taskId1> <taskId2>");
         pw.println("  unpair <taskId>");
         pw.println("    Pairs/unpairs tasks with given ids.");
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 94555de..f4c617e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
@@ -17,14 +17,12 @@
 package com.android.wm.shell;
 
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX;
 
 import com.android.wm.shell.apppairs.AppPairs;
 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.letterbox.LetterboxTaskListener;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -36,25 +34,25 @@
     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 LetterboxTaskListener mLetterboxTaskListener;
     private final FullscreenTaskListener mFullscreenTaskListener;
+    private final Transitions mTransitions;
 
     public ShellInit(DisplayImeController displayImeController,
             DragAndDropController dragAndDropController,
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<AppPairs> appPairsOptional,
-            LetterboxTaskListener letterboxTaskListener,
-            FullscreenTaskListener fullscreenTaskListener) {
+            FullscreenTaskListener fullscreenTaskListener,
+            Transitions transitions) {
         mDisplayImeController = displayImeController;
         mDragAndDropController = dragAndDropController;
         mShellTaskOrganizer = shellTaskOrganizer;
-        mSplitScreenOptional = splitScreenOptional;
+        mLegacySplitScreenOptional = legacySplitScreenOptional;
         mAppPairsOptional = appPairsOptional;
-        mLetterboxTaskListener = letterboxTaskListener;
         mFullscreenTaskListener = fullscreenTaskListener;
+        mTransitions = transitions;
     }
 
     @ExternalThread
@@ -63,14 +61,16 @@
         mDisplayImeController.startMonitorDisplays();
 
         mShellTaskOrganizer.addListenerForType(
-                mLetterboxTaskListener, TASK_LISTENER_TYPE_LETTERBOX);
-        mShellTaskOrganizer.addListenerForType(
                 mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
         // Register the shell organizer
         mShellTaskOrganizer.registerOrganizer();
 
         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/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 174c16a..faa4a0e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -31,23 +31,19 @@
 import android.os.IBinder;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizerController;
+import android.window.StartingWindowInfo;
 import android.window.TaskAppearedInfo;
 import android.window.TaskOrganizer;
 
-import androidx.annotation.BinderThread;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
 
 import java.io.PrintWriter;
@@ -67,14 +63,12 @@
     public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
     public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
     public static final int TASK_LISTENER_TYPE_PIP = -4;
-    public static final int TASK_LISTENER_TYPE_LETTERBOX = -5;
 
     @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
             TASK_LISTENER_TYPE_UNDEFINED,
             TASK_LISTENER_TYPE_FULLSCREEN,
             TASK_LISTENER_TYPE_MULTI_WINDOW,
             TASK_LISTENER_TYPE_PIP,
-            TASK_LISTENER_TYPE_LETTERBOX,
     })
     public @interface TaskListenerType {}
 
@@ -105,28 +99,21 @@
     /** @see #setPendingLaunchCookieListener */
     private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();
 
-    // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
-    private final Transitions mTransitions;
-
     private final Object mLock = new Object();
     private final StartingSurfaceDrawer mStartingSurfaceDrawer;
 
-    public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool,
-            ShellExecutor mainExecutor, ShellExecutor animExecutor, Context context) {
-        this(null, syncQueue, transactionPool, mainExecutor, animExecutor, context);
+    public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) {
+        this(null, mainExecutor, context);
     }
 
     @VisibleForTesting
-    ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
-            SyncTransactionQueue syncQueue, TransactionPool transactionPool,
-            ShellExecutor mainExecutor, ShellExecutor animExecutor, Context context) {
+    ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, ShellExecutor mainExecutor,
+            Context context) {
         super(taskOrganizerController, mainExecutor);
-        mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
-        if (Transitions.ENABLE_SHELL_TRANSITIONS) mTransitions.register(this);
         // TODO(b/131727939) temporarily live here, the starting surface drawer should be controlled
         //  by a controller, that class should be create while porting
         //  ActivityRecord#addStartingWindow to WMShell.
-        mStartingSurfaceDrawer = new StartingSurfaceDrawer(context);
+        mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, mainExecutor);
     }
 
     @Override
@@ -243,13 +230,13 @@
     }
 
     @Override
-    public void addStartingWindow(RunningTaskInfo taskInfo, IBinder appToken) {
-        mStartingSurfaceDrawer.addStartingWindow(taskInfo, appToken);
+    public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
+        mStartingSurfaceDrawer.addStartingWindow(info, appToken);
     }
 
     @Override
-    public void removeStartingWindow(RunningTaskInfo taskInfo) {
-        mStartingSurfaceDrawer.removeStartingWindow(taskInfo);
+    public void removeStartingWindow(int taskId) {
+        mStartingSurfaceDrawer.removeStartingWindow(taskId);
     }
 
     @Override
@@ -275,6 +262,12 @@
         synchronized (mLock) {
             ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
             final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
+            if (data == null) {
+                // TODO(b/171749427): It means onTaskInfoChanged send before onTaskAppeared or
+                //  after onTaskVanished, it should be fixed in controller side.
+                return;
+            }
+
             final TaskListener oldListener = getTaskListener(data.getTaskInfo());
             final TaskListener newListener = getTaskListener(taskInfo);
             mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
@@ -377,9 +370,7 @@
     static @TaskListenerType int taskInfoToTaskListenerType(RunningTaskInfo runningTaskInfo) {
         switch (runningTaskInfo.getWindowingMode()) {
             case WINDOWING_MODE_FULLSCREEN:
-                return runningTaskInfo.letterboxActivityBounds != null
-                        ? TASK_LISTENER_TYPE_LETTERBOX
-                        : TASK_LISTENER_TYPE_FULLSCREEN;
+                return TASK_LISTENER_TYPE_FULLSCREEN;
             case WINDOWING_MODE_MULTI_WINDOW:
                 return TASK_LISTENER_TYPE_MULTI_WINDOW;
             case WINDOWING_MODE_PINNED:
@@ -395,8 +386,6 @@
         switch (type) {
             case TASK_LISTENER_TYPE_FULLSCREEN:
                 return "TASK_LISTENER_TYPE_FULLSCREEN";
-            case TASK_LISTENER_TYPE_LETTERBOX:
-                return "TASK_LISTENER_TYPE_LETTERBOX";
             case TASK_LISTENER_TYPE_MULTI_WINDOW:
                 return "TASK_LISTENER_TYPE_MULTI_WINDOW";
             case TASK_LISTENER_TYPE_PIP:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 59a765d..d588419 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -87,16 +87,12 @@
         super(context, null, 0, 0, true /* disableBackgroundLayer */);
 
         mTaskOrganizer = organizer;
+        mExecutor = organizer.getExecutor();
         setUseAlpha();
         getHolder().addCallback(this);
         mGuard.open("release");
     }
 
-    // TODO: Use TaskOrganizer executor when part of wmshell proper
-    public void setExecutor(Executor executor) {
-        mExecutor = executor;
-    }
-
     /**
      * Only one listener may be set on the view, throws an exception otherwise.
      */
@@ -241,7 +237,7 @@
                 // so go ahead and hide the task entirely
                 updateTaskVisibility();
             }
-
+            mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, true);
             // TODO: Synchronize show with the resize
             onLocationChanged();
             setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
@@ -261,6 +257,7 @@
             if (mListener != null) {
                 mListener.onTaskRemovalStarted(taskInfo.taskId);
             }
+            mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, false);
 
             // Unparent the task when this surface is destroyed
             mTransaction.reparent(mTaskLeash, null).apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
index 10195b6..a779531 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell;
 
-import static android.window.TransitionInfo.TRANSIT_CLOSE;
-import static android.window.TransitionInfo.TRANSIT_HIDE;
-import static android.window.TransitionInfo.TRANSIT_OPEN;
-import static android.window.TransitionInfo.TRANSIT_SHOW;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
@@ -40,7 +40,6 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.ArrayList;
@@ -62,7 +61,7 @@
     /** Keeps track of currently tracked transitions and all the animations associated with each */
     private final ArrayMap<IBinder, ArrayList<Animator>> mActiveTransitions = new ArrayMap<>();
 
-    Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
+    public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
             @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
         mOrganizer = organizer;
         mTransactionPool = pool;
@@ -119,8 +118,8 @@
     }
 
     private static boolean isOpeningType(@WindowManager.TransitionType int type) {
-        return type == WindowManager.TRANSIT_OPEN
-                || type == WindowManager.TRANSIT_TO_FRONT
+        return type == TRANSIT_OPEN
+                || type == TRANSIT_TO_FRONT
                 || type == WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
     }
 
@@ -150,7 +149,7 @@
 
             // Don't animate anything with an animating parent
             if (change.getParent() != null) {
-                if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) {
+                if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
                     t.show(leash);
                     t.setMatrix(leash, 1, 0, 0, 1);
                 }
@@ -161,7 +160,7 @@
             t.setPosition(leash, change.getEndAbsBounds().left - info.getRootOffset().x,
                     change.getEndAbsBounds().top - info.getRootOffset().y);
             // Put all the OPEN/SHOW on top
-            if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) {
+            if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
                 t.show(leash);
                 t.setMatrix(leash, 1, 0, 0, 1);
                 if (isOpening) {
@@ -174,7 +173,7 @@
                     t.setLayer(leash, -i);
                     t.setAlpha(leash, 1.f);
                 }
-            } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_HIDE) {
+            } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
                 if (isOpening) {
                     // put on bottom and leave visible without fade
                     t.setLayer(leash, -i);
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..563de06 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,8 @@
         mTaskInfo2 = task2;
         mSplitLayout = new SplitLayout(
                 mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
-                mRootTaskInfo.configuration, this, mRootTaskLeash);
+                mRootTaskInfo.configuration, this /* layoutChangeListener */,
+                b -> b.setParent(mRootTaskLeash));
 
         final WindowContainerToken token1 = task1.token;
         final WindowContainerToken token2 = task2.token;
@@ -191,22 +192,7 @@
 
             if (mSplitLayout != null
                     && mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) {
-                // Update bounds when root bounds or its orientation changed.
-                final WindowContainerTransaction wct = new WindowContainerTransaction();
-                final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
-                final Rect dividerBounds = mSplitLayout.getDividerBounds();
-                final Rect bounds1 = mSplitLayout.getBounds1();
-                final Rect bounds2 = mSplitLayout.getBounds2();
-
-                wct.setBounds(mTaskInfo1.token, bounds1)
-                        .setBounds(mTaskInfo2.token, bounds2);
-                mController.getTaskOrganizer().applyTransaction(wct);
-                mSyncQueue.runInSync(t -> t
-                        .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
-                        .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
-                        .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
-                        // Resets layer to divider bar to make sure it is always on top.
-                        .setLayer(dividerLeash, Integer.MAX_VALUE));
+                onBoundsChanged(mSplitLayout);
             }
         } else if (taskInfo.taskId == getTaskId1()) {
             mTaskInfo1 = taskInfo;
@@ -262,6 +248,10 @@
         final Rect bounds1 = layout.getBounds1();
         final Rect bounds2 = layout.getBounds2();
         mSyncQueue.runInSync(t -> t
+                // Ignores the original surface bounds so that the app could fill up the gap
+                // between each surface with corresponding background while resizing.
+                .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
+                .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
                 .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
                 .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
                 .setPosition(mTaskLeash2, bounds2.left, bounds2.top));
@@ -279,6 +269,10 @@
                 .setBounds(mTaskInfo2.token, bounds2);
         mController.getTaskOrganizer().applyTransaction(wct);
         mSyncQueue.runInSync(t -> t
+                // Resets layer of divider bar to make sure it is always on top.
+                .setLayer(dividerLeash, Integer.MAX_VALUE)
+                .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
+                .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
                 .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
                 .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
                 .setPosition(mTaskLeash2, bounds2.left, bounds2.top));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 318a0bd..4bf01f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -59,7 +59,6 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.TaskView;
 import com.android.wm.shell.common.AlphaOptimizedButton;
-import com.android.wm.shell.common.HandlerExecutor;
 import com.android.wm.shell.common.TriangleShape;
 
 import java.io.FileDescriptor;
@@ -304,11 +303,6 @@
         setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mTaskView.setExecutor(new HandlerExecutor(getHandler()));
-    }
     /**
      * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need
      * to be called after view inflate.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 4c06a2c..616f24a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -339,9 +339,6 @@
         public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {}
 
         @Override
-        public void dispatchPointerCaptureChanged(boolean hasCapture) {}
-
-        @Override
         public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
             try {
                 callbacks.onUnavailable();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
index 5e07718..00bd9e5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
@@ -16,11 +16,11 @@
 
 package com.android.wm.shell.common;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ITaskStackListener;
 import android.content.ComponentName;
 import android.os.IBinder;
+import android.window.TaskSnapshot;
 
 import androidx.annotation.BinderThread;
 
@@ -55,7 +55,7 @@
 
     default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
 
-    default void onTaskSnapshotChanged(int taskId, ActivityManager.TaskSnapshot snapshot) { }
+    default void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
 
     default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index 7efacc7..718f7a0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -26,6 +26,7 @@
 import android.os.Message;
 import android.os.Trace;
 import android.util.Log;
+import android.window.TaskSnapshot;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
@@ -181,7 +182,7 @@
     }
 
     @Override
-    public void onTaskSnapshotChanged(int taskId, ActivityManager.TaskSnapshot snapshot) {
+    public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
         mHandler.obtainMessage(ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
     }
 
@@ -283,7 +284,7 @@
                     Trace.beginSection("onTaskSnapshotChanged");
                     for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                         mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
-                                (ActivityManager.TaskSnapshot) msg.obj);
+                                (TaskSnapshot) msg.obj);
                     }
                     Trace.endSection();
                     break;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
new file mode 100644
index 0000000..218bf47
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.common.split;
+
+import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION;
+import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.Property;
+import android.view.View;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
+
+/**
+ * View for the handle in the docked stack divider.
+ */
+public class DividerHandleView extends View {
+
+    private static final Property<DividerHandleView, Integer> WIDTH_PROPERTY =
+            new Property<DividerHandleView, Integer>(Integer.class, "width") {
+                @Override
+                public Integer get(DividerHandleView object) {
+                    return object.mCurrentWidth;
+                }
+
+                @Override
+                public void set(DividerHandleView object, Integer value) {
+                    object.mCurrentWidth = value;
+                    object.invalidate();
+                }
+            };
+
+    private static final Property<DividerHandleView, Integer> HEIGHT_PROPERTY =
+            new Property<DividerHandleView, Integer>(Integer.class, "height") {
+                @Override
+                public Integer get(DividerHandleView object) {
+                    return object.mCurrentHeight;
+                }
+
+                @Override
+                public void set(DividerHandleView object, Integer value) {
+                    object.mCurrentHeight = value;
+                    object.invalidate();
+                }
+            };
+
+    private final Paint mPaint = new Paint();
+    private final int mWidth;
+    private final int mHeight;
+    private final int mCircleDiameter;
+    private int mCurrentWidth;
+    private int mCurrentHeight;
+    private AnimatorSet mAnimator;
+    private boolean mTouching;
+
+    public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
+        mPaint.setAntiAlias(true);
+        mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
+        mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
+        mCurrentWidth = mWidth;
+        mCurrentHeight = mHeight;
+        mCircleDiameter = (mWidth + mHeight) / 3;
+    }
+
+    /** Sets touching state for this handle view. */
+    public void setTouching(boolean touching, boolean animate) {
+        if (touching == mTouching) {
+            return;
+        }
+        if (mAnimator != null) {
+            mAnimator.cancel();
+            mAnimator = null;
+        }
+        if (!animate) {
+            if (touching) {
+                mCurrentWidth = mCircleDiameter;
+                mCurrentHeight = mCircleDiameter;
+            } else {
+                mCurrentWidth = mWidth;
+                mCurrentHeight = mHeight;
+            }
+            invalidate();
+        } else {
+            animateToTarget(touching ? mCircleDiameter : mWidth,
+                    touching ? mCircleDiameter : mHeight, touching);
+        }
+        mTouching = touching;
+    }
+
+    private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
+        ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY,
+                mCurrentWidth, targetWidth);
+        ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY,
+                mCurrentHeight, targetHeight);
+        mAnimator = new AnimatorSet();
+        mAnimator.playTogether(widthAnimator, heightAnimator);
+        mAnimator.setDuration(touching
+                ? TOUCH_ANIMATION_DURATION
+                : TOUCH_RELEASE_ANIMATION_DURATION);
+        mAnimator.setInterpolator(touching
+                ? Interpolators.TOUCH_RESPONSE
+                : Interpolators.FAST_OUT_SLOW_IN);
+        mAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimator = null;
+            }
+        });
+        mAnimator.start();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        int left = getWidth() / 2 - mCurrentWidth / 2;
+        int top = getHeight() / 2 - mCurrentHeight / 2;
+        int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2;
+        canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
+                radius, radius, mPaint);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 50d9fe8..707747b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -33,17 +33,23 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
 
 /**
  * Stack divider for app pair.
  */
-// TODO(b/172704238): add handle view to indicate touching status.
 public class DividerView extends FrameLayout implements View.OnTouchListener {
+    public static final long TOUCH_ANIMATION_DURATION = 150;
+    public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
+
     private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
 
     private SplitLayout mSplitLayout;
     private SurfaceControlViewHost mViewHost;
-    private DragListener mDragListener;
+    private DividerHandleView mHandle;
+    private View mBackground;
+    private int mTouchElevation;
 
     private VelocityTracker mVelocityTracker;
     private boolean mMoving;
@@ -70,16 +76,18 @@
     /** Sets up essential dependencies of the divider bar. */
     public void setup(
             SplitLayout layout,
-            SurfaceControlViewHost viewHost,
-            @Nullable DragListener dragListener) {
+            SurfaceControlViewHost viewHost) {
         mSplitLayout = layout;
         mViewHost = viewHost;
-        mDragListener = dragListener;
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mHandle = findViewById(R.id.docked_divider_handle);
+        mBackground = findViewById(R.id.docked_divider_background);
+        mTouchElevation = getResources().getDimensionPixelSize(
+                R.dimen.docked_stack_divider_lift_elevation);
         setOnTouchListener(this);
     }
 
@@ -97,7 +105,7 @@
             case MotionEvent.ACTION_DOWN:
                 mVelocityTracker = VelocityTracker.obtain();
                 mVelocityTracker.addMovement(event);
-                setSlippery(false);
+                setTouching();
                 mStartPos = touchPos;
                 mMoving = false;
                 break;
@@ -106,13 +114,10 @@
                 if (!mMoving && Math.abs(touchPos - mStartPos) > mTouchSlop) {
                     mStartPos = touchPos;
                     mMoving = true;
-                    if (mDragListener != null) {
-                        mDragListener.onDragStart();
-                    }
                 }
                 if (mMoving) {
                     final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
-                    mSplitLayout.updateDividePosition(position);
+                    mSplitLayout.updateDivideBounds(position);
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -122,21 +127,57 @@
                 final float velocity = isLandscape
                         ? mVelocityTracker.getXVelocity()
                         : mVelocityTracker.getYVelocity();
-                setSlippery(true);
+                releaseTouching();
                 mMoving = false;
-                if (mDragListener != null) {
-                    mDragListener.onDragEnd();
-                }
 
                 final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
                 final DividerSnapAlgorithm.SnapTarget snapTarget =
                         mSplitLayout.findSnapTarget(position, velocity);
-                mSplitLayout.setSnapTarget(snapTarget);
+                mSplitLayout.snapToTarget(position, snapTarget);
                 break;
         }
         return true;
     }
 
+    private void setTouching() {
+        setSlippery(false);
+        mHandle.setTouching(true, true);
+        if (isLandscape()) {
+            mBackground.animate().scaleX(1.4f);
+        } else {
+            mBackground.animate().scaleY(1.4f);
+        }
+        mBackground.animate()
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
+                .setDuration(TOUCH_ANIMATION_DURATION)
+                .translationZ(mTouchElevation)
+                .start();
+        // Lift handle as well so it doesn't get behind the background, even though it doesn't
+        // cast shadow.
+        mHandle.animate()
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
+                .setDuration(TOUCH_ANIMATION_DURATION)
+                .translationZ(mTouchElevation)
+                .start();
+    }
+
+    private void releaseTouching() {
+        setSlippery(true);
+        mHandle.setTouching(false, true);
+        mBackground.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+                .translationZ(0)
+                .scaleX(1f)
+                .scaleY(1f)
+                .start();
+        mHandle.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+                .translationZ(0)
+                .start();
+    }
+
     private void setSlippery(boolean slippery) {
         if (mViewHost == null) {
             return;
@@ -159,13 +200,4 @@
     private boolean isLandscape() {
         return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
     }
-
-    /** Monitors dragging action of the divider bar. */
-    // TODO(b/172704238): add listeners to deal with resizing state of the app windows.
-    public interface DragListener {
-        /** Called when start dragging. */
-        void onDragStart();
-        /** Called when stop dragging. */
-        void onDragEnd();
-    }
 }
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 e11037f..291e9bd 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
@@ -22,6 +22,9 @@
 import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
 import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -31,6 +34,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.animation.Interpolators;
 
 /**
  * Records and handles layout of splits. Helps to calculate proper bounds when configuration or
@@ -53,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);
@@ -119,14 +125,16 @@
         mBounds1.set(mRootBounds);
         mBounds2.set(mRootBounds);
         if (isLandscape(mRootBounds)) {
+            position += mRootBounds.left;
             mDividerBounds.left = position - mDividerInsets;
             mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth;
-            mBounds1.right = mBounds1.left + position;
+            mBounds1.right = position;
             mBounds2.left = mBounds1.right + mDividerSize;
         } else {
+            position += mRootBounds.top;
             mDividerBounds.top = position - mDividerInsets;
             mDividerBounds.bottom = mDividerBounds.top + mDividerWindowWidth;
-            mBounds1.bottom = mBounds1.top + position;
+            mBounds1.bottom = position;
             mBounds2.top = mBounds1.bottom + mDividerSize;
         }
     }
@@ -145,27 +153,35 @@
      * Updates bounds with the passing position. Usually used to update recording bounds while
      * performing animation or dragging divider bar to resize the splits.
      */
-    public void updateDividePosition(int position) {
+    void updateDivideBounds(int position) {
         updateBounds(position);
         mLayoutChangeListener.onBoundsChanging(this);
+        mSplitWindowManager.setResizingSplits(true);
+    }
+
+    void setDividePosition(int position) {
+        mDividePosition = position;
+        updateBounds(mDividePosition);
+        mLayoutChangeListener.onBoundsChanged(this);
+        mSplitWindowManager.setResizingSplits(false);
     }
 
     /**
      * Sets new divide position and updates bounds correspondingly. Notifies listener if the new
      * target indicates dismissing split.
      */
-    public void setSnapTarget(DividerSnapAlgorithm.SnapTarget snapTarget) {
-        switch(snapTarget.flag) {
+    public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
+        switch (snapTarget.flag) {
             case FLAG_DISMISS_START:
                 mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */);
+                mSplitWindowManager.setResizingSplits(false);
                 break;
             case FLAG_DISMISS_END:
                 mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */);
+                mSplitWindowManager.setResizingSplits(false);
                 break;
             default:
-                mDividePosition = snapTarget.position;
-                updateBounds(mDividePosition);
-                mLayoutChangeListener.onBoundsChanged(this);
+                flingDividePosition(currentPosition, snapTarget.position);
                 break;
         }
     }
@@ -189,6 +205,27 @@
                 isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
     }
 
+    private void flingDividePosition(int from, int to) {
+        ValueAnimator animator = ValueAnimator
+                .ofInt(from, to)
+                .setDuration(250);
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        animator.addUpdateListener(
+                animation -> updateDivideBounds((int) animation.getAnimatedValue()));
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                setDividePosition(to);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                setDividePosition(to);
+            }
+        });
+        animator.start();
+    }
+
     private static boolean isLandscape(Rect bounds) {
         return bounds.width() > bounds.height();
     }
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..29116bd 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
@@ -25,6 +25,7 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
+import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
@@ -32,6 +33,8 @@
 import android.graphics.Region;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
 import android.view.IWindow;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
@@ -47,14 +50,23 @@
  * Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split.
  */
 public final class SplitWindowManager extends WindowlessWindowManager {
+    private static final String TAG = SplitWindowManager.class.getSimpleName();
     private static final String DIVIDER_WINDOW_TITLE = "SplitDivider";
 
+    private final ParentContainerCallbacks mParentContainerCallbacks;
     private Context mContext;
     private SurfaceControlViewHost mViewHost;
+    private boolean mResizingSplits;
 
-    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 +85,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) {
@@ -92,7 +109,7 @@
         lp.setTitle(DIVIDER_WINDOW_TITLE);
         lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
         mViewHost.setView(dividerView, lp);
-        dividerView.setup(splitLayout, mViewHost, null /* dragListener */);
+        dividerView.setup(splitLayout, mViewHost);
     }
 
     /**
@@ -105,6 +122,16 @@
         mViewHost = null;
     }
 
+    void setResizingSplits(boolean resizing) {
+        if (resizing == mResizingSplits) return;
+        try {
+            ActivityTaskManager.getService().setSplitScreenResizing(resizing);
+            mResizingSplits = resizing;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error calling setSplitScreenResizing", e);
+        }
+    }
+
     /**
      * Gets {@link SurfaceControl} of the surface holding divider view. @return {@code null} if not
      * feasible.
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 625c0a7..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,9 +52,8 @@
 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.Objects;
 import java.util.Optional;
 
 /**
@@ -67,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();
@@ -78,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
@@ -105,19 +104,25 @@
                 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));
-        wm.addView(rootView, layoutParams);
-
-        mDisplayDropTargets.put(displayId,
-                new PerDisplay(displayId, context, wm, rootView, dragLayout));
+        try {
+            wm.addView(rootView, layoutParams);
+            mDisplayDropTargets.put(displayId,
+                    new PerDisplay(displayId, context, wm, rootView, dragLayout));
+        } catch (WindowManager.InvalidDisplayException e) {
+            Slog.w(TAG, "Unable to add view for display id: " + displayId);
+        }
     }
 
     @Override
     public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display changed: %d", displayId);
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
+        if (pd == null) {
+            return;
+        }
         pd.rootView.requestApplyInsets();
     }
 
@@ -125,6 +130,9 @@
     public void onDisplayRemoved(int displayId) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display removed: %d", displayId);
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
+        if (pd == null) {
+            return;
+        }
         pd.wm.removeViewImmediate(pd.rootView);
         mDisplayDropTargets.remove(displayId);
     }
@@ -139,6 +147,10 @@
         final PerDisplay pd = mDisplayDropTargets.get(displayId);
         final ClipDescription description = event.getClipDescription();
 
+        if (pd == null) {
+            return false;
+        }
+
         if (event.getAction() == ACTION_DRAG_STARTED) {
             final boolean hasValidClipData = event.getClipData().getItemCount() > 0
                     && (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY)
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/legacysplitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
new file mode 100644
index 0000000..2c0cf59
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
@@ -0,0 +1,417 @@
+/*
+ * 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.legacysplitscreen;
+
+import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
+import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.util.Slog;
+import android.view.Choreographer;
+import android.view.SurfaceControl;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.TransactionPool;
+
+class DividerImeController implements DisplayImeController.ImePositionProcessor {
+    private static final String TAG = "DividerImeController";
+    private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
+
+    private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
+
+    private final LegacySplitScreenTaskListener mSplits;
+    private final TransactionPool mTransactionPool;
+    private final Handler mHandler;
+    private final TaskOrganizer mTaskOrganizer;
+
+    /**
+     * These are the y positions of the top of the IME surface when it is hidden and when it is
+     * shown respectively. These are NOT necessarily the top of the visible IME itself.
+     */
+    private int mHiddenTop = 0;
+    private int mShownTop = 0;
+
+    // The following are target states (what we are curretly animating towards).
+    /**
+     * {@code true} if, at the end of the animation, the split task positions should be
+     * adjusted by height of the IME. This happens when the secondary split is the IME target.
+     */
+    private boolean mTargetAdjusted = false;
+    /**
+     * {@code true} if, at the end of the animation, the IME should be shown/visible
+     * regardless of what has focus.
+     */
+    private boolean mTargetShown = false;
+    private float mTargetPrimaryDim = 0.f;
+    private float mTargetSecondaryDim = 0.f;
+
+    // The following are the current (most recent) states set during animation
+    /** {@code true} if the secondary split has IME focus. */
+    private boolean mSecondaryHasFocus = false;
+    /** The dimming currently applied to the primary/secondary splits. */
+    private float mLastPrimaryDim = 0.f;
+    private float mLastSecondaryDim = 0.f;
+    /** The most recent y position of the top of the IME surface */
+    private int mLastAdjustTop = -1;
+
+    // The following are states reached last time an animation fully completed.
+    /** {@code true} if the IME was shown/visible by the last-completed animation. */
+    private boolean mImeWasShown = false;
+    /** {@code true} if the split positions were adjusted by the last-completed animation. */
+    private boolean mAdjusted = false;
+
+    /**
+     * When some aspect of split-screen needs to animate independent from the IME,
+     * this will be non-null and control split animation.
+     */
+    @Nullable
+    private ValueAnimator mAnimation = null;
+
+    private boolean mPaused = true;
+    private boolean mPausedTargetAdjusted = false;
+    private boolean mAdjustedWhileHidden = false;
+
+    DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool,
+            Handler handler, TaskOrganizer taskOrganizer) {
+        mSplits = splits;
+        mTransactionPool = pool;
+        mHandler = handler;
+        mTaskOrganizer = taskOrganizer;
+    }
+
+    private DividerView getView() {
+        return mSplits.mSplitScreenController.getDividerView();
+    }
+
+    private LegacySplitDisplayLayout getLayout() {
+        return mSplits.mSplitScreenController.getSplitLayout();
+    }
+
+    private boolean isDividerVisible() {
+        return mSplits.mSplitScreenController.isDividerVisible();
+    }
+
+    private boolean getSecondaryHasFocus(int displayId) {
+        WindowContainerToken imeSplit = mTaskOrganizer.getImeTarget(displayId);
+        return imeSplit != null
+                && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
+    }
+
+    void reset() {
+        mPaused = true;
+        mPausedTargetAdjusted = false;
+        mAdjustedWhileHidden = false;
+        mAnimation = null;
+        mAdjusted = mTargetAdjusted = false;
+        mImeWasShown = mTargetShown = false;
+        mTargetPrimaryDim = mTargetSecondaryDim = mLastPrimaryDim = mLastSecondaryDim = 0.f;
+        mSecondaryHasFocus = false;
+        mLastAdjustTop = -1;
+    }
+
+    private void updateDimTargets() {
+        final boolean splitIsVisible = !getView().isHidden();
+        mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
+                ? ADJUSTED_NONFOCUS_DIM : 0.f;
+        mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
+                ? ADJUSTED_NONFOCUS_DIM : 0.f;
+    }
+
+    @Override
+    @ImeAnimationFlags
+    public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
+            boolean imeShouldShow, boolean imeIsFloating, SurfaceControl.Transaction t) {
+        mHiddenTop = hiddenTop;
+        mShownTop = shownTop;
+        mTargetShown = imeShouldShow;
+        if (!isDividerVisible()) {
+            return 0;
+        }
+        final boolean splitIsVisible = !getView().isHidden();
+        mSecondaryHasFocus = getSecondaryHasFocus(displayId);
+        final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
+                && !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
+                && !mSplits.mSplitScreenController.isMinimized();
+        if (mLastAdjustTop < 0) {
+            mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
+        } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
+            if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
+                // Check for an "interruption" of an existing animation. In this case, we
+                // need to fake-flip the last-known state direction so that the animation
+                // completes in the other direction.
+                mAdjusted = mTargetAdjusted;
+            } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
+                // Already fully adjusted for IME, but IME height has changed; so, force-start
+                // an async animation to the new IME height.
+                mAdjusted = false;
+            }
+        }
+        if (mPaused) {
+            mPausedTargetAdjusted = targetAdjusted;
+            if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
+            return (targetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
+        }
+        mTargetAdjusted = targetAdjusted;
+        updateDimTargets();
+        if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + "  " + dumpState());
+        if (mAnimation != null || (mImeWasShown && imeShouldShow
+                && mTargetAdjusted != mAdjusted)) {
+            // We need to animate adjustment independently of the IME position, so
+            // start our own animation to drive adjustment. This happens when a
+            // different split's editor has gained focus while the IME is still visible.
+            startAsyncAnimation();
+        }
+        if (splitIsVisible) {
+            // If split is hidden, we don't want to trigger any relayouts that would cause the
+            // divider to show again.
+            updateImeAdjustState();
+        } else {
+            mAdjustedWhileHidden = true;
+        }
+        return (mTargetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
+    }
+
+    private void updateImeAdjustState() {
+        updateImeAdjustState(false /* force */);
+    }
+
+    private void updateImeAdjustState(boolean force) {
+        if (mAdjusted != mTargetAdjusted || force) {
+            // Reposition the server's secondary split position so that it evaluates
+            // insets properly.
+            WindowContainerTransaction wct = new WindowContainerTransaction();
+            final LegacySplitDisplayLayout splitLayout = getLayout();
+            if (mTargetAdjusted) {
+                splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
+                wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
+                // "Freeze" the configuration size so that the app doesn't get a config
+                // or relaunch. This is required because normally nav-bar contributes
+                // to configuration bounds (via nondecorframe).
+                Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
+                        .windowConfiguration.getAppBounds());
+                adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top
+                        - splitLayout.mSecondary.top);
+                wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
+                wct.setScreenSizeDp(mSplits.mSecondary.token,
+                        mSplits.mSecondary.configuration.screenWidthDp,
+                        mSplits.mSecondary.configuration.screenHeightDp);
+
+                wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary);
+                adjustAppBounds = new Rect(mSplits.mPrimary.configuration
+                        .windowConfiguration.getAppBounds());
+                adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top
+                        - splitLayout.mPrimary.top);
+                wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
+                wct.setScreenSizeDp(mSplits.mPrimary.token,
+                        mSplits.mPrimary.configuration.screenWidthDp,
+                        mSplits.mPrimary.configuration.screenHeightDp);
+            } else {
+                wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary);
+                wct.setAppBounds(mSplits.mSecondary.token, null);
+                wct.setScreenSizeDp(mSplits.mSecondary.token,
+                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+                wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary);
+                wct.setAppBounds(mSplits.mPrimary.token, null);
+                wct.setScreenSizeDp(mSplits.mPrimary.token,
+                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+            }
+
+            if (!mSplits.mSplitScreenController.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
+                mTaskOrganizer.applyTransaction(wct);
+            }
+        }
+
+        // Update all the adjusted-for-ime states
+        if (!mPaused) {
+            final DividerView view = getView();
+            if (view != null) {
+                view.setAdjustedForIme(mTargetShown, mTargetShown
+                        ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
+                        : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
+            }
+        }
+        mSplits.mSplitScreenController.setAdjustedForIme(mTargetShown && !mPaused);
+    }
+
+    public void updateAdjustForIme() {
+        updateImeAdjustState(mAdjustedWhileHidden);
+        mAdjustedWhileHidden = false;
+    }
+
+    @Override
+    public void onImePositionChanged(int displayId, int imeTop,
+            SurfaceControl.Transaction t) {
+        if (mAnimation != null || !isDividerVisible() || mPaused) {
+            // Not synchronized with IME anymore, so return.
+            return;
+        }
+        final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
+        final float progress = mTargetShown ? fraction : 1.f - fraction;
+        onProgress(progress, t);
+    }
+
+    @Override
+    public void onImeEndPositioning(int displayId, boolean cancelled,
+            SurfaceControl.Transaction t) {
+        if (mAnimation != null || !isDividerVisible() || mPaused) {
+            // Not synchronized with IME anymore, so return.
+            return;
+        }
+        onEnd(cancelled, t);
+    }
+
+    private void onProgress(float progress, SurfaceControl.Transaction t) {
+        final DividerView view = getView();
+        if (mTargetAdjusted != mAdjusted && !mPaused) {
+            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);
+            view.resizeSplitSurfaces(t, splitLayout.mAdjustedPrimary,
+                    splitLayout.mAdjustedSecondary);
+        }
+        final float invProg = 1.f - progress;
+        view.setResizeDimLayer(t, true /* primary */,
+                mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
+        view.setResizeDimLayer(t, false /* primary */,
+                mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
+    }
+
+    void setDimsHidden(SurfaceControl.Transaction t, boolean hidden) {
+        final DividerView view = getView();
+        if (hidden) {
+            view.setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
+            view.setResizeDimLayer(t, false /* primary */, 0.f /* alpha */);
+        } else {
+            updateDimTargets();
+            view.setResizeDimLayer(t, true /* primary */, mTargetPrimaryDim);
+            view.setResizeDimLayer(t, false /* primary */, mTargetSecondaryDim);
+        }
+    }
+
+    private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
+        if (!cancelled) {
+            onProgress(1.f, t);
+            mAdjusted = mTargetAdjusted;
+            mImeWasShown = mTargetShown;
+            mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
+            mLastPrimaryDim = mTargetPrimaryDim;
+            mLastSecondaryDim = mTargetSecondaryDim;
+        }
+    }
+
+    private void startAsyncAnimation() {
+        if (mAnimation != null) {
+            mAnimation.cancel();
+        }
+        mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
+        mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
+        if (mTargetAdjusted != mAdjusted) {
+            final float fraction =
+                    ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
+            final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
+            mAnimation.setCurrentFraction(progress);
+        }
+
+        mAnimation.addUpdateListener(animation -> {
+            SurfaceControl.Transaction t = mTransactionPool.acquire();
+            float value = (float) animation.getAnimatedValue();
+            onProgress(value, t);
+            t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
+            t.apply();
+            mTransactionPool.release(t);
+        });
+        mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
+        mAnimation.addListener(new AnimatorListenerAdapter() {
+            private boolean mCancel = false;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCancel = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                SurfaceControl.Transaction t = mTransactionPool.acquire();
+                onEnd(mCancel, t);
+                t.apply();
+                mTransactionPool.release(t);
+                mAnimation = null;
+            }
+        });
+        mAnimation.start();
+    }
+
+    private String dumpState() {
+        return "top:" + mHiddenTop + "->" + mShownTop
+                + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
+                + " shw:" + mImeWasShown + "->" + mTargetShown
+                + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
+                + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
+                + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
+                + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
+    }
+
+    /** Completely aborts/resets adjustment state */
+    public void pause(int displayId) {
+        if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
+        mHandler.post(() -> {
+            if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
+            if (mPaused) {
+                return;
+            }
+            mPaused = true;
+            mPausedTargetAdjusted = mTargetAdjusted;
+            mTargetAdjusted = false;
+            mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
+            updateImeAdjustState();
+            startAsyncAnimation();
+            if (mAnimation != null) {
+                mAnimation.end();
+            }
+        });
+    }
+
+    public void resume(int displayId) {
+        if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
+        mHandler.post(() -> {
+            if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
+            if (!mPaused) {
+                return;
+            }
+            mPaused = false;
+            mTargetAdjusted = mPausedTargetAdjusted;
+            updateDimTargets();
+            final DividerView view = getView();
+            if ((mTargetAdjusted != mAdjusted) && !mSplits.mSplitScreenController.isMinimized()
+                    && view != null) {
+                // End unminimize animations since they conflict with adjustment animations.
+                view.finishAnimations();
+            }
+            updateImeAdjustState();
+            startAsyncAnimation();
+        });
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
new file mode 100644
index 0000000..af2ab15
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+/**
+ * Class to hold state of divider that needs to persist across configuration changes.
+ */
+final class DividerState {
+    public boolean animateAfterRecentsDrawn;
+    public float mRatioPositionBeforeMinimized;
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
new file mode 100644
index 0000000..c1b6c4f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -0,0 +1,1343 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
+import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
+import static android.view.WindowManager.DOCKED_RIGHT;
+
+import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION;
+import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION;
+
+import android.animation.AnimationHandler;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.Region.Op;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
+import android.view.ViewRootImpl;
+import android.view.ViewTreeObserver.InternalInsetsInfo;
+import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
+import com.android.internal.policy.DockedDividerUtils;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.split.DividerHandleView;
+
+import java.util.function.Consumer;
+
+/**
+ * Docked stack divider.
+ */
+public class DividerView extends FrameLayout implements OnTouchListener,
+        OnComputeInternalInsetsListener {
+    private static final String TAG = "DividerView";
+    private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
+
+    interface DividerCallbacks {
+        void onDraggingStart();
+        void onDraggingEnd();
+    }
+
+    public static final int INVALID_RECENTS_GROW_TARGET = -1;
+
+    private static final int LOG_VALUE_RESIZE_50_50 = 0;
+    private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
+    private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
+
+    private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
+    private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
+
+    private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
+
+    /**
+     * How much the background gets scaled when we are in the minimized dock state.
+     */
+    private static final float MINIMIZE_DOCK_SCALE = 0f;
+    private static final float ADJUSTED_FOR_IME_SCALE = 0.5f;
+
+    private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
+            new PathInterpolator(0.5f, 1f, 0.5f, 1f);
+    private static final PathInterpolator DIM_INTERPOLATOR =
+            new PathInterpolator(.23f, .87f, .52f, -0.11f);
+    private static final Interpolator IME_ADJUST_INTERPOLATOR =
+            new PathInterpolator(0.2f, 0f, 0.1f, 1f);
+
+    private DividerHandleView mHandle;
+    private View mBackground;
+    private MinimizedDockShadow mMinimizedShadow;
+    private int mStartX;
+    private int mStartY;
+    private int mStartPosition;
+    private int mDockSide;
+    private boolean mMoving;
+    private int mTouchSlop;
+    private boolean mBackgroundLifted;
+    private boolean mIsInMinimizeInteraction;
+    SnapTarget mSnapTargetBeforeMinimized;
+
+    private int mDividerInsets;
+    private final Display mDefaultDisplay;
+
+    private int mDividerSize;
+    private int mTouchElevation;
+    private int mLongPressEntraceAnimDuration;
+
+    private final Rect mDockedRect = new Rect();
+    private final Rect mDockedTaskRect = new Rect();
+    private final Rect mOtherTaskRect = new Rect();
+    private final Rect mOtherRect = new Rect();
+    private final Rect mDockedInsetRect = new Rect();
+    private final Rect mOtherInsetRect = new Rect();
+    private final Rect mLastResizeRect = new Rect();
+    private final Rect mTmpRect = new Rect();
+    private LegacySplitScreenController mSplitScreenController;
+    private WindowManagerProxy mWindowManagerProxy;
+    private DividerWindowManager mWindowManager;
+    private VelocityTracker mVelocityTracker;
+    private FlingAnimationUtils mFlingAnimationUtils;
+    private LegacySplitDisplayLayout mSplitLayout;
+    private DividerImeController mImeController;
+    private DividerCallbacks mCallback;
+    private final AnimationHandler mAnimationHandler = new AnimationHandler();
+
+    private ValueAnimator mCurrentAnimator;
+    private boolean mEntranceAnimationRunning;
+    private boolean mExitAnimationRunning;
+    private int mExitStartPosition;
+    private boolean mDockedStackMinimized;
+    private boolean mHomeStackResizable;
+    private boolean mAdjustedForIme;
+    private DividerState mState;
+
+    private LegacySplitScreenTaskListener mTiles;
+    boolean mFirstLayout = true;
+    int mDividerPositionX;
+    int mDividerPositionY;
+
+    private final Matrix mTmpMatrix = new Matrix();
+    private final float[] mTmpValues = new float[9];
+
+    // The view is removed or in the process of been removed from the system.
+    private boolean mRemoved;
+
+    // Whether the surface for this view has been hidden regardless of actual visibility. This is
+    // used interact with keyguard.
+    private boolean mSurfaceHidden = false;
+
+    private final Handler mHandler = new Handler();
+
+    private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
+        @Override
+        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+            final DividerSnapAlgorithm snapAlgorithm = getSnapAlgorithm();
+            if (isHorizontalDivision()) {
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
+                        mContext.getString(R.string.accessibility_action_divider_top_full)));
+                if (snapAlgorithm.isFirstSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
+                            mContext.getString(R.string.accessibility_action_divider_top_70)));
+                }
+                if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
+                    // Only show the middle target if there are more than 1 split target
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
+                            mContext.getString(R.string.accessibility_action_divider_top_50)));
+                }
+                if (snapAlgorithm.isLastSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
+                            mContext.getString(R.string.accessibility_action_divider_top_30)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
+                        mContext.getString(R.string.accessibility_action_divider_bottom_full)));
+            } else {
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
+                        mContext.getString(R.string.accessibility_action_divider_left_full)));
+                if (snapAlgorithm.isFirstSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
+                            mContext.getString(R.string.accessibility_action_divider_left_70)));
+                }
+                if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
+                    // Only show the middle target if there are more than 1 split target
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
+                            mContext.getString(R.string.accessibility_action_divider_left_50)));
+                }
+                if (snapAlgorithm.isLastSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
+                            mContext.getString(R.string.accessibility_action_divider_left_30)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
+                        mContext.getString(R.string.accessibility_action_divider_right_full)));
+            }
+        }
+
+        @Override
+        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+            int currentPosition = getCurrentPosition();
+            SnapTarget nextTarget = null;
+            DividerSnapAlgorithm snapAlgorithm = mSplitLayout.getSnapAlgorithm();
+            if (action == R.id.action_move_tl_full) {
+                nextTarget = snapAlgorithm.getDismissEndTarget();
+            } else if (action == R.id.action_move_tl_70) {
+                nextTarget = snapAlgorithm.getLastSplitTarget();
+            } else if (action == R.id.action_move_tl_50) {
+                nextTarget = snapAlgorithm.getMiddleTarget();
+            } else if (action == R.id.action_move_tl_30) {
+                nextTarget = snapAlgorithm.getFirstSplitTarget();
+            } else if (action == R.id.action_move_rb_full) {
+                nextTarget = snapAlgorithm.getDismissStartTarget();
+            }
+            if (nextTarget != null) {
+                startDragging(true /* animate */, false /* touching */);
+                stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
+                return true;
+            }
+            return super.performAccessibilityAction(host, action, args);
+        }
+    };
+
+    private final Runnable mResetBackgroundRunnable = new Runnable() {
+        @Override
+        public void run() {
+            resetBackground();
+        }
+    };
+
+    private Runnable mUpdateEmbeddedMatrix = () -> {
+        if (getViewRootImpl() == null) {
+            return;
+        }
+        if (isHorizontalDivision()) {
+            mTmpMatrix.setTranslate(0, mDividerPositionY - mDividerInsets);
+        } else {
+            mTmpMatrix.setTranslate(mDividerPositionX - mDividerInsets, 0);
+        }
+        mTmpMatrix.getValues(mTmpValues);
+        try {
+            getViewRootImpl().getAccessibilityEmbeddedConnection().setScreenMatrix(mTmpValues);
+        } catch (RemoteException e) {
+        }
+    };
+
+    public DividerView(Context context) {
+        this(context, null);
+    }
+
+    public DividerView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        final DisplayManager displayManager =
+                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mHandle = findViewById(R.id.docked_divider_handle);
+        mBackground = findViewById(R.id.docked_divider_background);
+        mMinimizedShadow = findViewById(R.id.minimized_dock_shadow);
+        mHandle.setOnTouchListener(this);
+        final int dividerWindowWidth = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
+        mDividerInsets = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_insets);
+        mDividerSize = dividerWindowWidth - 2 * mDividerInsets;
+        mTouchElevation = getResources().getDimensionPixelSize(
+                R.dimen.docked_stack_divider_lift_elevation);
+        mLongPressEntraceAnimDuration = getResources().getInteger(
+                R.integer.long_press_dock_anim_duration);
+        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f);
+        boolean landscape = getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
+        mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
+                landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW));
+        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+        mHandle.setAccessibilityDelegate(mHandleDelegate);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        // Save the current target if not minimized once attached to window
+        if (mDockSide != WindowManager.DOCKED_INVALID && !mIsInMinimizeInteraction) {
+            saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized);
+        }
+        mFirstLayout = true;
+    }
+
+    void onDividerRemoved() {
+        mRemoved = true;
+        mCallback = null;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (mFirstLayout) {
+            // Wait for first layout so that the ViewRootImpl surface has been created.
+            initializeSurfaceState();
+            mFirstLayout = false;
+        }
+        int minimizeLeft = 0;
+        int minimizeTop = 0;
+        if (mDockSide == WindowManager.DOCKED_TOP) {
+            minimizeTop = mBackground.getTop();
+        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+            minimizeLeft = mBackground.getLeft();
+        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+            minimizeLeft = mBackground.getRight() - mMinimizedShadow.getWidth();
+        }
+        mMinimizedShadow.layout(minimizeLeft, minimizeTop,
+                minimizeLeft + mMinimizedShadow.getMeasuredWidth(),
+                minimizeTop + mMinimizedShadow.getMeasuredHeight());
+        if (changed) {
+            notifySplitScreenBoundsChanged();
+        }
+    }
+
+    void injectDependencies(LegacySplitScreenController splitScreenController,
+            DividerWindowManager windowManager, DividerState dividerState,
+            DividerCallbacks callback, LegacySplitScreenTaskListener tiles,
+            LegacySplitDisplayLayout sdl, DividerImeController imeController,
+            WindowManagerProxy wmProxy) {
+        mSplitScreenController = splitScreenController;
+        mWindowManager = windowManager;
+        mState = dividerState;
+        mCallback = callback;
+        mTiles = tiles;
+        mSplitLayout = sdl;
+        mImeController = imeController;
+        mWindowManagerProxy = wmProxy;
+
+        if (mState.mRatioPositionBeforeMinimized == 0) {
+            // Set the middle target as the initial state
+            mSnapTargetBeforeMinimized = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
+        } else {
+            repositionSnapTargetBeforeMinimized();
+        }
+    }
+
+    /** Gets non-minimized secondary bounds of split screen. */
+    public Rect getNonMinimizedSplitScreenSecondaryBounds() {
+        mOtherTaskRect.set(mSplitLayout.mSecondary);
+        return mOtherTaskRect;
+    }
+
+    private boolean inSplitMode() {
+        return getVisibility() == VISIBLE;
+    }
+
+    /** Unlike setVisible, this directly hides the surface without changing view visibility. */
+    void setHidden(boolean hidden) {
+        if (mSurfaceHidden == hidden) {
+            return;
+        }
+        mSurfaceHidden = hidden;
+        post(() -> {
+            final SurfaceControl sc = getWindowSurfaceControl();
+            if (sc == null) {
+                return;
+            }
+            Transaction t = mTiles.getTransaction();
+            if (hidden) {
+                t.hide(sc);
+            } else {
+                t.show(sc);
+            }
+            mImeController.setDimsHidden(t, hidden);
+            t.apply();
+            mTiles.releaseTransaction(t);
+        });
+    }
+
+    boolean isHidden() {
+        return mSurfaceHidden;
+    }
+
+    /** Starts dragging the divider bar. */
+    public boolean startDragging(boolean animate, boolean touching) {
+        cancelFlingAnimation();
+        if (touching) {
+            mHandle.setTouching(true, animate);
+        }
+        mDockSide = mSplitLayout.getPrimarySplitSide();
+
+        mWindowManagerProxy.setResizing(true);
+        if (touching) {
+            mWindowManager.setSlippery(false);
+            liftBackground();
+        }
+        if (mCallback != null) {
+            mCallback.onDraggingStart();
+        }
+        return inSplitMode();
+    }
+
+    /** Stops dragging the divider bar. */
+    public void stopDragging(int position, float velocity, boolean avoidDismissStart,
+            boolean logMetrics) {
+        mHandle.setTouching(false, true /* animate */);
+        fling(position, velocity, avoidDismissStart, logMetrics);
+        mWindowManager.setSlippery(true);
+        releaseBackground();
+    }
+
+    private void stopDragging(int position, SnapTarget target, long duration,
+            Interpolator interpolator) {
+        stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator);
+    }
+
+    private void stopDragging(int position, SnapTarget target, long duration,
+            Interpolator interpolator, long endDelay) {
+        stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator);
+    }
+
+    private void stopDragging(int position, SnapTarget target, long duration, long startDelay,
+            long endDelay, Interpolator interpolator) {
+        mHandle.setTouching(false, true /* animate */);
+        flingTo(position, target, duration, startDelay, endDelay, interpolator);
+        mWindowManager.setSlippery(true);
+        releaseBackground();
+    }
+
+    private void stopDragging() {
+        mHandle.setTouching(false, true /* animate */);
+        mWindowManager.setSlippery(true);
+        releaseBackground();
+    }
+
+    private void updateDockSide() {
+        mDockSide = mSplitLayout.getPrimarySplitSide();
+        mMinimizedShadow.setDockSide(mDockSide);
+    }
+
+    public DividerSnapAlgorithm getSnapAlgorithm() {
+        return mDockedStackMinimized ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+                        : mSplitLayout.getSnapAlgorithm();
+    }
+
+    public int getCurrentPosition() {
+        return isHorizontalDivision() ? mDividerPositionY : mDividerPositionX;
+    }
+
+    public boolean isMinimized() {
+        return mDockedStackMinimized;
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        convertToScreenCoordinates(event);
+        final int action = event.getAction() & MotionEvent.ACTION_MASK;
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mVelocityTracker = VelocityTracker.obtain();
+                mVelocityTracker.addMovement(event);
+                mStartX = (int) event.getX();
+                mStartY = (int) event.getY();
+                boolean result = startDragging(true /* animate */, true /* touching */);
+                if (!result) {
+
+                    // Weren't able to start dragging successfully, so cancel it again.
+                    stopDragging();
+                }
+                mStartPosition = getCurrentPosition();
+                mMoving = false;
+                return result;
+            case MotionEvent.ACTION_MOVE:
+                mVelocityTracker.addMovement(event);
+                int x = (int) event.getX();
+                int y = (int) event.getY();
+                boolean exceededTouchSlop =
+                        isHorizontalDivision() && Math.abs(y - mStartY) > mTouchSlop
+                                || (!isHorizontalDivision() && Math.abs(x - mStartX) > mTouchSlop);
+                if (!mMoving && exceededTouchSlop) {
+                    mStartX = x;
+                    mStartY = y;
+                    mMoving = true;
+                }
+                if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
+                    SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget(
+                            mStartPosition, 0 /* velocity */, false /* hardDismiss */);
+                    resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget,
+                            null /* transaction */);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mVelocityTracker.addMovement(event);
+
+                x = (int) event.getRawX();
+                y = (int) event.getRawY();
+
+                mVelocityTracker.computeCurrentVelocity(1000);
+                int position = calculatePosition(x, y);
+                stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
+                        : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,
+                        true /* log */);
+                mMoving = false;
+                break;
+        }
+        return true;
+    }
+
+    private void logResizeEvent(SnapTarget snapTarget) {
+        if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissStartTarget()) {
+            MetricsLogger.action(
+                    mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
+                            ? LOG_VALUE_UNDOCK_MAX_OTHER
+                            : LOG_VALUE_UNDOCK_MAX_DOCKED);
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissEndTarget()) {
+            MetricsLogger.action(
+                    mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
+                            ? LOG_VALUE_UNDOCK_MAX_OTHER
+                            : LOG_VALUE_UNDOCK_MAX_DOCKED);
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getMiddleTarget()) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+                    LOG_VALUE_RESIZE_50_50);
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getFirstSplitTarget()) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+                    dockSideTopLeft(mDockSide)
+                            ? LOG_VALUE_RESIZE_DOCKED_SMALLER
+                            : LOG_VALUE_RESIZE_DOCKED_LARGER);
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getLastSplitTarget()) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+                    dockSideTopLeft(mDockSide)
+                            ? LOG_VALUE_RESIZE_DOCKED_LARGER
+                            : LOG_VALUE_RESIZE_DOCKED_SMALLER);
+        }
+    }
+
+    private void convertToScreenCoordinates(MotionEvent event) {
+        event.setLocation(event.getRawX(), event.getRawY());
+    }
+
+    private void fling(int position, float velocity, boolean avoidDismissStart,
+            boolean logMetrics) {
+        DividerSnapAlgorithm currentSnapAlgorithm = getSnapAlgorithm();
+        SnapTarget snapTarget = currentSnapAlgorithm.calculateSnapTarget(position, velocity);
+        if (avoidDismissStart && snapTarget == currentSnapAlgorithm.getDismissStartTarget()) {
+            snapTarget = currentSnapAlgorithm.getFirstSplitTarget();
+        }
+        if (logMetrics) {
+            logResizeEvent(snapTarget);
+        }
+        ValueAnimator anim = getFlingAnimator(position, snapTarget, 0 /* endDelay */);
+        mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity);
+        anim.start();
+    }
+
+    private void flingTo(int position, SnapTarget target, long duration, long startDelay,
+            long endDelay, Interpolator interpolator) {
+        ValueAnimator anim = getFlingAnimator(position, target, endDelay);
+        anim.setDuration(duration);
+        anim.setStartDelay(startDelay);
+        anim.setInterpolator(interpolator);
+        anim.start();
+    }
+
+    private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget,
+            final long endDelay) {
+        if (mCurrentAnimator != null) {
+            cancelFlingAnimation();
+            updateDockSide();
+        }
+        if (DEBUG) Slog.d(TAG, "Getting fling " + position + "->" + snapTarget.position);
+        final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
+        ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
+        anim.addUpdateListener(animation -> resizeStackSurfaces((int) animation.getAnimatedValue(),
+                taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
+                        ? TASK_POSITION_SAME
+                        : snapTarget.taskPosition,
+                snapTarget, null /* transaction */));
+        Consumer<Boolean> endAction = cancelled -> {
+            if (DEBUG) Slog.d(TAG, "End Fling " + cancelled + " min:" + mIsInMinimizeInteraction);
+            final boolean wasMinimizeInteraction = mIsInMinimizeInteraction;
+            // Reset minimized divider position after unminimized state animation finishes.
+            if (!cancelled && !mDockedStackMinimized && mIsInMinimizeInteraction) {
+                mIsInMinimizeInteraction = false;
+            }
+            boolean dismissed = commitSnapFlags(snapTarget);
+            mWindowManagerProxy.setResizing(false);
+            updateDockSide();
+            mCurrentAnimator = null;
+            mEntranceAnimationRunning = false;
+            mExitAnimationRunning = false;
+            if (!dismissed && !wasMinimizeInteraction) {
+                mWindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout);
+            }
+            if (mCallback != null) {
+                mCallback.onDraggingEnd();
+            }
+
+            // Record last snap target the divider moved to
+            if (!mIsInMinimizeInteraction) {
+                // The last snapTarget position can be negative when the last divider position was
+                // offscreen. In that case, save the middle (default) SnapTarget so calculating next
+                // position isn't negative.
+                final SnapTarget saveTarget;
+                if (snapTarget.position < 0) {
+                    saveTarget = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
+                } else {
+                    saveTarget = snapTarget;
+                }
+                final DividerSnapAlgorithm snapAlgo = mSplitLayout.getSnapAlgorithm();
+                if (saveTarget.position != snapAlgo.getDismissEndTarget().position
+                        && saveTarget.position != snapAlgo.getDismissStartTarget().position) {
+                    saveSnapTargetBeforeMinimized(saveTarget);
+                }
+            }
+            notifySplitScreenBoundsChanged();
+        };
+        anim.addListener(new AnimatorListenerAdapter() {
+
+            private boolean mCancelled;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                long delay = 0;
+                if (endDelay != 0) {
+                    delay = endDelay;
+                } else if (mCancelled) {
+                    delay = 0;
+                }
+                if (delay == 0) {
+                    endAction.accept(mCancelled);
+                } else {
+                    final Boolean cancelled = mCancelled;
+                    if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms");
+                    mHandler.postDelayed(() -> endAction.accept(cancelled), delay);
+                }
+            }
+        });
+        anim.setAnimationHandler(mAnimationHandler);
+        mCurrentAnimator = anim;
+        return anim;
+    }
+
+    private void notifySplitScreenBoundsChanged() {
+        if (mSplitLayout.mPrimary == null || mSplitLayout.mSecondary == null) {
+            return;
+        }
+        mOtherTaskRect.set(mSplitLayout.mSecondary);
+
+        mTmpRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), mHandle.getBottom());
+        if (isHorizontalDivision()) {
+            mTmpRect.offsetTo(0, mDividerPositionY);
+        } else {
+            mTmpRect.offsetTo(mDividerPositionX, 0);
+        }
+        mWindowManagerProxy.setTouchRegion(mTmpRect);
+
+        mTmpRect.set(mSplitLayout.mDisplayLayout.stableInsets());
+        switch (mSplitLayout.getPrimarySplitSide()) {
+            case WindowManager.DOCKED_LEFT:
+                mTmpRect.left = 0;
+                break;
+            case WindowManager.DOCKED_RIGHT:
+                mTmpRect.right = 0;
+                break;
+            case WindowManager.DOCKED_TOP:
+                mTmpRect.top = 0;
+                break;
+        }
+        mSplitScreenController.notifyBoundsChanged(mOtherTaskRect, mTmpRect);
+    }
+
+    private void cancelFlingAnimation() {
+        if (mCurrentAnimator != null) {
+            mCurrentAnimator.cancel();
+        }
+    }
+
+    private boolean commitSnapFlags(SnapTarget target) {
+        if (target.flag == SnapTarget.FLAG_NONE) {
+            return false;
+        }
+        final boolean dismissOrMaximize;
+        if (target.flag == SnapTarget.FLAG_DISMISS_START) {
+            dismissOrMaximize = mDockSide == WindowManager.DOCKED_LEFT
+                    || mDockSide == WindowManager.DOCKED_TOP;
+        } else {
+            dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT
+                    || mDockSide == WindowManager.DOCKED_BOTTOM;
+        }
+        mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, mSplitLayout, dismissOrMaximize);
+        Transaction t = mTiles.getTransaction();
+        setResizeDimLayer(t, true /* primary */, 0f);
+        setResizeDimLayer(t, false /* primary */, 0f);
+        t.apply();
+        mTiles.releaseTransaction(t);
+        return true;
+    }
+
+    private void liftBackground() {
+        if (mBackgroundLifted) {
+            return;
+        }
+        if (isHorizontalDivision()) {
+            mBackground.animate().scaleY(1.4f);
+        } else {
+            mBackground.animate().scaleX(1.4f);
+        }
+        mBackground.animate()
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
+                .setDuration(TOUCH_ANIMATION_DURATION)
+                .translationZ(mTouchElevation)
+                .start();
+
+        // Lift handle as well so it doesn't get behind the background, even though it doesn't
+        // cast shadow.
+        mHandle.animate()
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
+                .setDuration(TOUCH_ANIMATION_DURATION)
+                .translationZ(mTouchElevation)
+                .start();
+        mBackgroundLifted = true;
+    }
+
+    private void releaseBackground() {
+        if (!mBackgroundLifted) {
+            return;
+        }
+        mBackground.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+                .translationZ(0)
+                .scaleX(1f)
+                .scaleY(1f)
+                .start();
+        mHandle.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+                .translationZ(0)
+                .start();
+        mBackgroundLifted = false;
+    }
+
+    private void initializeSurfaceState() {
+        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+        // Recalculate the split-layout's internal tile bounds
+        mSplitLayout.resizeSplits(midPos);
+        Transaction t = mTiles.getTransaction();
+        if (mDockedStackMinimized) {
+            int position = mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+                    .getMiddleTarget().position;
+            calculateBoundsForPosition(position, mDockSide, mDockedRect);
+            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+                    mOtherRect);
+            mDividerPositionX = mDividerPositionY = position;
+            resizeSplitSurfaces(t, mDockedRect, mSplitLayout.mPrimary,
+                    mOtherRect, mSplitLayout.mSecondary);
+        } else {
+            resizeSplitSurfaces(t, mSplitLayout.mPrimary, null,
+                    mSplitLayout.mSecondary, null);
+        }
+        setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
+        setResizeDimLayer(t, false /* secondary */, 0.f /* alpha */);
+        t.apply();
+        mTiles.releaseTransaction(t);
+
+        // Get the actually-visible bar dimensions (relative to full window). This is a thin
+        // bar going through the center.
+        final Rect dividerBar = isHorizontalDivision()
+                ? new Rect(0, mDividerInsets, mSplitLayout.mDisplayLayout.width(),
+                mDividerInsets + mDividerSize)
+                : new Rect(mDividerInsets, 0, mDividerInsets + mDividerSize,
+                mSplitLayout.mDisplayLayout.height());
+        final Region touchRegion = new Region(dividerBar);
+        // Add in the "draggable" portion. While not visible, this is an expanded area that the
+        // user can interact with.
+        touchRegion.union(new Rect(mHandle.getLeft(), mHandle.getTop(),
+                mHandle.getRight(), mHandle.getBottom()));
+        mWindowManager.setTouchRegion(touchRegion);
+    }
+
+    void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable,
+            Transaction t) {
+        mHomeStackResizable = isHomeStackResizable;
+        updateDockSide();
+        if (!minimized) {
+            resetBackground();
+        }
+        mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
+        if (mDockedStackMinimized != minimized) {
+            mDockedStackMinimized = minimized;
+            if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) {
+                // Splitscreen to minimize is about to starts after rotating landscape to seascape,
+                // update display info and snap algorithm targets
+                repositionSnapTargetBeforeMinimized();
+            }
+            if (mIsInMinimizeInteraction != minimized || mCurrentAnimator != null) {
+                cancelFlingAnimation();
+                if (minimized) {
+                    // Relayout to recalculate the divider shadow when minimizing
+                    requestLayout();
+                    mIsInMinimizeInteraction = true;
+                    resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+                            .getMiddleTarget(), t);
+                } else {
+                    resizeStackSurfaces(mSnapTargetBeforeMinimized, t);
+                    mIsInMinimizeInteraction = false;
+                }
+            }
+        }
+    }
+
+    void enterSplitMode(boolean isHomeStackResizable) {
+        setHidden(false);
+
+        SnapTarget miniMid =
+                mSplitLayout.getMinimizedSnapAlgorithm(isHomeStackResizable).getMiddleTarget();
+        if (mDockedStackMinimized) {
+            mDividerPositionY = mDividerPositionX = miniMid.position;
+        }
+    }
+
+    /**
+     * Tries to grab a surface control from ViewRootImpl. If this isn't available for some reason
+     * (ie. the window isn't ready yet), it will get the surfacecontrol that the WindowlessWM has
+     * assigned to it.
+     */
+    private SurfaceControl getWindowSurfaceControl() {
+        final ViewRootImpl root = getViewRootImpl();
+        if (root == null) {
+            return null;
+        }
+        SurfaceControl out = root.getSurfaceControl();
+        if (out != null && out.isValid()) {
+            return out;
+        }
+        return mWindowManager.mSystemWindows.getViewSurface(this);
+    }
+
+    void exitSplitMode() {
+        // The view is going to be removed right after this function involved, updates the surface
+        // in the current thread instead of posting it to the view's UI thread.
+        final SurfaceControl sc = getWindowSurfaceControl();
+        if (sc == null) {
+            return;
+        }
+        Transaction t = mTiles.getTransaction();
+        t.hide(sc);
+        mImeController.setDimsHidden(t, true);
+        t.apply();
+        mTiles.releaseTransaction(t);
+
+        // Reset tile bounds
+        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+        mWindowManagerProxy.applyResizeSplits(midPos, mSplitLayout);
+    }
+
+    void setMinimizedDockStack(boolean minimized, long animDuration,
+            boolean isHomeStackResizable) {
+        if (DEBUG) Slog.d(TAG, "setMinDock: " + mDockedStackMinimized + "->" + minimized);
+        mHomeStackResizable = isHomeStackResizable;
+        updateDockSide();
+        if (mDockedStackMinimized != minimized) {
+            mIsInMinimizeInteraction = true;
+            mDockedStackMinimized = minimized;
+            stopDragging(minimized
+                            ? mSnapTargetBeforeMinimized.position
+                            : getCurrentPosition(),
+                    minimized
+                            ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
+                                    .getMiddleTarget()
+                            : mSnapTargetBeforeMinimized,
+                    animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
+            setAdjustedForIme(false, animDuration);
+        }
+        if (!minimized) {
+            mBackground.animate().withEndAction(mResetBackgroundRunnable);
+        }
+        mBackground.animate()
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .setDuration(animDuration)
+                .start();
+    }
+
+    // Needed to end any currently playing animations when they might compete with other anims
+    // (specifically, IME adjust animation immediately after leaving minimized). Someday maybe
+    // these can be unified, but not today.
+    void finishAnimations() {
+        if (mCurrentAnimator != null) {
+            mCurrentAnimator.end();
+        }
+    }
+
+    void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
+        if (mAdjustedForIme == adjustedForIme) {
+            return;
+        }
+        updateDockSide();
+        mHandle.animate()
+                .setInterpolator(IME_ADJUST_INTERPOLATOR)
+                .setDuration(animDuration)
+                .alpha(adjustedForIme ? 0f : 1f)
+                .start();
+        if (mDockSide == WindowManager.DOCKED_TOP) {
+            mBackground.setPivotY(0);
+            mBackground.animate()
+                    .scaleY(adjustedForIme ? ADJUSTED_FOR_IME_SCALE : 1f);
+        }
+        if (!adjustedForIme) {
+            mBackground.animate().withEndAction(mResetBackgroundRunnable);
+        }
+        mBackground.animate()
+                .setInterpolator(IME_ADJUST_INTERPOLATOR)
+                .setDuration(animDuration)
+                .start();
+        mAdjustedForIme = adjustedForIme;
+    }
+
+    private void saveSnapTargetBeforeMinimized(SnapTarget target) {
+        mSnapTargetBeforeMinimized = target;
+        mState.mRatioPositionBeforeMinimized = (float) target.position
+                / (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+                        : mSplitLayout.mDisplayLayout.width());
+    }
+
+    private void resetBackground() {
+        mBackground.setPivotX(mBackground.getWidth() / 2);
+        mBackground.setPivotY(mBackground.getHeight() / 2);
+        mBackground.setScaleX(1f);
+        mBackground.setScaleY(1f);
+        mMinimizedShadow.setAlpha(0f);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+    }
+
+    private void repositionSnapTargetBeforeMinimized() {
+        int position = (int) (mState.mRatioPositionBeforeMinimized
+                * (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+                        : mSplitLayout.mDisplayLayout.width()));
+
+        // Set the snap target before minimized but do not save until divider is attached and not
+        // minimized because it does not know its minimized state yet.
+        mSnapTargetBeforeMinimized =
+                mSplitLayout.getSnapAlgorithm().calculateNonDismissingSnapTarget(position);
+    }
+
+    private int calculatePosition(int touchX, int touchY) {
+        return isHorizontalDivision() ? calculateYPosition(touchY) : calculateXPosition(touchX);
+    }
+
+    public boolean isHorizontalDivision() {
+        return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
+    }
+
+    private int calculateXPosition(int touchX) {
+        return mStartPosition + touchX - mStartX;
+    }
+
+    private int calculateYPosition(int touchY) {
+        return mStartPosition + touchY - mStartY;
+    }
+
+    private void alignTopLeft(Rect containingRect, Rect rect) {
+        int width = rect.width();
+        int height = rect.height();
+        rect.set(containingRect.left, containingRect.top,
+                containingRect.left + width, containingRect.top + height);
+    }
+
+    private void alignBottomRight(Rect containingRect, Rect rect) {
+        int width = rect.width();
+        int height = rect.height();
+        rect.set(containingRect.right - width, containingRect.bottom - height,
+                containingRect.right, containingRect.bottom);
+    }
+
+    private void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
+        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect,
+                mSplitLayout.mDisplayLayout.width(), mSplitLayout.mDisplayLayout.height(),
+                mDividerSize);
+    }
+
+    private void resizeStackSurfaces(SnapTarget taskSnapTarget, Transaction t) {
+        resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget, t);
+    }
+
+    void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect otherRect) {
+        resizeSplitSurfaces(t, dockedRect, null, otherRect, null);
+    }
+
+    private void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect dockedTaskRect,
+            Rect otherRect, Rect otherTaskRect) {
+        dockedTaskRect = dockedTaskRect == null ? dockedRect : dockedTaskRect;
+        otherTaskRect = otherTaskRect == null ? otherRect : otherTaskRect;
+
+        mDividerPositionX = mSplitLayout.getPrimarySplitSide() == DOCKED_RIGHT
+                ? otherRect.right : dockedRect.right;
+        mDividerPositionY = dockedRect.bottom;
+
+        if (DEBUG) {
+            Slog.d(TAG, "Resizing split surfaces: " + dockedRect + " " + dockedTaskRect
+                    + " " + otherRect + " " + otherTaskRect);
+        }
+
+        t.setPosition(mTiles.mPrimarySurface, dockedTaskRect.left, dockedTaskRect.top);
+        Rect crop = new Rect(dockedRect);
+        crop.offsetTo(-Math.min(dockedTaskRect.left - dockedRect.left, 0),
+                -Math.min(dockedTaskRect.top - dockedRect.top, 0));
+        t.setWindowCrop(mTiles.mPrimarySurface, crop);
+        t.setPosition(mTiles.mSecondarySurface, otherTaskRect.left, otherTaskRect.top);
+        crop.set(otherRect);
+        crop.offsetTo(-(otherTaskRect.left - otherRect.left),
+                -(otherTaskRect.top - otherRect.top));
+        t.setWindowCrop(mTiles.mSecondarySurface, crop);
+        final SurfaceControl dividerCtrl = getWindowSurfaceControl();
+        if (dividerCtrl != null) {
+            if (isHorizontalDivision()) {
+                t.setPosition(dividerCtrl, 0, mDividerPositionY - mDividerInsets);
+            } else {
+                t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0);
+            }
+        }
+        if (getViewRootImpl() != null) {
+            mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
+            mHandler.post(mUpdateEmbeddedMatrix);
+        }
+    }
+
+    void setResizeDimLayer(Transaction t, boolean primary, float alpha) {
+        SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim;
+        if (alpha <= 0.001f) {
+            t.hide(dim);
+        } else {
+            t.setAlpha(dim, alpha);
+            t.show(dim);
+        }
+    }
+
+    void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget,
+            Transaction transaction) {
+        if (mRemoved) {
+            // This divider view has been removed so shouldn't have any additional influence.
+            return;
+        }
+        calculateBoundsForPosition(position, mDockSide, mDockedRect);
+        calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+                mOtherRect);
+
+        if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
+            return;
+        }
+
+        // Make sure shadows are updated
+        if (mBackground.getZ() > 0f) {
+            mBackground.invalidate();
+        }
+
+        final boolean ownTransaction = transaction == null;
+        final Transaction t = ownTransaction ? mTiles.getTransaction() : transaction;
+        mLastResizeRect.set(mDockedRect);
+        if (mIsInMinimizeInteraction) {
+            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
+                    mDockedTaskRect);
+            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
+                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+
+            // Move a right-docked-app to line up with the divider while dragging it
+            if (mDockSide == DOCKED_RIGHT) {
+                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
+                        - mDockedTaskRect.left + mDividerSize, 0);
+            }
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
+            if (ownTransaction) {
+                t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
+                t.apply();
+                mTiles.releaseTransaction(t);
+            }
+            return;
+        }
+
+        if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
+            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
+
+            // Move a docked app if from the right in position with the divider up to insets
+            if (mDockSide == DOCKED_RIGHT) {
+                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
+                        - mDockedTaskRect.left + mDividerSize, 0);
+            }
+            calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
+                    mOtherTaskRect);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
+        } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
+            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
+            mDockedInsetRect.set(mDockedTaskRect);
+            calculateBoundsForPosition(mExitStartPosition,
+                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+            mOtherInsetRect.set(mOtherTaskRect);
+            applyExitAnimationParallax(mOtherTaskRect, position);
+
+            // Move a right-docked-app to line up with the divider while dragging it
+            if (mDockSide == DOCKED_RIGHT) {
+                mDockedTaskRect.offset(position + mDividerSize, 0);
+            }
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
+        } else if (taskPosition != TASK_POSITION_SAME) {
+            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+                    mOtherRect);
+            int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide);
+            int taskPositionDocked =
+                    restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget);
+            int taskPositionOther =
+                    restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
+            calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
+            calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
+            mTmpRect.set(0, 0, mSplitLayout.mDisplayLayout.width(),
+                    mSplitLayout.mDisplayLayout.height());
+            alignTopLeft(mDockedRect, mDockedTaskRect);
+            alignTopLeft(mOtherRect, mOtherTaskRect);
+            mDockedInsetRect.set(mDockedTaskRect);
+            mOtherInsetRect.set(mOtherTaskRect);
+            if (dockSideTopLeft(mDockSide)) {
+                alignTopLeft(mTmpRect, mDockedInsetRect);
+                alignBottomRight(mTmpRect, mOtherInsetRect);
+            } else {
+                alignBottomRight(mTmpRect, mDockedInsetRect);
+                alignTopLeft(mTmpRect, mOtherInsetRect);
+            }
+            applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
+                    taskPositionDocked);
+            applyDismissingParallax(mOtherTaskRect, dockSideInverted, taskSnapTarget, position,
+                    taskPositionOther);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
+        } else {
+            resizeSplitSurfaces(t, mDockedRect, null, mOtherRect, null);
+        }
+        SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position);
+        float dimFraction = getDimFraction(position, closestDismissTarget);
+        setResizeDimLayer(t, isDismissTargetPrimary(closestDismissTarget), dimFraction);
+        if (ownTransaction) {
+            t.apply();
+            mTiles.releaseTransaction(t);
+        }
+    }
+
+    private void applyExitAnimationParallax(Rect taskRect, int position) {
+        if (mDockSide == WindowManager.DOCKED_TOP) {
+            taskRect.offset(0, (int) ((position - mExitStartPosition) * 0.25f));
+        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+            taskRect.offset((int) ((position - mExitStartPosition) * 0.25f), 0);
+        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+            taskRect.offset((int) ((mExitStartPosition - position) * 0.25f), 0);
+        }
+    }
+
+    private float getDimFraction(int position, SnapTarget dismissTarget) {
+        if (mEntranceAnimationRunning) {
+            return 0f;
+        }
+        float fraction = getSnapAlgorithm().calculateDismissingFraction(position);
+        fraction = Math.max(0, Math.min(fraction, 1f));
+        fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
+        return fraction;
+    }
+
+    /**
+     * When the snap target is dismissing one side, make sure that the dismissing side doesn't get
+     * 0 size.
+     */
+    private int restrictDismissingTaskPosition(int taskPosition, int dockSide,
+            SnapTarget snapTarget) {
+        if (snapTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(dockSide)) {
+            return Math.max(mSplitLayout.getSnapAlgorithm().getFirstSplitTarget().position,
+                    mStartPosition);
+        } else if (snapTarget.flag == SnapTarget.FLAG_DISMISS_END
+                && dockSideBottomRight(dockSide)) {
+            return Math.min(mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position,
+                    mStartPosition);
+        } else {
+            return taskPosition;
+        }
+    }
+
+    /**
+     * Applies a parallax to the task when dismissing.
+     */
+    private void applyDismissingParallax(Rect taskRect, int dockSide, SnapTarget snapTarget,
+            int position, int taskPosition) {
+        float fraction = Math.min(1, Math.max(0,
+                mSplitLayout.getSnapAlgorithm().calculateDismissingFraction(position)));
+        SnapTarget dismissTarget = null;
+        SnapTarget splitTarget = null;
+        int start = 0;
+        if (position <= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
+                && dockSideTopLeft(dockSide)) {
+            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
+            splitTarget = mSplitLayout.getSnapAlgorithm().getFirstSplitTarget();
+            start = taskPosition;
+        } else if (position >= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
+                && dockSideBottomRight(dockSide)) {
+            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissEndTarget();
+            splitTarget = mSplitLayout.getSnapAlgorithm().getLastSplitTarget();
+            start = splitTarget.position;
+        }
+        if (dismissTarget != null && fraction > 0f
+                && isDismissing(splitTarget, position, dockSide)) {
+            fraction = calculateParallaxDismissingFraction(fraction, dockSide);
+            int offsetPosition = (int) (start + fraction
+                    * (dismissTarget.position - splitTarget.position));
+            int width = taskRect.width();
+            int height = taskRect.height();
+            switch (dockSide) {
+                case WindowManager.DOCKED_LEFT:
+                    taskRect.left = offsetPosition - width;
+                    taskRect.right = offsetPosition;
+                    break;
+                case WindowManager.DOCKED_RIGHT:
+                    taskRect.left = offsetPosition + mDividerSize;
+                    taskRect.right = offsetPosition + width + mDividerSize;
+                    break;
+                case WindowManager.DOCKED_TOP:
+                    taskRect.top = offsetPosition - height;
+                    taskRect.bottom = offsetPosition;
+                    break;
+                case WindowManager.DOCKED_BOTTOM:
+                    taskRect.top = offsetPosition + mDividerSize;
+                    taskRect.bottom = offsetPosition + height + mDividerSize;
+                    break;
+            }
+        }
+    }
+
+    /**
+     * @return for a specified {@code fraction}, this returns an adjusted value that simulates a
+     *         slowing down parallax effect
+     */
+    private static float calculateParallaxDismissingFraction(float fraction, int dockSide) {
+        float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+
+        // Less parallax at the top, just because.
+        if (dockSide == WindowManager.DOCKED_TOP) {
+            result /= 2f;
+        }
+        return result;
+    }
+
+    private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) {
+        if (dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT) {
+            return position < snapTarget.position;
+        } else {
+            return position > snapTarget.position;
+        }
+    }
+
+    private boolean isDismissTargetPrimary(SnapTarget dismissTarget) {
+        return (dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
+                || (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END
+                        && dockSideBottomRight(mDockSide));
+    }
+
+    /**
+     * @return true if and only if {@code dockSide} is top or left
+     */
+    private static boolean dockSideTopLeft(int dockSide) {
+        return dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT;
+    }
+
+    /**
+     * @return true if and only if {@code dockSide} is bottom or right
+     */
+    private static boolean dockSideBottomRight(int dockSide) {
+        return dockSide == WindowManager.DOCKED_BOTTOM || dockSide == WindowManager.DOCKED_RIGHT;
+    }
+
+    @Override
+    public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
+        inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+        inoutInfo.touchableRegion.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
+                mHandle.getBottom());
+        inoutInfo.touchableRegion.op(mBackground.getLeft(), mBackground.getTop(),
+                mBackground.getRight(), mBackground.getBottom(), Op.UNION);
+    }
+
+    void onUndockingTask() {
+        int dockSide = mSplitLayout.getPrimarySplitSide();
+        if (inSplitMode()) {
+            startDragging(false /* animate */, false /* touching */);
+            SnapTarget target = dockSideTopLeft(dockSide)
+                    ? mSplitLayout.getSnapAlgorithm().getDismissEndTarget()
+                    : mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
+
+            // Don't start immediately - give a little bit time to settle the drag resize change.
+            mExitAnimationRunning = true;
+            mExitStartPosition = getCurrentPosition();
+            stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */,
+                    0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
+        }
+    }
+
+    private int calculatePositionForInsetBounds() {
+        mSplitLayout.mDisplayLayout.getStableBounds(mTmpRect);
+        return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
new file mode 100644
index 0000000..2c3ae68
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER;
+
+import android.graphics.PixelFormat;
+import android.graphics.Region;
+import android.os.Binder;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.wm.shell.common.SystemWindows;
+
+/**
+ * Manages the window parameters of the docked stack divider.
+ */
+final class DividerWindowManager {
+
+    private static final String WINDOW_TITLE = "DockedStackDivider";
+
+    final SystemWindows mSystemWindows;
+    private WindowManager.LayoutParams mLp;
+    private View mView;
+
+    DividerWindowManager(SystemWindows systemWindows) {
+        mSystemWindows = systemWindows;
+    }
+
+    /** Add a divider view */
+    void add(View view, int width, int height, int displayId) {
+        mLp = new WindowManager.LayoutParams(
+                width, height, TYPE_DOCK_DIVIDER,
+                FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
+                        | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY,
+                PixelFormat.TRANSLUCENT);
+        mLp.token = new Binder();
+        mLp.setTitle(WINDOW_TITLE);
+        mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+        mSystemWindows.addView(view, mLp, displayId, SHELL_ROOT_LAYER_DIVIDER);
+        mView = view;
+    }
+
+    void remove() {
+        if (mView != null) {
+            mSystemWindows.removeView(mView);
+        }
+        mView = null;
+    }
+
+    void setSlippery(boolean slippery) {
+        boolean changed = false;
+        if (slippery && (mLp.flags & FLAG_SLIPPERY) == 0) {
+            mLp.flags |= FLAG_SLIPPERY;
+            changed = true;
+        } else if (!slippery && (mLp.flags & FLAG_SLIPPERY) != 0) {
+            mLp.flags &= ~FLAG_SLIPPERY;
+            changed = true;
+        }
+        if (changed) {
+            mSystemWindows.updateViewLayout(mView, mLp);
+        }
+    }
+
+    void setTouchable(boolean touchable) {
+        if (mView == null) {
+            return;
+        }
+        boolean changed = false;
+        if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) {
+            mLp.flags |= FLAG_NOT_TOUCHABLE;
+            changed = true;
+        } else if (touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) != 0) {
+            mLp.flags &= ~FLAG_NOT_TOUCHABLE;
+            changed = true;
+        }
+        if (changed) {
+            mSystemWindows.updateViewLayout(mView, mLp);
+        }
+    }
+
+    /** Sets the touch region to `touchRegion`. Use null to unset.*/
+    void setTouchRegion(Region touchRegion) {
+        if (mView == null) {
+            return;
+        }
+        mSystemWindows.setTouchableRegion(mView, touchRegion);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
new file mode 100644
index 0000000..abff69c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
+import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.widget.TextView;
+
+import com.android.wm.shell.R;
+
+/**
+ * Translucent activity that gets started on top of a task in multi-window to inform the user that
+ * we forced the activity below to be resizable.
+ */
+public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {
+
+    public static final String EXTRA_FORCED_RESIZEABLE_REASON = "extra_forced_resizeable_reason";
+
+    private static final long DISMISS_DELAY = 2500;
+
+    private final Runnable mFinishRunnable = new Runnable() {
+        @Override
+        public void run() {
+            finish();
+        }
+    };
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.forced_resizable_activity);
+        TextView tv = findViewById(com.android.internal.R.id.message);
+        int reason = getIntent().getIntExtra(EXTRA_FORCED_RESIZEABLE_REASON, -1);
+        String text;
+        switch (reason) {
+            case FORCED_RESIZEABLE_REASON_SPLIT_SCREEN:
+                text = getString(R.string.dock_forced_resizable);
+                break;
+            case FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY:
+                text = getString(R.string.forced_resizable_secondary_display);
+                break;
+            default:
+                throw new IllegalArgumentException("Unexpected forced resizeable reason: "
+                        + reason);
+        }
+        tv.setText(text);
+        getWindow().setTitle(text);
+        getWindow().getDecorView().setOnTouchListener(this);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        getWindow().getDecorView().postDelayed(mFinishRunnable, DISMISS_DELAY);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        finish();
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        finish();
+        return true;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        finish();
+        return true;
+    }
+
+    @Override
+    public void finish() {
+        super.finish();
+        overridePendingTransition(0, R.anim.forced_resizable_exit);
+    }
+
+    @Override
+    public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
+        // Do nothing
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
new file mode 100644
index 0000000..ee5c9bc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+
+import static com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.widget.Toast;
+
+import com.android.wm.shell.R;
+
+import java.util.function.Consumer;
+
+/**
+ * Controller that decides when to show the {@link ForcedResizableInfoActivity}.
+ */
+final class ForcedResizableInfoActivityController implements DividerView.DividerCallbacks {
+
+    private static final String SELF_PACKAGE_NAME = "com.android.systemui";
+
+    private static final int TIMEOUT = 1000;
+    private final Context mContext;
+    private final Handler mHandler = new Handler();
+    private final ArraySet<PendingTaskRecord> mPendingTasks = new ArraySet<>();
+    private final ArraySet<String> mPackagesShownInSession = new ArraySet<>();
+    private boolean mDividerDragging;
+
+    private final Runnable mTimeoutRunnable = this::showPending;
+
+    private final Consumer<Boolean> mDockedStackExistsListener = exists -> {
+        if (!exists) {
+            mPackagesShownInSession.clear();
+        }
+    };
+
+    /** Record of force resized task that's pending to be handled. */
+    private class PendingTaskRecord {
+        int mTaskId;
+        /**
+         * {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SPLIT_SCREEN} or
+         * {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY}
+         */
+        int mReason;
+
+        PendingTaskRecord(int taskId, int reason) {
+            this.mTaskId = taskId;
+            this.mReason = reason;
+        }
+    }
+
+    ForcedResizableInfoActivityController(Context context,
+            LegacySplitScreenController splitScreenController) {
+        mContext = context;
+        splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
+    }
+
+    @Override
+    public void onDraggingStart() {
+        mDividerDragging = true;
+        mHandler.removeCallbacks(mTimeoutRunnable);
+    }
+
+    @Override
+    public void onDraggingEnd() {
+        mDividerDragging = false;
+        showPending();
+    }
+
+    void onAppTransitionFinished() {
+        if (!mDividerDragging) {
+            showPending();
+        }
+    }
+
+    void activityForcedResizable(String packageName, int taskId, int reason) {
+        if (debounce(packageName)) {
+            return;
+        }
+        mPendingTasks.add(new PendingTaskRecord(taskId, reason));
+        postTimeout();
+    }
+
+    void activityDismissingSplitScreen() {
+        Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+                Toast.LENGTH_SHORT).show();
+    }
+
+    void activityLaunchOnSecondaryDisplayFailed() {
+        Toast.makeText(mContext, R.string.activity_launch_on_secondary_display_failed_text,
+                Toast.LENGTH_SHORT).show();
+    }
+
+    private void showPending() {
+        mHandler.removeCallbacks(mTimeoutRunnable);
+        for (int i = mPendingTasks.size() - 1; i >= 0; i--) {
+            PendingTaskRecord pendingRecord = mPendingTasks.valueAt(i);
+            Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
+            ActivityOptions options = ActivityOptions.makeBasic();
+            options.setLaunchTaskId(pendingRecord.mTaskId);
+            // Set as task overlay and allow to resume, so that when an app enters split-screen and
+            // becomes paused, the overlay will still be shown.
+            options.setTaskOverlay(true, true /* canResume */);
+            intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.mReason);
+            mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
+        }
+        mPendingTasks.clear();
+    }
+
+    private void postTimeout() {
+        mHandler.removeCallbacks(mTimeoutRunnable);
+        mHandler.postDelayed(mTimeoutRunnable, TIMEOUT);
+    }
+
+    private boolean debounce(String packageName) {
+        if (packageName == null) {
+            return false;
+        }
+
+        // We launch ForcedResizableInfoActivity into a task that was forced resizable, so that
+        // triggers another notification. So ignore our own activity.
+        if (SELF_PACKAGE_NAME.equals(packageName)) {
+            return true;
+        }
+        boolean debounce = mPackagesShownInSession.contains(packageName);
+        mPackagesShownInSession.add(packageName);
+        return debounce;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
new file mode 100644
index 0000000..477ec33
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
@@ -0,0 +1,314 @@
+/*
+ * 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.legacysplitscreen;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.util.TypedValue;
+import android.window.WindowContainerTransaction;
+
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DockedDividerUtils;
+import com.android.wm.shell.common.DisplayLayout;
+
+/**
+ * Handles split-screen related internal display layout. In general, this represents the
+ * WM-facing understanding of the splits.
+ */
+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;
+
+    LegacySplitScreenTaskListener mTiles;
+    DisplayLayout mDisplayLayout;
+    Context mContext;
+
+    // Lazy stuff
+    boolean mResourcesValid = false;
+    int mDividerSize;
+    int mDividerSizeInactive;
+    private DividerSnapAlgorithm mSnapAlgorithm = null;
+    private DividerSnapAlgorithm mMinimizedSnapAlgorithm = null;
+    Rect mPrimary = null;
+    Rect mSecondary = null;
+    Rect mAdjustedPrimary = null;
+    Rect mAdjustedSecondary = null;
+
+    public LegacySplitDisplayLayout(Context ctx, DisplayLayout dl,
+            LegacySplitScreenTaskListener taskTiles) {
+        mTiles = taskTiles;
+        mDisplayLayout = dl;
+        mContext = ctx;
+    }
+
+    void rotateTo(int newRotation) {
+        mDisplayLayout.rotateTo(mContext.getResources(), newRotation);
+        final Configuration config = new Configuration();
+        config.unset();
+        config.orientation = mDisplayLayout.getOrientation();
+        Rect tmpRect = new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+        tmpRect.inset(mDisplayLayout.nonDecorInsets());
+        config.windowConfiguration.setAppBounds(tmpRect);
+        tmpRect.set(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+        tmpRect.inset(mDisplayLayout.stableInsets());
+        config.screenWidthDp = (int) (tmpRect.width() / mDisplayLayout.density());
+        config.screenHeightDp = (int) (tmpRect.height() / mDisplayLayout.density());
+        mContext = mContext.createConfigurationContext(config);
+        mSnapAlgorithm = null;
+        mMinimizedSnapAlgorithm = null;
+        mResourcesValid = false;
+    }
+
+    private void updateResources() {
+        if (mResourcesValid) {
+            return;
+        }
+        mResourcesValid = true;
+        Resources res = mContext.getResources();
+        mDividerSize = DockedDividerUtils.getDividerSize(res,
+                DockedDividerUtils.getDividerInsets(res));
+        mDividerSizeInactive = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, DIVIDER_WIDTH_INACTIVE_DP, res.getDisplayMetrics());
+    }
+
+    int getPrimarySplitSide() {
+        switch (mDisplayLayout.getNavigationBarPosition(mContext.getResources())) {
+            case DisplayLayout.NAV_BAR_BOTTOM:
+                return mDisplayLayout.isLandscape() ? DOCKED_LEFT : DOCKED_TOP;
+            case DisplayLayout.NAV_BAR_LEFT:
+                return DOCKED_RIGHT;
+            case DisplayLayout.NAV_BAR_RIGHT:
+                return DOCKED_LEFT;
+            default:
+                return DOCKED_INVALID;
+        }
+    }
+
+    DividerSnapAlgorithm getSnapAlgorithm() {
+        if (mSnapAlgorithm == null) {
+            updateResources();
+            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
+            mSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
+                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
+                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide());
+        }
+        return mSnapAlgorithm;
+    }
+
+    DividerSnapAlgorithm getMinimizedSnapAlgorithm(boolean homeStackResizable) {
+        if (mMinimizedSnapAlgorithm == null) {
+            updateResources();
+            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
+            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
+                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
+                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide(),
+                    true /* isMinimized */, homeStackResizable);
+        }
+        return mMinimizedSnapAlgorithm;
+    }
+
+    void resizeSplits(int position) {
+        mPrimary = mPrimary == null ? new Rect() : mPrimary;
+        mSecondary = mSecondary == null ? new Rect() : mSecondary;
+        calcSplitBounds(position, mPrimary, mSecondary);
+    }
+
+    void resizeSplits(int position, WindowContainerTransaction t) {
+        resizeSplits(position);
+        t.setBounds(mTiles.mPrimary.token, mPrimary);
+        t.setBounds(mTiles.mSecondary.token, mSecondary);
+
+        t.setSmallestScreenWidthDp(mTiles.mPrimary.token,
+                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mPrimary));
+        t.setSmallestScreenWidthDp(mTiles.mSecondary.token,
+                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mSecondary));
+    }
+
+    void calcSplitBounds(int position, @NonNull Rect outPrimary, @NonNull Rect outSecondary) {
+        int dockSide = getPrimarySplitSide();
+        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outPrimary,
+                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
+
+        DockedDividerUtils.calculateBoundsForPosition(position,
+                DockedDividerUtils.invertDockSide(dockSide), outSecondary, mDisplayLayout.width(),
+                mDisplayLayout.height(), mDividerSize);
+    }
+
+    Rect calcResizableMinimizedHomeStackBounds() {
+        DividerSnapAlgorithm.SnapTarget miniMid =
+                getMinimizedSnapAlgorithm(true /* resizable */).getMiddleTarget();
+        Rect homeBounds = new Rect();
+        DockedDividerUtils.calculateBoundsForPosition(miniMid.position,
+                DockedDividerUtils.invertDockSide(getPrimarySplitSide()), homeBounds,
+                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
+        return homeBounds;
+    }
+
+    /**
+     * Updates the adjustment depending on it's current state.
+     */
+    void updateAdjustedBounds(int currImeTop, int hiddenTop, int shownTop) {
+        adjustForIME(mDisplayLayout, currImeTop, hiddenTop, shownTop, mDividerSize,
+                mDividerSizeInactive, mPrimary, mSecondary);
+    }
+
+    /** Assumes top/bottom split. Splits are not adjusted for left/right splits. */
+    private void adjustForIME(DisplayLayout dl, int currImeTop, int hiddenTop, int shownTop,
+            int dividerWidth, int dividerWidthInactive, Rect primaryBounds, Rect secondaryBounds) {
+        if (mAdjustedPrimary == null) {
+            mAdjustedPrimary = new Rect();
+            mAdjustedSecondary = new Rect();
+        }
+
+        final Rect displayStableRect = new Rect();
+        dl.getStableBounds(displayStableRect);
+
+        final float shownFraction = ((float) (currImeTop - hiddenTop)) / (shownTop - hiddenTop);
+        final int currDividerWidth =
+                (int) (dividerWidthInactive * shownFraction + dividerWidth * (1.f - shownFraction));
+
+        // Calculate the highest we can move the bottom of the top stack to keep 30% visible.
+        final int minTopStackBottom = displayStableRect.top
+                + (int) ((mPrimary.bottom - displayStableRect.top) * ADJUSTED_STACK_FRACTION_MIN);
+        // Based on that, calculate the maximum amount we'll allow the ime to shift things.
+        final int maxOffset = mPrimary.bottom - minTopStackBottom;
+        // Calculate how much we would shift things without limits (basically the height of ime).
+        final int desiredOffset = hiddenTop - shownTop;
+        // Calculate an "adjustedTop" which is the currImeTop but restricted by our constraints.
+        // We want an effect where the adjustment only occurs during the "highest" portion of the
+        // ime animation. This is done by shifting the adjustment values by the difference in
+        // offsets (effectively playing the whole adjustment animation some fixed amount of pixels
+        // below the ime top).
+        final int topCorrection = Math.max(0, desiredOffset - maxOffset);
+        final int adjustedTop = currImeTop + topCorrection;
+        // The actual yOffset is the distance between adjustedTop and the bottom of the display.
+        // Since our adjustedTop values are playing "below" the ime, we clamp at 0 so we only
+        // see adjustment upward.
+        final int yOffset = Math.max(0, dl.height() - adjustedTop);
+
+        // TOP
+        // Reduce the offset by an additional small amount to squish the divider bar.
+        mAdjustedPrimary.set(primaryBounds);
+        mAdjustedPrimary.offset(0, -yOffset + (dividerWidth - currDividerWidth));
+
+        // BOTTOM
+        mAdjustedSecondary.set(secondaryBounds);
+        mAdjustedSecondary.offset(0, -yOffset);
+    }
+
+    static int getSmallestWidthDpForBounds(@NonNull Context context, DisplayLayout dl,
+            Rect bounds) {
+        int dividerSize = DockedDividerUtils.getDividerSize(context.getResources(),
+                DockedDividerUtils.getDividerInsets(context.getResources()));
+
+        int minWidth = Integer.MAX_VALUE;
+
+        // Go through all screen orientations and find the orientation in which the task has the
+        // smallest width.
+        Rect tmpRect = new Rect();
+        Rect rotatedDisplayRect = new Rect();
+        Rect displayRect = new Rect(0, 0, dl.width(), dl.height());
+
+        DisplayLayout tmpDL = new DisplayLayout();
+        for (int rotation = 0; rotation < 4; rotation++) {
+            tmpDL.set(dl);
+            tmpDL.rotateTo(context.getResources(), rotation);
+            DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);
+
+            tmpRect.set(bounds);
+            DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
+            rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
+            final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
+                    tmpDL.getOrientation());
+            final int position = DockedDividerUtils.calculatePositionForBounds(tmpRect, dockSide,
+                    dividerSize);
+
+            final int snappedPosition =
+                    snap.calculateNonDismissingSnapTarget(position).position;
+            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, tmpRect,
+                    tmpDL.width(), tmpDL.height(), dividerSize);
+            Rect insettedDisplay = new Rect(rotatedDisplayRect);
+            insettedDisplay.inset(tmpDL.stableInsets());
+            tmpRect.intersect(insettedDisplay);
+            minWidth = Math.min(tmpRect.width(), minWidth);
+        }
+        return (int) (minWidth / dl.density());
+    }
+
+    static DividerSnapAlgorithm initSnapAlgorithmForRotation(Context context, DisplayLayout dl,
+            int dividerSize) {
+        final Configuration config = new Configuration();
+        config.unset();
+        config.orientation = dl.getOrientation();
+        Rect tmpRect = new Rect(0, 0, dl.width(), dl.height());
+        tmpRect.inset(dl.nonDecorInsets());
+        config.windowConfiguration.setAppBounds(tmpRect);
+        tmpRect.set(0, 0, dl.width(), dl.height());
+        tmpRect.inset(dl.stableInsets());
+        config.screenWidthDp = (int) (tmpRect.width() / dl.density());
+        config.screenHeightDp = (int) (tmpRect.height() / dl.density());
+        final Context rotationContext = context.createConfigurationContext(config);
+        return new DividerSnapAlgorithm(
+                rotationContext.getResources(), dl.width(), dl.height(), dividerSize,
+                config.orientation == ORIENTATION_PORTRAIT, dl.stableInsets());
+    }
+
+    /**
+     * Get the current primary-split side. Determined by its location of {@param bounds} within
+     * {@param displayRect} but if both are the same, it will try to dock to each side and determine
+     * if allowed in its respected {@param orientation}.
+     *
+     * @param bounds bounds of the primary split task to get which side is docked
+     * @param displayRect bounds of the display that contains the primary split task
+     * @param orientation the origination of device
+     * @return current primary-split side
+     */
+    static int getPrimarySplitSide(Rect bounds, Rect displayRect, int orientation) {
+        if (orientation == ORIENTATION_PORTRAIT) {
+            // Portrait mode, docked either at the top or the bottom.
+            final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
+            if (diff < 0) {
+                return DOCKED_BOTTOM;
+            } else {
+                // Top is default
+                return DOCKED_TOP;
+            }
+        } else if (orientation == ORIENTATION_LANDSCAPE) {
+            // Landscape mode, docked either on the left or on the right.
+            final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
+            if (diff < 0) {
+                return DOCKED_RIGHT;
+            }
+            return DOCKED_LEFT;
+        }
+        return DOCKED_INVALID;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
new file mode 100644
index 0000000..499a9c5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.legacysplitscreen;
+
+import android.graphics.Rect;
+import android.window.WindowContainerToken;
+
+import com.android.wm.shell.common.annotations.ExternalThread;
+
+import java.io.PrintWriter;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Interface to engage split screen feature.
+ */
+@ExternalThread
+public interface LegacySplitScreen {
+    /** Called when keyguard showing state changed. */
+    void onKeyguardVisibilityChanged(boolean isShowing);
+
+    /** Returns {@link DividerView}. */
+    DividerView getDividerView();
+
+    /** Returns {@code true} if one of the split screen is in minimized mode. */
+    boolean isMinimized();
+
+    /** Returns {@code true} if the home stack is resizable. */
+    boolean isHomeStackResizable();
+
+    /** Returns {@code true} if the divider is visible. */
+    boolean isDividerVisible();
+
+    /** Switch to minimized state if appropriate. */
+    void setMinimized(boolean minimized);
+
+    /** Called when there's a task undocking. */
+    void onUndockingTask();
+
+    /** Called when app transition finished. */
+    void onAppTransitionFinished();
+
+    /** Dumps current status of Split Screen. */
+    void dump(PrintWriter pw);
+
+    /** Registers listener that gets called whenever the existence of the divider changes. */
+    void registerInSplitScreenListener(Consumer<Boolean> listener);
+
+    /** Unregisters listener that gets called whenever the existence of the divider changes. */
+    void unregisterInSplitScreenListener(Consumer<Boolean> listener);
+
+    /** Registers listener that gets called whenever the split screen bounds changes. */
+    void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener);
+
+    /** @return the container token for the secondary split root task. */
+    WindowContainerToken getSecondaryRoot();
+
+    /**
+     * Splits the primary task if feasible, this is to preserve legacy way to toggle split screen.
+     * Like triggering split screen through long pressing recents app button or through
+     * {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN}.
+     *
+     * @return {@code true} if it successes to split the primary task.
+     */
+    boolean splitPrimaryTask();
+
+    /**
+     * Exits the split to make the primary task fullscreen.
+     */
+    void dismissSplitToPrimaryTask();
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
new file mode 100644
index 0000000..d88696d
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -0,0 +1,604 @@
+/*
+ * 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.legacysplitscreen;
+
+import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Toast;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayChangeController;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.common.TransactionPool;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Controls split screen feature.
+ */
+public class LegacySplitScreenController implements LegacySplitScreen,
+        DisplayController.OnDisplaysChangedListener {
+    static final boolean DEBUG = false;
+
+    private static final String TAG = "SplitScreenCtrl";
+    private static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+
+    private final Context mContext;
+    private final DisplayChangeController.OnDisplayChangingListener mRotationController;
+    private final DisplayController mDisplayController;
+    private final DisplayImeController mImeController;
+    private final DividerImeController mImePositionProcessor;
+    private final DividerState mDividerState = new DividerState();
+    private final ForcedResizableInfoActivityController mForcedResizableController;
+    private final Handler mHandler;
+    private final LegacySplitScreenTaskListener mSplits;
+    private final SystemWindows mSystemWindows;
+    final TransactionPool mTransactionPool;
+    private final WindowManagerProxy mWindowManagerProxy;
+    private final TaskOrganizer mTaskOrganizer;
+
+    private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
+            = new CopyOnWriteArrayList<>();
+    private final ArrayList<WeakReference<BiConsumer<Rect, Rect>>> mBoundsChangedListeners =
+            new ArrayList<>();
+
+
+    private DividerWindowManager mWindowManager;
+    private DividerView mView;
+
+    // Keeps track of real-time split geometry including snap positions and ime adjustments
+    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 LegacySplitDisplayLayout mRotateSplitLayout;
+
+    private boolean mIsKeyguardShowing;
+    private boolean mVisible = false;
+    private boolean mMinimized = false;
+    private boolean mAdjustedForIme = false;
+    private boolean mHomeStackResizable = false;
+
+    public LegacySplitScreenController(Context context,
+            DisplayController displayController, SystemWindows systemWindows,
+            DisplayImeController imeController, Handler handler, TransactionPool transactionPool,
+            ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
+            TaskStackListenerImpl taskStackListener) {
+        mContext = context;
+        mDisplayController = displayController;
+        mSystemWindows = systemWindows;
+        mImeController = imeController;
+        mHandler = handler;
+        mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
+        mTransactionPool = transactionPool;
+        mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
+        mTaskOrganizer = shellTaskOrganizer;
+        mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
+        mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
+                shellTaskOrganizer);
+        mRotationController =
+                (display, fromRotation, toRotation, wct) -> {
+                    if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) {
+                        return;
+                    }
+                    WindowContainerTransaction t = new WindowContainerTransaction();
+                    DisplayLayout displayLayout =
+                            new DisplayLayout(mDisplayController.getDisplayLayout(display));
+                    LegacySplitDisplayLayout sdl =
+                            new LegacySplitDisplayLayout(mContext, displayLayout, mSplits);
+                    sdl.rotateTo(toRotation);
+                    mRotateSplitLayout = sdl;
+                    final int position = isDividerVisible()
+                            ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
+                            : mView.getCurrentPosition())
+                            // snap resets to middle target when not in split-mode
+                            : sdl.getSnapAlgorithm().getMiddleTarget().position;
+                    DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
+                    final DividerSnapAlgorithm.SnapTarget target =
+                            snap.calculateNonDismissingSnapTarget(position);
+                    sdl.resizeSplits(target.position, t);
+
+                    if (isSplitActive() && mHomeStackResizable) {
+                        mWindowManagerProxy
+                                .applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
+                    }
+                    if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) {
+                        // Because sync transactions are serialized, its possible for an "older"
+                        // bounds-change to get applied after a screen rotation. In that case, we
+                        // want to actually defer on that rather than apply immediately. Of course,
+                        // this means that the bounds may not change until after the rotation so
+                        // the user might see some artifacts. This should be rare.
+                        Slog.w(TAG, "Screen rotated while other operations were pending, this may"
+                                + " result in some graphical artifacts.");
+                    } else {
+                        wct.merge(t, true /* transfer */);
+                    }
+                };
+
+        mWindowManager = new DividerWindowManager(mSystemWindows);
+        mDisplayController.addDisplayWindowListener(this);
+        // Don't initialize the divider or anything until we get the default display.
+
+        taskStackListener.addListener(
+                new TaskStackListenerCallback() {
+                    @Override
+                    public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+                            boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+                        if (!wasVisible || task.getWindowingMode()
+                                != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                                || !mSplits.isSplitScreenSupported()) {
+                            return;
+                        }
+
+                        if (isMinimized()) {
+                            onUndockingTask();
+                        }
+                    }
+
+                    @Override
+                    public void onActivityForcedResizable(String packageName, int taskId,
+                            int reason) {
+                        mForcedResizableController.activityForcedResizable(packageName, taskId,
+                                reason);
+                    }
+
+                    @Override
+                    public void onActivityDismissingDockedStack() {
+                        mForcedResizableController.activityDismissingSplitScreen();
+                    }
+
+                    @Override
+                    public void onActivityLaunchOnSecondaryDisplayFailed() {
+                        mForcedResizableController.activityLaunchOnSecondaryDisplayFailed();
+                    }
+                });
+    }
+
+    void onSplitScreenSupported() {
+        // Set starting tile bounds based on middle target
+        final WindowContainerTransaction tct = new WindowContainerTransaction();
+        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+        mSplitLayout.resizeSplits(midPos, tct);
+        mTaskOrganizer.applyTransaction(tct);
+    }
+
+    @Override
+    public void onKeyguardVisibilityChanged(boolean showing) {
+        if (!isSplitActive() || mView == null) {
+            return;
+        }
+        mView.setHidden(showing);
+        if (!showing) {
+            mImePositionProcessor.updateAdjustForIme();
+        }
+        mIsKeyguardShowing = showing;
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+        mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+                mDisplayController.getDisplayLayout(displayId), mSplits);
+        mImeController.addPositionProcessor(mImePositionProcessor);
+        mDisplayController.addDisplayChangingController(mRotationController);
+        if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
+            removeDivider();
+            return;
+        }
+        try {
+            mSplits.init();
+        } catch (Exception e) {
+            Slog.e(TAG, "Failed to register docked stack listener", e);
+            removeDivider();
+            return;
+        }
+    }
+
+    @Override
+    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+        if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
+            return;
+        }
+        mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+                mDisplayController.getDisplayLayout(displayId), mSplits);
+        if (mRotateSplitLayout == null) {
+            int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+            final WindowContainerTransaction tct = new WindowContainerTransaction();
+            mSplitLayout.resizeSplits(midPos, tct);
+            mTaskOrganizer.applyTransaction(tct);
+        } else if (mSplitLayout.mDisplayLayout.rotation()
+                == mRotateSplitLayout.mDisplayLayout.rotation()) {
+            mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
+            mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
+            mRotateSplitLayout = null;
+        }
+        if (isSplitActive()) {
+            update(newConfig);
+        }
+    }
+
+    /** Posts task to handler dealing with divider. */
+    void post(Runnable task) {
+        mHandler.post(task);
+    }
+
+    @Override
+    public DividerView getDividerView() {
+        return mView;
+    }
+
+    @Override
+    public boolean isMinimized() {
+        return mMinimized;
+    }
+
+    @Override
+    public boolean isHomeStackResizable() {
+        return mHomeStackResizable;
+    }
+
+    @Override
+    public boolean isDividerVisible() {
+        return mView != null && mView.getVisibility() == View.VISIBLE;
+    }
+
+    /**
+     * This indicates that at-least one of the splits has content. This differs from
+     * isDividerVisible because the divider is only visible once *everything* is in split mode
+     * while this only cares if some things are (eg. while entering/exiting as well).
+     */
+    private boolean isSplitActive() {
+        return mSplits.mPrimary != null && mSplits.mSecondary != null
+                && (mSplits.mPrimary.topActivityType != ACTIVITY_TYPE_UNDEFINED
+                || mSplits.mSecondary.topActivityType != ACTIVITY_TYPE_UNDEFINED);
+    }
+
+    private void addDivider(Configuration configuration) {
+        Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
+        mView = (DividerView)
+                LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
+        DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
+        mView.injectDependencies(this, mWindowManager, mDividerState, mForcedResizableController,
+                mSplits, mSplitLayout, mImePositionProcessor, mWindowManagerProxy);
+        mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
+        mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, null /* transaction */);
+        final int size = dctx.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
+        final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
+        final int width = landscape ? size : displayLayout.width();
+        final int height = landscape ? displayLayout.height() : size;
+        mWindowManager.add(mView, width, height, mContext.getDisplayId());
+    }
+
+    private void removeDivider() {
+        if (mView != null) {
+            mView.onDividerRemoved();
+        }
+        mWindowManager.remove();
+    }
+
+    private void update(Configuration configuration) {
+        final boolean isDividerHidden = mView != null && mIsKeyguardShowing;
+
+        removeDivider();
+        addDivider(configuration);
+
+        if (mMinimized) {
+            mView.setMinimizedDockStack(true, mHomeStackResizable, null /* transaction */);
+            updateTouchable();
+        }
+        mView.setHidden(isDividerHidden);
+    }
+
+    void onTaskVanished() {
+        mHandler.post(this::removeDivider);
+    }
+
+    private void updateVisibility(final boolean visible) {
+        if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
+        if (mVisible != visible) {
+            mVisible = visible;
+            mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+            if (visible) {
+                mView.enterSplitMode(mHomeStackResizable);
+                // Update state because animations won't finish.
+                mWindowManagerProxy.runInSync(
+                        t -> mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, t));
+
+            } else {
+                mView.exitSplitMode();
+                mWindowManagerProxy.runInSync(
+                        t -> mView.setMinimizedDockStack(false, mHomeStackResizable, t));
+            }
+            // Notify existence listeners
+            synchronized (mDockedStackExistsListeners) {
+                mDockedStackExistsListeners.removeIf(wf -> {
+                    Consumer<Boolean> l = wf.get();
+                    if (l != null) l.accept(visible);
+                    return l == null;
+                });
+            }
+        }
+    }
+
+    @Override
+    public void setMinimized(final boolean minimized) {
+        if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
+        mHandler.post(() -> {
+            if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
+            if (!mVisible) {
+                return;
+            }
+            setHomeMinimized(minimized);
+        });
+    }
+
+    private void setHomeMinimized(final boolean minimized) {
+        if (DEBUG) {
+            Slog.d(TAG, "setHomeMinimized  min:" + mMinimized + "->" + minimized + " hrsz:"
+                    + mHomeStackResizable + " split:" + isDividerVisible());
+        }
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        final boolean minimizedChanged = mMinimized != minimized;
+        // Update minimized state
+        if (minimizedChanged) {
+            mMinimized = minimized;
+        }
+        // Always set this because we could be entering split when mMinimized is already true
+        wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
+
+        // Sync state to DividerView if it exists.
+        if (mView != null) {
+            final int displayId = mView.getDisplay() != null
+                    ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY;
+            // pause ime here (before updateMinimizedDockedStack)
+            if (mMinimized) {
+                mImePositionProcessor.pause(displayId);
+            }
+            if (minimizedChanged) {
+                // This conflicts with IME adjustment, so only call it when things change.
+                mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable);
+            }
+            if (!mMinimized) {
+                // afterwards so it can end any animations started in view
+                mImePositionProcessor.resume(displayId);
+            }
+        }
+        updateTouchable();
+
+        // If we are only setting focusability, a sync transaction isn't necessary (in fact it
+        // can interrupt other animations), so see if it can be submitted on pending instead.
+        if (!mWindowManagerProxy.queueSyncTransactionIfWaiting(wct)) {
+            mTaskOrganizer.applyTransaction(wct);
+        }
+    }
+
+    void setAdjustedForIme(boolean adjustedForIme) {
+        if (mAdjustedForIme == adjustedForIme) {
+            return;
+        }
+        mAdjustedForIme = adjustedForIme;
+        updateTouchable();
+    }
+
+    private void updateTouchable() {
+        mWindowManager.setTouchable(!mAdjustedForIme);
+    }
+
+    @Override
+    public void onUndockingTask() {
+        if (mView != null) {
+            mView.onUndockingTask();
+        }
+    }
+
+    @Override
+    public void onAppTransitionFinished() {
+        if (mView == null) {
+            return;
+        }
+        mForcedResizableController.onAppTransitionFinished();
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("  mVisible="); pw.println(mVisible);
+        pw.print("  mMinimized="); pw.println(mMinimized);
+        pw.print("  mAdjustedForIme="); pw.println(mAdjustedForIme);
+    }
+
+    long getAnimDuration() {
+        float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
+                Settings.Global.TRANSITION_ANIMATION_SCALE,
+                mContext.getResources().getFloat(
+                        com.android.internal.R.dimen
+                                .config_appTransitionAnimationDurationScaleDefault));
+        final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
+        return (long) (transitionDuration * transitionScale);
+    }
+
+    @Override
+    public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+        listener.accept(isDividerVisible());
+        synchronized (mDockedStackExistsListeners) {
+            mDockedStackExistsListeners.add(new WeakReference<>(listener));
+        }
+    }
+
+    @Override
+    public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+        synchronized (mDockedStackExistsListeners) {
+            for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
+                if (mDockedStackExistsListeners.get(i) == listener) {
+                    mDockedStackExistsListeners.remove(i);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
+        synchronized (mBoundsChangedListeners) {
+            mBoundsChangedListeners.add(new WeakReference<>(listener));
+        }
+    }
+
+    @Override
+    public boolean splitPrimaryTask() {
+        try {
+            if (ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED
+                    || isSplitActive()) {
+                return false;
+            }
+
+            // Try fetching the top running task.
+            final List<RunningTaskInfo> runningTasks =
+                    ActivityTaskManager.getInstance().getTasks(1 /* maxNum */);
+            if (runningTasks == null || runningTasks.isEmpty()) {
+                return false;
+            }
+            // Note: The set of running tasks from the system is ordered by recency.
+            final RunningTaskInfo topRunningTask = runningTasks.get(0);
+            final int activityType = topRunningTask.getActivityType();
+            if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
+                return false;
+            }
+
+            if (!topRunningTask.supportsSplitScreenMultiWindow) {
+                Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+                        Toast.LENGTH_SHORT).show();
+                return false;
+            }
+
+            return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(
+                    topRunningTask.taskId, true /* onTop */);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public void dismissSplitToPrimaryTask() {
+        startDismissSplit(true /* toPrimaryTask */);
+    }
+
+    /** Notifies the bounds of split screen changed. */
+    void notifyBoundsChanged(Rect secondaryWindowBounds, Rect secondaryWindowInsets) {
+        synchronized (mBoundsChangedListeners) {
+            mBoundsChangedListeners.removeIf(wf -> {
+                BiConsumer<Rect, Rect> l = wf.get();
+                if (l != null) l.accept(secondaryWindowBounds, secondaryWindowInsets);
+                return l == null;
+            });
+        }
+    }
+
+    void startEnterSplit() {
+        update(mDisplayController.getDisplayContext(
+                mContext.getDisplayId()).getResources().getConfiguration());
+        // Set resizable directly here because applyEnterSplit already resizes home stack.
+        mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
+    }
+
+    void startDismissSplit(boolean toPrimaryTask) {
+        mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, !toPrimaryTask);
+        updateVisibility(false /* visible */);
+        mMinimized = false;
+        // Resets divider bar position to undefined, so new divider bar will apply default position
+        // next time entering split mode.
+        mDividerState.mRatioPositionBeforeMinimized = 0;
+        removeDivider();
+        mImePositionProcessor.reset();
+    }
+
+    void ensureMinimizedSplit() {
+        setHomeMinimized(true /* minimized */);
+        if (mView != null && !isDividerVisible()) {
+            // Wasn't in split-mode yet, so enter now.
+            if (DEBUG) {
+                Slog.d(TAG, " entering split mode with minimized=true");
+            }
+            updateVisibility(true /* visible */);
+        }
+    }
+
+    void ensureNormalSplit() {
+        setHomeMinimized(false /* minimized */);
+        if (mView != null && !isDividerVisible()) {
+            // Wasn't in split-mode, so enter now.
+            if (DEBUG) {
+                Slog.d(TAG, " enter split mode unminimized ");
+            }
+            updateVisibility(true /* visible */);
+        }
+    }
+
+    LegacySplitDisplayLayout getSplitLayout() {
+        return mSplitLayout;
+    }
+
+    WindowManagerProxy getWmProxy() {
+        return mWindowManagerProxy;
+    }
+
+    @Override
+    public WindowContainerToken getSecondaryRoot() {
+        if (mSplits == null || mSplits.mSecondary == null) {
+            return null;
+        }
+        return mSplits.mSecondary.token;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
new file mode 100644
index 0000000..02c82de
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
@@ -0,0 +1,321 @@
+/*
+ * 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.legacysplitscreen;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.Transitions;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+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;
+    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
+
+    RunningTaskInfo mPrimary;
+    RunningTaskInfo mSecondary;
+    SurfaceControl mPrimarySurface;
+    SurfaceControl mSecondarySurface;
+    SurfaceControl mPrimaryDim;
+    SurfaceControl mSecondaryDim;
+    Rect mHomeBounds = new Rect();
+    final LegacySplitScreenController mSplitScreenController;
+    private boolean mSplitScreenSupported = false;
+
+    final SurfaceSession mSurfaceSession = new SurfaceSession();
+
+    LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController,
+                    ShellTaskOrganizer shellTaskOrganizer,
+                    SyncTransactionQueue syncQueue) {
+        mSplitScreenController = splitScreenController;
+        mTaskOrganizer = shellTaskOrganizer;
+        mSyncQueue = syncQueue;
+    }
+
+    void init() {
+        synchronized (this) {
+            try {
+                mTaskOrganizer.createRootTask(
+                        DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, this);
+                mTaskOrganizer.createRootTask(
+                        DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, this);
+            } catch (Exception e) {
+                // teardown to prevent callbacks
+                mTaskOrganizer.removeListener(this);
+                throw e;
+            }
+        }
+    }
+
+    boolean isSplitScreenSupported() {
+        return mSplitScreenSupported;
+    }
+
+    SurfaceControl.Transaction getTransaction() {
+        return mSplitScreenController.mTransactionPool.acquire();
+    }
+
+    void releaseTransaction(SurfaceControl.Transaction t) {
+        mSplitScreenController.mTransactionPool.release(t);
+    }
+
+    @Override
+    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+        synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                handleChildTaskAppeared(taskInfo, leash);
+                return;
+            }
+
+            final int winMode = taskInfo.getWindowingMode();
+            if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+                ProtoLog.v(WM_SHELL_TASK_ORG,
+                        "%s onTaskAppeared Primary taskId=%d", TAG, taskInfo.taskId);
+                mPrimary = taskInfo;
+                mPrimarySurface = leash;
+            } else if (winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+                ProtoLog.v(WM_SHELL_TASK_ORG,
+                        "%s onTaskAppeared Secondary taskId=%d", TAG, taskInfo.taskId);
+                mSecondary = taskInfo;
+                mSecondarySurface = leash;
+            } else {
+                ProtoLog.v(WM_SHELL_TASK_ORG, "%s onTaskAppeared unknown taskId=%d winMode=%d",
+                        TAG, taskInfo.taskId, winMode);
+            }
+
+            if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) {
+                mSplitScreenSupported = true;
+                mSplitScreenController.onSplitScreenSupported();
+                ProtoLog.v(WM_SHELL_TASK_ORG, "%s onTaskAppeared Supported", TAG);
+
+                // Initialize dim surfaces:
+                mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
+                        .setParent(mPrimarySurface).setColorLayer()
+                        .setName("Primary Divider Dim")
+                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+                        .build();
+                mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
+                        .setParent(mSecondarySurface).setColorLayer()
+                        .setName("Secondary Divider Dim")
+                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+                        .build();
+                SurfaceControl.Transaction t = getTransaction();
+                t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
+                t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
+                t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
+                t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
+                t.apply();
+                releaseTransaction(t);
+            }
+        }
+    }
+
+    @Override
+    public void onTaskVanished(RunningTaskInfo taskInfo) {
+        synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                mLeashByTaskId.remove(taskInfo.taskId);
+                return;
+            }
+
+            final boolean isPrimaryTask = mPrimary != null
+                    && taskInfo.token.equals(mPrimary.token);
+            final boolean isSecondaryTask = mSecondary != null
+                    && taskInfo.token.equals(mSecondary.token);
+
+            if (mSplitScreenSupported && (isPrimaryTask || isSecondaryTask)) {
+                mSplitScreenSupported = false;
+
+                SurfaceControl.Transaction t = getTransaction();
+                t.remove(mPrimaryDim);
+                t.remove(mSecondaryDim);
+                t.remove(mPrimarySurface);
+                t.remove(mSecondarySurface);
+                t.apply();
+                releaseTransaction(t);
+
+                mSplitScreenController.onTaskVanished();
+            }
+        }
+    }
+
+    @Override
+    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+        if (taskInfo.displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+        synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                handleChildTaskChanged(taskInfo);
+                return;
+            }
+
+            mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
+        }
+    }
+
+    private void handleChildTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+        mLeashByTaskId.put(taskInfo.taskId, leash);
+        updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
+    }
+
+    private void handleChildTaskChanged(RunningTaskInfo taskInfo) {
+        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+        updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
+    }
+
+    private void updateChildTaskSurface(
+            RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) {
+        final Point taskPositionInParent = taskInfo.positionInParent;
+        mSyncQueue.runInSync(t -> {
+            t.setWindowCrop(leash, null);
+            t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
+            if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
+                t.setAlpha(leash, 1f);
+                t.setMatrix(leash, 1, 0, 0, 1);
+                t.show(leash);
+            }
+        });
+    }
+
+    /**
+     * This is effectively a finite state machine which moves between the various split-screen
+     * presentations based on the contents of the split regions.
+     */
+    private void handleTaskInfoChanged(RunningTaskInfo info) {
+        if (!mSplitScreenSupported) {
+            // This shouldn't happen; but apparently there is a chance that SysUI crashes without
+            // system server receiving binder-death (or maybe it receives binder-death too late?).
+            // In this situation, when sys-ui restarts, the split root-tasks will still exist so
+            // there is a small window of time during init() where WM might send messages here
+            // before init() fails. So, avoid a cycle of crashes by returning early.
+            Log.e(TAG, "Got handleTaskInfoChanged when not initialized: " + info);
+            return;
+        }
+        final boolean secondaryImpliedMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+                || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
+                        && mSplitScreenController.isHomeStackResizable());
+        final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        if (info.token.asBinder() == mPrimary.token.asBinder()) {
+            mPrimary = info;
+        } else if (info.token.asBinder() == mSecondary.token.asBinder()) {
+            mSecondary = info;
+        }
+        final boolean primaryIsEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean secondaryImpliesMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+                || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
+                        && mSplitScreenController.isHomeStackResizable());
+        if (DEBUG) {
+            Log.d(TAG, "onTaskInfoChanged " + mPrimary + "  " + mSecondary);
+        }
+        if (primaryIsEmpty == primaryWasEmpty && secondaryWasEmpty == secondaryIsEmpty
+                && secondaryImpliedMinimize == secondaryImpliesMinimize) {
+            // No relevant changes
+            return;
+        }
+        if (primaryIsEmpty || secondaryIsEmpty) {
+            // At-least one of the splits is empty which means we are currently transitioning
+            // into or out-of split-screen mode.
+            if (DEBUG) {
+                Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
+                        + "  " + mSecondary.topActivityType);
+            }
+            if (mSplitScreenController.isDividerVisible()) {
+                // Was in split-mode, which means we are leaving split, so continue that.
+                // This happens when the stack in the primary-split is dismissed.
+                if (DEBUG) {
+                    Log.d(TAG, "    was in split, so this means leave it "
+                            + mPrimary.topActivityType + "  " + mSecondary.topActivityType);
+                }
+                mSplitScreenController.startDismissSplit(false /* toPrimaryTask */);
+            } else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) {
+                // Wasn't in split-mode (both were empty), but now that the primary split is
+                // populated, we should fully enter split by moving everything else into secondary.
+                // This just tells window-manager to reparent things, the UI will respond
+                // when it gets new task info for the secondary split.
+                if (DEBUG) {
+                    Log.d(TAG, "   was not in split, but primary is populated, so enter it");
+                }
+                mSplitScreenController.startEnterSplit();
+            }
+        } else if (secondaryImpliesMinimize) {
+            // Workaround for b/172686383, we can't rely on the sync bounds change transaction for
+            // the home task to finish before the last updateChildTaskSurface() call even if it's
+            // queued on the sync transaction queue, so ensure that the home task surface is updated
+            // again before we minimize
+            final ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
+            mSplitScreenController.getWmProxy().getHomeAndRecentsTasks(tasks,
+                    mSplitScreenController.getSecondaryRoot());
+            for (int i = 0; i < tasks.size(); i++) {
+                final RunningTaskInfo taskInfo = tasks.get(i);
+                final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+                if (leash != null) {
+                    updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
+                }
+            }
+
+            // Both splits are populated but the secondary split has a home/recents stack on top,
+            // so enter minimized mode.
+            mSplitScreenController.ensureMinimizedSplit();
+        } else {
+            // Both splits are populated by normal activities, so make sure we aren't minimized.
+            mSplitScreenController.ensureNormalSplit();
+        }
+    }
+
+    @Override
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + this);
+        pw.println(innerPrefix + "mSplitScreenSupported=" + mSplitScreenSupported);
+        if (mPrimary != null) pw.println(innerPrefix + "mPrimary.taskId=" + mPrimary.taskId);
+        if (mSecondary != null) pw.println(innerPrefix + "mSecondary.taskId=" + mSecondary.taskId);
+    }
+
+    @Override
+    public String toString() {
+        return TAG;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
new file mode 100644
index 0000000..1e9223c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.wm.shell.R;
+
+/**
+ * Shadow for the minimized dock state on homescreen.
+ */
+public class MinimizedDockShadow extends View {
+
+    private final Paint mShadowPaint = new Paint();
+
+    private int mDockSide = WindowManager.DOCKED_INVALID;
+
+    public MinimizedDockShadow(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    void setDockSide(int dockSide) {
+        if (dockSide != mDockSide) {
+            mDockSide = dockSide;
+            updatePaint(getLeft(), getTop(), getRight(), getBottom());
+            invalidate();
+        }
+    }
+
+    private void updatePaint(int left, int top, int right, int bottom) {
+        int startColor = mContext.getResources().getColor(
+                R.color.minimize_dock_shadow_start, null);
+        int endColor = mContext.getResources().getColor(
+                R.color.minimize_dock_shadow_end, null);
+        final int middleColor = Color.argb(
+                (Color.alpha(startColor) + Color.alpha(endColor)) / 2, 0, 0, 0);
+        final int quarter = Color.argb(
+                (int) (Color.alpha(startColor) * 0.25f + Color.alpha(endColor) * 0.75f),
+                0, 0, 0);
+        if (mDockSide == WindowManager.DOCKED_TOP) {
+            mShadowPaint.setShader(new LinearGradient(
+                    0, 0, 0, bottom - top,
+                    new int[] { startColor, middleColor, quarter, endColor },
+                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+            mShadowPaint.setShader(new LinearGradient(
+                    0, 0, right - left, 0,
+                    new int[] { startColor, middleColor, quarter, endColor },
+                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+            mShadowPaint.setShader(new LinearGradient(
+                    right - left, 0, 0, 0,
+                    new int[] { startColor, middleColor, quarter, endColor },
+                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed) {
+            updatePaint(left, top, right, bottom);
+            invalidate();
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.drawRect(0, 0, getWidth(), getHeight(), mShadowPaint);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
new file mode 100644
index 0000000..68da35d
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.legacysplitscreen;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Display;
+import android.view.SurfaceControl;
+import android.view.WindowManagerGlobal;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Proxy to simplify calls into window manager/activity manager
+ */
+class WindowManagerProxy {
+
+    private static final String TAG = "WindowManagerProxy";
+    private static final int[] HOME_AND_RECENTS = {ACTIVITY_TYPE_HOME, ACTIVITY_TYPE_RECENTS};
+
+    @GuardedBy("mDockedRect")
+    private final Rect mDockedRect = new Rect();
+
+    private final Rect mTmpRect1 = new Rect();
+
+    @GuardedBy("mDockedRect")
+    private final Rect mTouchableRegion = new Rect();
+
+    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
+    private final SyncTransactionQueue mSyncTransactionQueue;
+
+    private final Runnable mSetTouchableRegionRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                synchronized (mDockedRect) {
+                    mTmpRect1.set(mTouchableRegion);
+                }
+                WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+                        mTmpRect1);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to set touchable region: " + e);
+            }
+        }
+    };
+
+    private final TaskOrganizer mTaskOrganizer;
+
+    WindowManagerProxy(SyncTransactionQueue syncQueue, TaskOrganizer taskOrganizer) {
+        mSyncTransactionQueue = syncQueue;
+        mTaskOrganizer = taskOrganizer;
+    }
+
+    void dismissOrMaximizeDocked(final LegacySplitScreenTaskListener tiles,
+            LegacySplitDisplayLayout layout, final boolean dismissOrMaximize) {
+        mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
+    }
+
+    public void setResizing(final boolean resizing) {
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    ActivityTaskManager.getService().setSplitScreenResizing(resizing);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error calling setDockedStackResizing: " + e);
+                }
+            }
+        });
+    }
+
+    /** Sets a touch region */
+    public void setTouchRegion(Rect region) {
+        synchronized (mDockedRect) {
+            mTouchableRegion.set(region);
+        }
+        mExecutor.execute(mSetTouchableRegionRunnable);
+    }
+
+    void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) {
+        WindowContainerTransaction t = new WindowContainerTransaction();
+        splitLayout.resizeSplits(position, t);
+        new WindowOrganizer().applyTransaction(t);
+    }
+
+    boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out,
+            WindowContainerToken parent) {
+        boolean resizable = false;
+        List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
+                ? mTaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
+                : mTaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
+        for (int i = 0, n = rootTasks.size(); i < n; ++i) {
+            final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
+            out.add(ti);
+            if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
+                resizable = ti.isResizeable;
+            }
+        }
+        return resizable;
+    }
+
+    /**
+     * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary
+     * 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(LegacySplitDisplayLayout layout, WindowContainerToken parent,
+            @NonNull WindowContainerTransaction wct) {
+        // Resize the home/recents stacks to the larger minimized-state size
+        final Rect homeBounds;
+        final ArrayList<ActivityManager.RunningTaskInfo> homeStacks = new ArrayList<>();
+        boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
+        if (isHomeResizable) {
+            homeBounds = layout.calcResizableMinimizedHomeStackBounds();
+        } else {
+            // home is not resizable, so lock it to its inherent orientation size.
+            homeBounds = new Rect(0, 0, 0, 0);
+            for (int i = homeStacks.size() - 1; i >= 0; --i) {
+                if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_HOME) {
+                    final int orient = homeStacks.get(i).configuration.orientation;
+                    final boolean displayLandscape = layout.mDisplayLayout.isLandscape();
+                    final boolean isLandscape = orient == ORIENTATION_LANDSCAPE
+                            || (orient == ORIENTATION_UNDEFINED && displayLandscape);
+                    homeBounds.right = isLandscape == displayLandscape
+                            ? layout.mDisplayLayout.width() : layout.mDisplayLayout.height();
+                    homeBounds.bottom = isLandscape == displayLandscape
+                            ? layout.mDisplayLayout.height() : layout.mDisplayLayout.width();
+                    break;
+                }
+            }
+        }
+        for (int i = homeStacks.size() - 1; i >= 0; --i) {
+            // For non-resizable homes, the minimized size is actually the fullscreen-size. As a
+            // result, we don't minimize for recents since it only shows half-size screenshots.
+            if (!isHomeResizable) {
+                if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_RECENTS) {
+                    continue;
+                }
+                wct.setWindowingMode(homeStacks.get(i).token, WINDOWING_MODE_FULLSCREEN);
+            }
+            wct.setBounds(homeStacks.get(i).token, homeBounds);
+        }
+        layout.mTiles.mHomeBounds.set(homeBounds);
+        return isHomeResizable;
+    }
+
+    /**
+     * Finishes entering split-screen by reparenting all FULLSCREEN tasks into the secondary split.
+     * This assumes there is already something in the primary split since that is usually what
+     * triggers a call to this. In the same transaction, this overrides the home task bounds via
+     * {@link #applyHomeTasksMinimized}.
+     *
+     * @return whether the home stack is resizable
+     */
+    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.
+        mTaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
+        List<ActivityManager.RunningTaskInfo> rootTasks =
+                mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (rootTasks.isEmpty()) {
+            return false;
+        }
+        ActivityManager.RunningTaskInfo topHomeTask = null;
+        for (int i = rootTasks.size() - 1; i >= 0; --i) {
+            final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
+            // Only move resizeable task to split secondary. However, we have an exception
+            // for non-resizable home because we will minimize to show it.
+            if (!rootTask.isResizeable && rootTask.topActivityType != ACTIVITY_TYPE_HOME) {
+                continue;
+            }
+            // Only move fullscreen tasks to split secondary.
+            if (rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+                continue;
+            }
+            // Since this iterates from bottom to top, update topHomeTask for every fullscreen task
+            // so it will be left with the status of the top one.
+            topHomeTask = isHomeOrRecentTask(rootTask) ? rootTask : null;
+            wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
+        }
+        // Move the secondary split-forward.
+        wct.reorder(tiles.mSecondary.token, true /* onTop */);
+        boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
+        if (topHomeTask != null) {
+            // Translate/update-crop of secondary out-of-band with sync transaction -- Until BALST
+            // is enabled, this temporarily syncs the home surface position with offset until
+            // sync transaction finishes.
+            wct.setBoundsChangeTransaction(topHomeTask.token, tiles.mHomeBounds);
+        }
+        applySyncTransaction(wct);
+        return isHomeResizable;
+    }
+
+    boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
+        final int atype = ti.getActivityType();
+        return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS;
+    }
+
+    /**
+     * Reparents all tile members back to their display and resets home task override bounds.
+     * @param dismissOrMaximize When {@code true} this resolves the split by closing the primary
+     *                          split (thus resulting in the top of the secondary split becoming
+     *                          fullscreen. {@code false} resolves the other way.
+     */
+    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.
+        mTaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
+        // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
+        //                 plus specific APIs to clean this up.
+        List<ActivityManager.RunningTaskInfo> primaryChildren =
+                mTaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
+        List<ActivityManager.RunningTaskInfo> secondaryChildren =
+                mTaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
+        // In some cases (eg. non-resizable is launched), system-server will leave split-screen.
+        // as a result, the above will not capture any tasks; yet, we need to clean-up the
+        // home task bounds.
+        List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
+                mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, HOME_AND_RECENTS);
+        // Filter out the root split tasks
+        freeHomeAndRecents.removeIf(p -> p.token.equals(tiles.mSecondary.token)
+                || p.token.equals(tiles.mPrimary.token));
+
+        if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
+                && freeHomeAndRecents.isEmpty()) {
+            return;
+        }
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (dismissOrMaximize) {
+            // Dismissing, so move all primary split tasks first
+            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
+            }
+            boolean homeOnTop = false;
+            // Don't need to worry about home tasks because they are already in the "proper"
+            // order within the secondary split.
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                wct.reparent(ti.token, null /* parent */, true /* onTop */);
+                if (isHomeOrRecentTask(ti)) {
+                    wct.setBounds(ti.token, null);
+                    wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
+                    if (i == 0) {
+                        homeOnTop = true;
+                    }
+                }
+            }
+            if (homeOnTop) {
+                // Translate/update-crop of secondary out-of-band with sync transaction -- instead
+                // play this in sync with new home-app frame because until BALST is enabled this
+                // shows up on screen before the syncTransaction returns.
+                // We only have access to the secondary root surface, though, so in order to
+                // position things properly, we have to take into account the existing negative
+                // offset/crop of the minimized-home task.
+                final boolean landscape = layout.mDisplayLayout.isLandscape();
+                final int posX = landscape ? layout.mSecondary.left - tiles.mHomeBounds.left
+                        : layout.mSecondary.left;
+                final int posY = landscape ? layout.mSecondary.top
+                        : layout.mSecondary.top - tiles.mHomeBounds.top;
+                final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
+                sft.setPosition(tiles.mSecondarySurface, posX, posY);
+                final Rect crop = new Rect(0, 0, layout.mDisplayLayout.width(),
+                        layout.mDisplayLayout.height());
+                crop.offset(-posX, -posY);
+                sft.setWindowCrop(tiles.mSecondarySurface, crop);
+                wct.setBoundsChangeTransaction(tiles.mSecondary.token, sft);
+            }
+        } else {
+            // Maximize, so move non-home secondary split first
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                if (isHomeOrRecentTask(secondaryChildren.get(i))) {
+                    continue;
+                }
+                wct.reparent(secondaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
+            }
+            // Find and place home tasks in-between. This simulates the fact that there was
+            // nothing behind the primary split's tasks.
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                if (isHomeOrRecentTask(ti)) {
+                    wct.reparent(ti.token, null /* parent */, true /* onTop */);
+                    // reset bounds and mode too
+                    wct.setBounds(ti.token, null);
+                    wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
+                }
+            }
+            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
+            }
+        }
+        for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
+            wct.setBounds(freeHomeAndRecents.get(i).token, null);
+            wct.setWindowingMode(freeHomeAndRecents.get(i).token, WINDOWING_MODE_UNDEFINED);
+        }
+        // Reset focusable to true
+        wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
+        applySyncTransaction(wct);
+    }
+
+    /**
+     * Utility to apply a sync transaction serially with other sync transactions.
+     *
+     * @see SyncTransactionQueue#queue
+     */
+    void applySyncTransaction(WindowContainerTransaction wct) {
+        mSyncTransactionQueue.queue(wct);
+    }
+
+    /**
+     * @see SyncTransactionQueue#queueIfWaiting
+     */
+    boolean queueSyncTransactionIfWaiting(WindowContainerTransaction wct) {
+        return mSyncTransactionQueue.queueIfWaiting(wct);
+    }
+
+    /**
+     * @see SyncTransactionQueue#runInSync
+     */
+    void runInSync(SyncTransactionQueue.TransactionRunnable runnable) {
+        mSyncTransactionQueue.runInSync(runnable);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java
deleted file mode 100644
index 0a549c6..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.letterbox;
-
-import android.content.Context;
-import android.view.Gravity;
-
-import com.android.wm.shell.R;
-
-/**
-  * Controls access to and overrides of resource config values used by {@link
-  * LetterboxTaskOrganizer}.
-  */
-public final class LetterboxConfigController {
-
-    private final Context mContext;
-
-    /** {@link Gravity} of letterboxed apps in portrait screen orientation. */
-    private int mLetterboxPortraitGravity;
-
-    /** {@link Gravity} of letterboxed apps in landscape screen orientation. */
-    private int mLetterboxLandscapeGravity;
-
-    public LetterboxConfigController(Context context) {
-        mContext = context;
-        mLetterboxPortraitGravity =
-                mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity);
-        mLetterboxLandscapeGravity =
-                mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
-    }
-
-    /**
-     * Overrides {@link Gravity} of letterboxed apps in portrait screen orientation.
-     *
-     * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#TOP}, {@link
-     *         Gravity#CENTER} or {@link Gravity#BOTTOM}.
-     */
-    public void setPortraitGravity(int gravity) {
-        if (gravity != Gravity.TOP && gravity != Gravity.CENTER && gravity != Gravity.BOTTOM) {
-            throw new IllegalArgumentException(
-                    "Expected Gravity#TOP, Gravity#CENTER or Gravity#BOTTOM but got"
-                    + gravity);
-        }
-        mLetterboxPortraitGravity = gravity;
-    }
-
-    /**
-     * Resets {@link Gravity} of letterboxed apps in portrait screen orientation to {@link
-     * R.integer.config_letterboxPortraitGravity}.
-     */
-    public void resetPortraitGravity() {
-        mLetterboxPortraitGravity =
-                mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity);
-    }
-
-    /**
-     * Gets {@link Gravity} of letterboxed apps in portrait screen orientation.
-     */
-    public int getPortraitGravity() {
-        return mLetterboxPortraitGravity;
-    }
-
-    /**
-     * Overrides {@link Gravity} of letterboxed apps in landscape screen orientation.
-     *
-     * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#RIGHT}, {@link
-     *         Gravity#CENTER} or {@link Gravity#LEFT}.
-     */
-    public void setLandscapeGravity(int gravity) {
-        if (gravity != Gravity.LEFT && gravity != Gravity.CENTER && gravity != Gravity.RIGHT) {
-            throw new IllegalArgumentException(
-                    "Expected Gravity#LEFT, Gravity#CENTER or Gravity#RIGHT but got"
-                    + gravity);
-        }
-        mLetterboxLandscapeGravity = gravity;
-    }
-
-    /**
-     * Resets {@link Gravity} of letterboxed apps in landscape screen orientation to {@link
-     * R.integer.config_letterboxLandscapeGravity}.
-     */
-    public void resetLandscapeGravity() {
-        mLetterboxLandscapeGravity =
-                mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
-    }
-
-    /**
-     * Gets {@link Gravity} of letterboxed apps in landscape screen orientation.
-     */
-    public int getLandscapeGravity() {
-        return mLetterboxLandscapeGravity;
-    }
-
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java
deleted file mode 100644
index 6e87f13..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.letterbox;
-
-import android.app.ActivityManager;
-import android.graphics.Insets;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.Gravity;
-import android.view.SurfaceControl;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.Transitions;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.protolog.ShellProtoLogGroup;
-
-/**
-  * Organizes a task in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN} when
-  * it's presented in the letterbox mode either because orientations of a top activity and a device
-  * don't match or because a top activity is in a size compat mode.
-  */
-public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener {
-    private static final String TAG = "LetterboxTaskListener";
-
-    private final SyncTransactionQueue mSyncQueue;
-    private final LetterboxConfigController mLetterboxConfigController;
-    private final WindowManager mWindowManager;
-    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
-
-    public LetterboxTaskListener(
-            SyncTransactionQueue syncQueue,
-            LetterboxConfigController letterboxConfigController,
-            WindowManager windowManager) {
-        mSyncQueue = syncQueue;
-        mLetterboxConfigController = letterboxConfigController;
-        mWindowManager = windowManager;
-    }
-
-    @Override
-    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
-        if (mLeashByTaskId.get(taskInfo.taskId) != null) {
-            throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
-        }
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Appeared: #%d",
-                taskInfo.taskId);
-        mLeashByTaskId.put(taskInfo.taskId, leash);
-        Point positionInParent = new Point();
-        Rect crop = new Rect();
-        resolveTaskPositionAndCrop(taskInfo, positionInParent, crop);
-        mSyncQueue.runInSync(t -> {
-            setPositionAndWindowCrop(t, leash, positionInParent, crop);
-            if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
-                t.setAlpha(leash, 1f);
-                t.setMatrix(leash, 1, 0, 0, 1);
-                t.show(leash);
-            }
-        });
-    }
-
-    @Override
-    public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
-        if (mLeashByTaskId.get(taskInfo.taskId) == null) {
-            Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
-            return;
-        }
-        mLeashByTaskId.remove(taskInfo.taskId);
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Vanished: #%d",
-                taskInfo.taskId);
-    }
-
-    @Override
-    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Changed: #%d",
-                taskInfo.taskId);
-        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
-        Point positionInParent = new Point();
-        Rect crop = new Rect();
-        resolveTaskPositionAndCrop(taskInfo, positionInParent, crop);
-        mSyncQueue.runInSync(t -> setPositionAndWindowCrop(t, leash, positionInParent, crop));
-    }
-
-    private static void setPositionAndWindowCrop(
-                SurfaceControl.Transaction transaction,
-                SurfaceControl leash,
-                final Point positionInParent,
-                final Rect crop) {
-        transaction.setPosition(leash, positionInParent.x, positionInParent.y);
-        transaction.setWindowCrop(leash, crop);
-    }
-
-    // TODO(b/173440321): Correct presentation of letterboxed activities in One-handed mode.
-    private void resolveTaskPositionAndCrop(
-                ActivityManager.RunningTaskInfo taskInfo,
-                Point positionInParent,
-                Rect crop) {
-        // In screen coordinates
-        Rect parentBounds = new Rect(taskInfo.parentBounds);
-        // Intersect parent and max bounds. This is required for situations when parent bounds
-        // go beyond display bounds, for example, in One-handed mode.
-        final Rect maxBounds = taskInfo.getConfiguration().windowConfiguration.getMaxBounds();
-        if (!parentBounds.intersect(maxBounds)) {
-            Slog.w(TAG, "Task parent and max bounds don't intersect: #" + taskInfo.taskId);
-        }
-
-        // In screen coordinates
-        final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
-        final Rect activityBounds = taskInfo.letterboxActivityBounds;
-
-        Insets insets = getInsets();
-        Rect displayBoundsWithInsets =
-                new Rect(mWindowManager.getMaximumWindowMetrics().getBounds());
-        displayBoundsWithInsets.inset(insets);
-
-        Rect taskBoundsWithInsets = new Rect(taskBounds);
-        taskBoundsWithInsets.intersect(displayBoundsWithInsets);
-
-        Rect activityBoundsWithInsets = new Rect(activityBounds);
-        activityBoundsWithInsets.intersect(displayBoundsWithInsets);
-
-        Rect parentBoundsWithInsets = new Rect(parentBounds);
-        parentBoundsWithInsets.intersect(displayBoundsWithInsets);
-
-        // Crop need to be in the task coordinates.
-        crop.set(activityBoundsWithInsets);
-        crop.offset(-taskBounds.left, -taskBounds.top);
-
-        // Account for insets since coordinates calculations below are done with them.
-        positionInParent.x = parentBoundsWithInsets.left - parentBounds.left
-                    - (taskBoundsWithInsets.left - taskBounds.left);
-        positionInParent.y = parentBoundsWithInsets.top - parentBounds.top
-                - (taskBoundsWithInsets.top - taskBounds.top);
-
-        // Calculating a position of task bounds (without insets) in parent coordinates (without
-        // insets) to align activity bounds (without insets) as requested in config. Activity
-        // accounts for insets that overlap with its bounds (this overlap can be partial) so
-        // ignoring overlap with insets when computing the position. Also, cropping unwanted insets
-        // while keeping the top one if the activity is aligned at the top of the window to show
-        // status bar decor view.
-        if (parentBounds.height() >= parentBounds.width()) {
-            final int gravity = mLetterboxConfigController.getPortraitGravity();
-            // Center activity horizontally.
-            positionInParent.x +=
-                    (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2
-                            + taskBoundsWithInsets.left - activityBoundsWithInsets.left;
-            switch (gravity) {
-                case Gravity.TOP:
-                    positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top;
-                    // Showing status bar decor view.
-                    crop.top -= activityBoundsWithInsets.top - activityBounds.top;
-                    break;
-                case Gravity.CENTER:
-                    positionInParent.y +=
-                            taskBoundsWithInsets.top - activityBoundsWithInsets.top
-                                    + (parentBoundsWithInsets.height()
-                                            - activityBoundsWithInsets.height()) / 2;
-                    break;
-                case Gravity.BOTTOM:
-                    positionInParent.y +=
-                            parentBoundsWithInsets.height() - activityBoundsWithInsets.bottom
-                                    + taskBoundsWithInsets.top;
-                    break;
-                default:
-                    throw new AssertionError(
-                            "Unexpected portrait gravity " + gravity
-                            + " for task: #" + taskInfo.taskId);
-            }
-        } else {
-            final int gravity = mLetterboxConfigController.getLandscapeGravity();
-            // Align activity to the top.
-            positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top;
-            // Showing status bar decor view.
-            crop.top -= activityBoundsWithInsets.top - activityBounds.top;
-            switch (gravity) {
-                case Gravity.LEFT:
-                    positionInParent.x += taskBoundsWithInsets.left - activityBoundsWithInsets.left;
-                    break;
-                case Gravity.CENTER:
-                    positionInParent.x +=
-                            (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2
-                                    + taskBoundsWithInsets.left - activityBoundsWithInsets.left;
-                    break;
-                case Gravity.RIGHT:
-                    positionInParent.x +=
-                            parentBoundsWithInsets.width()
-                                    - activityBoundsWithInsets.right + taskBoundsWithInsets.left;
-                    break;
-                default:
-                    throw new AssertionError(
-                            "Unexpected landscape gravity " + gravity
-                            + " for task: #" + taskInfo.taskId);
-            }
-        }
-    }
-
-    private Insets getInsets() {
-        return mWindowManager
-                .getMaximumWindowMetrics()
-                .getWindowInsets()
-                .getInsets(
-                        WindowInsets.Type.navigationBars()
-                                | WindowInsets.Type.statusBars()
-                                | WindowInsets.Type.displayCutout());
-    }
-
-}
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..69d8db2 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
@@ -32,6 +32,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -45,6 +46,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.
@@ -74,6 +76,7 @@
     private final Handler mMainHandler = new Handler(Looper.getMainLooper());
 
     private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
+    private final AccessibilityManager mAccessibilityManager;
 
     /**
      * Handle rotation based on OnDisplayChangingListener callback
@@ -163,13 +166,33 @@
                 }
             };
 
+    private AccessibilityManager.AccessibilityStateChangeListener
+            mAccessibilityStateChangeListener =
+            new AccessibilityManager.AccessibilityStateChangeListener() {
+                @Override
+                public void onAccessibilityStateChanged(boolean enabled) {
+                    if (enabled) {
+                        final int mOneHandedTimeout = OneHandedSettingsUtil
+                                .getSettingsOneHandedModeTimeout(mContext.getContentResolver());
+                        final int timeout = mAccessibilityManager
+                                .getRecommendedTimeoutMillis(mOneHandedTimeout * 1000
+                                        /* align with A11y timeout millis */,
+                                        AccessibilityManager.FLAG_CONTENT_CONTROLS);
+                        mTimeoutHandler.setTimeout(timeout / 1000);
+                    } else {
+                        mTimeoutHandler.setTimeout(OneHandedSettingsUtil
+                                .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
+                    }
+                }
+            };
+
     /**
      * Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
      */
     @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 +205,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,
@@ -238,6 +261,11 @@
                         stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
                     }
                 });
+
+        mAccessibilityManager = (AccessibilityManager)
+                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        mAccessibilityManager.addAccessibilityStateChangeListener(
+                mAccessibilityStateChangeListener);
     }
 
     /**
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/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 3b1e6cb..951a688 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -75,6 +75,7 @@
     @Nullable
     OneHandedGestureEventCallback mGestureEventCallback;
     private Rect mGestureRegion = new Rect();
+    private boolean mIsStopGesture;
 
     /**
      * Constructor of OneHandedGestureHandler, we only handle the gesture of
@@ -153,20 +154,20 @@
                         float distance = (float) Math.hypot(mLastPos.x - mDownPos.x,
                                 mLastPos.y - mDownPos.y);
                         if (distance > mDragDistThreshold) {
-                            mGestureEventCallback.onStop();
+                            mIsStopGesture = true;
                         }
                     }
                     break;
                 case MotionEvent.ACTION_UP:
                     if (mLastPos.y >= mDownPos.y && mPassedSlop) {
                         mGestureEventCallback.onStart();
+                    } else if (mIsStopGesture) {
+                        mGestureEventCallback.onStop();
                     }
-                    mPassedSlop = false;
-                    mAllowGesture = false;
+                    clearState();
                     break;
                 case MotionEvent.ACTION_CANCEL:
-                    mPassedSlop = false;
-                    mAllowGesture = false;
+                    clearState();
                     break;
                 default:
                     break;
@@ -174,6 +175,11 @@
         }
     }
 
+    private void clearState() {
+        mPassedSlop = false;
+        mIsStopGesture = false;
+    }
+
     private void disposeInputChannel() {
         if (mInputEventReceiver != null) {
             mInputEventReceiver.dispose();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 4d66f29..f8217c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -126,7 +126,7 @@
      */
     public static boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver) {
         return Settings.Secure.getInt(resolver,
-                Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0) == 1;
+                Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1) == 1;
     }
 
     protected static void dump(PrintWriter pw, String prefix, ContentResolver resolver) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index d65ad62..a944e3b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -63,6 +63,16 @@
     private String mStartOneHandedDescription;
     private String mStopOneHandedDescription;
 
+    private enum ONE_HANDED_TRIGGER_STATE {
+        UNSET, ENTERING, EXITING
+    }
+    /**
+     * Current One-Handed trigger state.
+     * Note: This is a dynamic state, whenever last state has been confirmed
+     * (i.e. onStartFinished() or onStopFinished()), the state should be set "UNSET" at final.
+     */
+    private ONE_HANDED_TRIGGER_STATE mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
+
     /**
      * Container of the tutorial panel showing at outside region when one handed starting
      */
@@ -74,6 +84,21 @@
         public void onTutorialAnimationUpdate(int offset) {
             mUpdateHandler.post(() -> onAnimationUpdate(offset));
         }
+
+        @Override
+        public void onOneHandedAnimationStart(
+                OneHandedAnimationController.OneHandedTransitionAnimator animator) {
+            mUpdateHandler.post(() -> {
+                final Rect startValue = (Rect) animator.getStartValue();
+                if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) {
+                    mTriggerState = (startValue.top == 0)
+                            ? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
+                    if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
+                        createTutorialTarget();
+                    }
+                }
+            });
+        }
     };
 
     public OneHandedTutorialHandler(Context context) {
@@ -100,9 +125,6 @@
                 R.string.accessibility_action_start_one_handed);
         mStopOneHandedDescription = context.getResources().getString(
                 R.string.accessibility_action_stop_one_handed);
-        if (mCanShowTutorial) {
-            createOrUpdateTutorialTarget();
-        }
     }
 
     @Override
@@ -111,6 +133,7 @@
             updateFinished(View.VISIBLE, 0f);
             updateTutorialCount();
             announcementForScreenReader(true);
+            mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
         });
     }
 
@@ -119,6 +142,8 @@
         mUpdateHandler.post(() -> {
             updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
             announcementForScreenReader(false);
+            removeTutorialFromWindowManager();
+            mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
         });
     }
 
@@ -126,7 +151,6 @@
         if (!canShowTutorial()) {
             return;
         }
-
         mTargetViewContainer.setVisibility(visible);
         mTargetViewContainer.setTranslationY(finalPosition);
     }
@@ -155,24 +179,23 @@
      * Adds the tutorial target view to the WindowManager and update its layout, so it's ready
      * to be animated in.
      */
-    private void createOrUpdateTutorialTarget() {
-        mUpdateHandler.post(() -> {
-            if (!mTargetViewContainer.isAttachedToWindow()) {
-                mTargetViewContainer.setVisibility(View.INVISIBLE);
-
-                try {
-                    mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
-                } catch (IllegalStateException e) {
-                    // This shouldn't happen, but if the target is already added, just update its
-                    // layout params.
-                    mWindowManager.updateViewLayout(
-                            mTargetViewContainer, getTutorialTargetLayoutParams());
-                }
-            } else {
-                mWindowManager.updateViewLayout(mTargetViewContainer,
-                        getTutorialTargetLayoutParams());
+    private void createTutorialTarget() {
+        if (!mTargetViewContainer.isAttachedToWindow()) {
+            try {
+                mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
+            } catch (IllegalStateException e) {
+                // This shouldn't happen, but if the target is already added, just update its
+                // layout params.
+                mWindowManager.updateViewLayout(
+                        mTargetViewContainer, getTutorialTargetLayoutParams());
             }
-        });
+        }
+    }
+
+    private void removeTutorialFromWindowManager() {
+        if (mTargetViewContainer.isAttachedToWindow()) {
+            mWindowManager.removeViewImmediate(mTargetViewContainer);
+        }
     }
 
     OneHandedAnimationCallback getAnimationCallback() {
@@ -193,7 +216,6 @@
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setFitInsetsTypes(0 /* types */);
         lp.setTitle("one-handed-tutorial-overlay");
-
         return lp;
     }
 
@@ -206,10 +228,12 @@
 
     private boolean canShowTutorial() {
         if (!mCanShowTutorial) {
+            // Since canSHowTutorial() will be called in onAnimationUpdate() and we still need to
+            // hide Tutorial text in the period of continuously onAnimationUpdate() API call,
+            // so we have to hide mTargetViewContainer here.
             mTargetViewContainer.setVisibility(View.GONE);
             return false;
         }
-
         return true;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
index 5593268..d59aec2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
@@ -20,7 +20,6 @@
 import android.content.ComponentName;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
-import android.view.DisplayInfo;
 import android.view.IPinnedStackListener;
 import android.view.WindowManagerGlobal;
 
@@ -85,18 +84,6 @@
         }
     }
 
-    private void onDisplayInfoChanged(DisplayInfo displayInfo) {
-        for (PinnedStackListener listener : mListeners) {
-            listener.onDisplayInfoChanged(displayInfo);
-        }
-    }
-
-    private void onConfigurationChanged() {
-        for (PinnedStackListener listener : mListeners) {
-            listener.onConfigurationChanged();
-        }
-    }
-
     private void onAspectRatioChanged(float aspectRatio) {
         for (PinnedStackListener listener : mListeners) {
             listener.onAspectRatioChanged(aspectRatio);
@@ -134,20 +121,6 @@
         }
 
         @Override
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
-            mShellMainExecutor.execute(() -> {
-                PinnedStackListenerForwarder.this.onDisplayInfoChanged(displayInfo);
-            });
-        }
-
-        @Override
-        public void onConfigurationChanged() {
-            mShellMainExecutor.execute(() -> {
-                PinnedStackListenerForwarder.this.onConfigurationChanged();
-            });
-        }
-
-        @Override
         public void onAspectRatioChanged(float aspectRatio) {
             mShellMainExecutor.execute(() -> {
                 PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio);
@@ -168,10 +141,6 @@
 
         public void onActivityHidden(ComponentName componentName) {}
 
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {}
-
-        public void onConfigurationChanged() {}
-
         public void onAspectRatioChanged(float aspectRatio) {}
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index da9ce0a..1f07542 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -20,6 +20,7 @@
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 
 import com.android.wm.shell.common.annotations.ExternalThread;
@@ -82,6 +83,12 @@
     }
 
     /**
+     * Called when configuration is changed.
+     */
+    default void onConfigurationChanged(Configuration newConfig) {
+    }
+
+    /**
      * Called when display size or font size of settings changed
      */
     default void onDensityOrFontScaleChanged() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index fe01811..3362d2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -22,6 +22,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.graphics.Rect;
+import android.view.Choreographer;
 import android.view.SurfaceControl;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -327,8 +328,14 @@
             mEndValue = endValue;
         }
 
-        SurfaceControl.Transaction newSurfaceControlTransaction() {
-            return mSurfaceControlTransactionFactory.getTransaction();
+        /**
+         * @return {@link SurfaceControl.Transaction} instance with vsync-id.
+         */
+        protected SurfaceControl.Transaction newSurfaceControlTransaction() {
+            final SurfaceControl.Transaction tx =
+                    mSurfaceControlTransactionFactory.getTransaction();
+            tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
+            return tx;
         }
 
         @VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 1bb5eda..f839727 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -102,9 +102,7 @@
         return mSnapAlgorithm;
     }
 
-    /**
-     * Responds to IPinnedStackListener on configuration change.
-     */
+    /** Responds to configuration change. */
     public void onConfigurationChanged(Context context) {
         reloadResources(context);
     }
@@ -125,15 +123,15 @@
     /** Returns the destination bounds to place the PIP window on entry. */
     public Rect getEntryDestinationBounds() {
         final PipBoundsState.PipReentryState reentryState = mPipBoundsState.getReentryState();
-        final boolean shouldRestoreReentryBounds = reentryState != null;
 
-        final Rect destinationBounds = shouldRestoreReentryBounds
+        final Rect destinationBounds = reentryState != null
                 ? getDefaultBounds(reentryState.getSnapFraction(), reentryState.getSize())
                 : getDefaultBounds();
 
+        final boolean useCurrentSize = reentryState != null && reentryState.getSize() != null;
         return transformBoundsToAspectRatioIfValid(destinationBounds,
                 mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
-                shouldRestoreReentryBounds);
+                useCurrentSize);
     }
 
     /** Returns the current bounds adjusted to the new aspect ratio, if valid. */
@@ -223,24 +221,36 @@
     private Rect getDefaultBounds(float snapFraction, Size size) {
         final Rect defaultBounds = new Rect();
         if (snapFraction != INVALID_SNAP_FRACTION && size != null) {
+            // The default bounds are the given size positioned at the given snap fraction.
             defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
             final Rect movementBounds = getMovementBounds(defaultBounds);
             mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
+            return defaultBounds;
+        }
+
+        // Calculate the default size.
+        final Size defaultSize;
+        final Rect insetBounds = new Rect();
+        getInsetBounds(insetBounds);
+        final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
+        final Size overrideMinSize = mPipBoundsState.getOverrideMinSize();
+        if (overrideMinSize != null) {
+            // The override minimal size is set, use that as the default size making sure it's
+            // adjusted to the aspect ratio.
+            defaultSize = adjustSizeToAspectRatio(overrideMinSize, mDefaultAspectRatio);
         } else {
-            final Rect insetBounds = new Rect();
-            getInsetBounds(insetBounds);
-            final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
-            final Size defaultSize;
-            final Size overrideMinSize = mPipBoundsState.getOverrideMinSize();
-            if (overrideMinSize != null) {
-                // The override minimal size is set, use that as the default size making sure it's
-                // adjusted to the aspect ratio.
-                defaultSize = adjustSizeToAspectRatio(overrideMinSize, mDefaultAspectRatio);
-            } else {
-                // Calculate the default size using the display size and default min edge size.
-                defaultSize = getSizeForAspectRatio(mDefaultAspectRatio,
-                        mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
-            }
+            // Calculate the default size using the display size and default min edge size.
+            defaultSize = getSizeForAspectRatio(mDefaultAspectRatio,
+                    mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
+        }
+
+        // Now that we have the default size, apply the snap fraction if valid or position the
+        // bounds using the default gravity.
+        if (snapFraction != INVALID_SNAP_FRACTION) {
+            defaultBounds.set(0, 0, defaultSize.getWidth(), defaultSize.getHeight());
+            final Rect movementBounds = getMovementBounds(defaultBounds);
+            mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
+        } else {
             Gravity.apply(mDefaultStackGravity, defaultSize.getWidth(), defaultSize.getHeight(),
                     insetBounds, 0, Math.max(
                             mPipBoundsState.isImeShowing() ? mPipBoundsState.getImeHeight() : 0,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 53aa614..d0d9b26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -26,6 +26,7 @@
 import android.view.DisplayInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.TriConsumer;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayLayout;
 
@@ -33,7 +34,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
-import java.util.function.BiConsumer;
 
 /**
  * Singleton source of truth for the current state of PIP bounds.
@@ -76,9 +76,11 @@
     private int mImeHeight;
     private boolean mIsShelfShowing;
     private int mShelfHeight;
+    /** Whether the user has resized the PIP manually. */
+    private boolean mHasUserResizedPip;
 
     private @Nullable Runnable mOnMinimalSizeChangeCallback;
-    private @Nullable BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
+    private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
 
     public PipBoundsState(@NonNull Context context) {
         mContext = context;
@@ -189,8 +191,8 @@
     }
 
     /** Save the reentry state to restore to when re-entering PIP mode. */
-    public void saveReentryState(@NonNull Rect bounds, float fraction) {
-        mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction);
+    public void saveReentryState(Size size, float fraction) {
+        mPipReentryState = new PipReentryState(size, fraction);
     }
 
     /** Returns the saved reentry state. */
@@ -205,6 +207,7 @@
         mLastPipComponentName = lastPipComponentName;
         if (changed) {
             clearReentryState();
+            setHasUserResizedPip(false);
         }
     }
 
@@ -307,6 +310,11 @@
 
     /** Set whether the shelf is showing and its height. */
     public void setShelfVisibility(boolean showing, int height) {
+        setShelfVisibility(showing, height, true);
+    }
+
+    /** Set whether the shelf is showing and its height. */
+    public void setShelfVisibility(boolean showing, int height, boolean updateMovementBounds) {
         final boolean shelfShowing = showing && height > 0;
         if (shelfShowing == mIsShelfShowing && height == mShelfHeight) {
             return;
@@ -315,7 +323,8 @@
         mIsShelfShowing = showing;
         mShelfHeight = height;
         if (mOnShelfVisibilityChangeCallback != null) {
-            mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight);
+            mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight,
+                    updateMovementBounds);
         }
     }
 
@@ -329,6 +338,16 @@
         return mShelfHeight;
     }
 
+    /** Returns whether the user has resized the PIP. */
+    public boolean hasUserResizedPip() {
+        return mHasUserResizedPip;
+    }
+
+    /** Set whether the user has resized the PIP. */
+    public void setHasUserResizedPip(boolean hasUserResizedPip) {
+        mHasUserResizedPip = hasUserResizedPip;
+    }
+
     /**
      * Registers a callback when the minimal size of PIP that is set by the app changes.
      */
@@ -338,7 +357,7 @@
 
     /** Set a callback to be notified when the shelf visibility changes. */
     public void setOnShelfVisibilityChangeCallback(
-            @Nullable BiConsumer<Boolean, Integer> onShelfVisibilityChangeCallback) {
+            @Nullable TriConsumer<Boolean, Integer, Boolean> onShelfVisibilityChangeCallback) {
         mOnShelfVisibilityChangeCallback = onShelfVisibilityChangeCallback;
     }
 
@@ -397,15 +416,15 @@
     static final class PipReentryState {
         private static final String TAG = PipReentryState.class.getSimpleName();
 
-        private final @NonNull Size mSize;
+        private final @Nullable Size mSize;
         private final float mSnapFraction;
 
-        PipReentryState(@NonNull Size size, float snapFraction) {
+        PipReentryState(@Nullable Size size, float snapFraction) {
             mSize = size;
             mSnapFraction = snapFraction;
         }
 
-        @NonNull
+        @Nullable
         Size getSize() {
             return mSize;
         }
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 167b9f9..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) {
@@ -502,7 +502,6 @@
 
         mPipMenuController.attach(leash);
 
-
         if (mShouldIgnoreEnteringPipTransition) {
             final Rect destinationBounds = mPipBoundsState.getBounds();
             // animation is finished in the Launcher and here we directly apply the final touch.
@@ -1119,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
@@ -1129,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/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 3234ef6..fa88084 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -33,12 +33,14 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ParceledListSlice;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 import android.util.Pair;
+import android.util.Size;
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.WindowManagerGlobal;
@@ -85,7 +87,6 @@
 
     private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
     private final Rect mTmpInsetBounds = new Rect();
-    protected final Rect mReentryBounds = new Rect();
 
     private boolean mIsInFixedRotation;
     private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
@@ -104,20 +105,23 @@
             // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
             // the display layout in the bounds handler in this case.
             onDisplayRotationChangedNotInPip(mContext, toRotation);
+            // do not forget to update the movement bounds as well.
+            updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
+                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
             return;
         }
         // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
         // the bounds for the next orientation using the destination bounds of the animation
         // TODO: Technically this should account for movement animation bounds as well
         Rect currentBounds = mPipTaskOrganizer.getCurrentOrAnimatingBounds();
-        final boolean changed = onDisplayRotationChanged(mContext,
-                mPipBoundsState.getNormalBounds(), currentBounds, mTmpInsetBounds, displayId,
-                fromRotation, toRotation, t);
+        final Rect outBounds = new Rect();
+        final boolean changed = onDisplayRotationChanged(mContext, outBounds, currentBounds,
+                mTmpInsetBounds, displayId, fromRotation, toRotation, t);
         if (changed) {
             // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
             // movement bounds
-            mTouchHandler.adjustBoundsForRotation(mPipBoundsState.getNormalBounds(),
-                    mPipBoundsState.getBounds(), mTmpInsetBounds);
+            mTouchHandler.adjustBoundsForRotation(outBounds, mPipBoundsState.getBounds(),
+                    mTmpInsetBounds);
 
             // The bounds are being applied to a specific snap fraction, so reset any known offsets
             // for the previous orientation before updating the movement bounds.
@@ -125,18 +129,22 @@
             // not during the fixed rotation. In fixed rotation case, app is about to enter PiP
             // and we need the offsets preserved to calculate the destination bounds.
             if (!mIsInFixedRotation) {
-                mPipBoundsState.setShelfVisibility(false /* showing */, 0 /* height */);
+                // Update the shelf visibility without updating the movement bounds. We're already
+                // updating them below with the |fromRotation| flag set, which is more accurate
+                // than using the |fromShelfAdjustment|.
+                mPipBoundsState.setShelfVisibility(false /* showing */, 0 /* height */,
+                        false /* updateMovementBounds */);
                 mPipBoundsState.setImeVisibility(false /* showing */, 0 /* height */);
                 mTouchHandler.onShelfVisibilityChanged(false, 0);
                 mTouchHandler.onImeVisibilityChanged(false, 0);
             }
 
-            updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
-                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
+            updateMovementBounds(outBounds, true /* fromRotation */, false /* fromImeAdjustment */,
+                    false /* fromShelfAdjustment */, t);
         }
     };
 
-    private DisplayController.OnDisplaysChangedListener mFixedRotationListener =
+    private final DisplayController.OnDisplaysChangedListener mFixedRotationListener =
             new DisplayController.OnDisplaysChangedListener() {
                 @Override
                 public void onFixedRotationStarted(int displayId, int newRotation) {
@@ -188,18 +196,6 @@
         }
 
         @Override
-        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
-            mPipBoundsState.setDisplayInfo(displayInfo);
-        }
-
-        @Override
-        public void onConfigurationChanged() {
-            mPipBoundsAlgorithm.onConfigurationChanged(mContext);
-            mTouchHandler.onConfigurationChanged();
-            mPipBoundsState.onConfigurationChanged();
-        }
-
-        @Override
         public void onAspectRatioChanged(float aspectRatio) {
             // TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
             // change.
@@ -256,12 +252,16 @@
                             false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
                             null /* wct */);
                 });
-        mPipBoundsState.setOnShelfVisibilityChangeCallback((isShowing, height) -> {
-            mTouchHandler.onShelfVisibilityChanged(isShowing, height);
-            updateMovementBounds(mPipBoundsState.getBounds(),
-                    false /* fromRotation */, false /* fromImeAdjustment */,
-                    true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
-        });
+        mPipBoundsState.setOnShelfVisibilityChangeCallback(
+                (isShowing, height, updateMovementBounds) -> {
+                    mTouchHandler.onShelfVisibilityChanged(isShowing, height);
+                    if (updateMovementBounds) {
+                        updateMovementBounds(mPipBoundsState.getBounds(),
+                                false /* fromRotation */, false /* fromImeAdjustment */,
+                                true /* fromShelfAdjustment */,
+                                null /* windowContainerTransaction */);
+                    }
+                });
         if (mTouchHandler != null) {
             // Register the listener for input consumer touch events. Only for Phone
             mPipInputConsumer.setInputListener(mTouchHandler::handleTouchEvent);
@@ -334,6 +334,15 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mMainExecutor.execute(() -> {
+            mPipBoundsAlgorithm.onConfigurationChanged(mContext);
+            mTouchHandler.onConfigurationChanged();
+            mPipBoundsState.onConfigurationChanged();
+        });
+    }
+
+    @Override
     public void onDensityOrFontScaleChanged() {
         mMainExecutor.execute(() -> {
             mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
@@ -437,10 +446,8 @@
     @Override
     public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) {
         if (isOutPipDirection(direction)) {
-            // Exiting PIP, save the reentry bounds to restore to when re-entering.
-            updateReentryBounds(pipBounds);
-            final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mReentryBounds);
-            mPipBoundsState.saveReentryState(mReentryBounds, snapFraction);
+            // Exiting PIP, save the reentry state to restore to when re-entering.
+            saveReentryState(pipBounds);
         }
         // Disable touches while the animation is running
         mTouchHandler.setTouchEnabled(false);
@@ -449,14 +456,16 @@
         }
     }
 
-    /**
-     * Update the bounds used to save the re-entry size and snap fraction when exiting PIP.
-     */
-    public void updateReentryBounds(Rect bounds) {
-        final Rect reentryBounds = mTouchHandler.getUserResizeBounds();
-        float snapFraction = mPipBoundsAlgorithm.getSnapFraction(bounds);
-        mPipBoundsAlgorithm.applySnapFraction(reentryBounds, snapFraction);
-        mReentryBounds.set(reentryBounds);
+    /** Save the state to restore to on re-entry. */
+    public void saveReentryState(Rect pipBounds) {
+        float snapFraction = mPipBoundsAlgorithm.getSnapFraction(pipBounds);
+        if (mPipBoundsState.hasUserResizedPip()) {
+            final Rect reentryBounds = mTouchHandler.getUserResizeBounds();
+            final Size reentrySize = new Size(reentryBounds.width(), reentryBounds.height());
+            mPipBoundsState.saveReentryState(reentrySize, snapFraction);
+        } else {
+            mPipBoundsState.saveReentryState(null /* bounds */, snapFraction);
+        }
     }
 
     /**
@@ -532,7 +541,7 @@
      *
      * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
      */
-    public boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds,
+    private boolean onDisplayRotationChanged(Context context, Rect outBounds, Rect oldBounds,
             Rect outInsetBounds,
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
         // Bail early if the event is not sent to current {@link #mDisplayInfo}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 88a1168..02f6231c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -93,6 +93,7 @@
 
     private int mDelta;
     private float mTouchSlop;
+
     private boolean mAllowGesture;
     private boolean mIsAttached;
     private boolean mIsEnabled;
@@ -409,6 +410,7 @@
 
                 mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
                         null);
+                mPipBoundsState.setHasUserResizedPip(true);
             }
         }
     }
@@ -461,6 +463,7 @@
                                 true /* useCurrentSize */);
                         mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
                                 null);
+                        mPipBoundsState.setHasUserResizedPip(true);
                     }
                     break;
                 case MotionEvent.ACTION_UP:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 9281f58..33439a4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -86,7 +86,7 @@
     private boolean mEnableStash = true;
 
     // The reference inset bounds, used to determine the dismiss fraction
-    private Rect mInsetBounds = new Rect();
+    private final Rect mInsetBounds = new Rect();
     private int mExpandedShortestEdgeSize;
 
     // Used to workaround an issue where the WM rotation happens before we are notified, allowing
@@ -94,7 +94,8 @@
     private int mDeferResizeToNormalBoundsUntilRotation = -1;
     private int mDisplayRotation;
 
-    private Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler();
+    private final PipAccessibilityInteractionConnection mConnection;
 
     // Behaviour states
     private int mMenuState = MENU_STATE_NONE;
@@ -108,7 +109,6 @@
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinDismiss;
-    private PipAccessibilityInteractionConnection mConnection;
 
     // Touch state
     private final PipTouchState mTouchState;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
index 763370b..0955056 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
@@ -37,7 +37,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -56,8 +55,6 @@
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipTaskOrganizer;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -87,42 +84,21 @@
     private static final int TASK_ID_NO_PIP = -1;
     private static final int INVALID_RESOURCE_TYPE = -1;
 
-    public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1;
-
-    /**
-     * PIPed activity is playing a media and it can be paused.
-     */
-    static final int PLAYBACK_STATE_PLAYING = 0;
-    /**
-     * PIPed activity has a paused media and it can be played.
-     */
-    static final int PLAYBACK_STATE_PAUSED = 1;
-    /**
-     * Users are unable to control PIPed activity's media playback.
-     */
-    static final int PLAYBACK_STATE_UNAVAILABLE = 2;
-
-    private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000;
-
-    private int mSuspendPipResizingReason;
-
     private final Context mContext;
     private final PipBoundsState mPipBoundsState;
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final PipTaskOrganizer mPipTaskOrganizer;
     private final PipMediaController mPipMediaController;
     private final TvPipMenuController mTvPipMenuController;
+    private final PipNotification mPipNotification;
 
     private IActivityTaskManager mActivityTaskManager;
     private int mState = STATE_NO_PIP;
-    private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
-    private List<Listener> mListeners = new ArrayList<>();
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
     private int mPipTaskId = TASK_ID_NO_PIP;
     private int mPinnedStackId = INVALID_STACK_ID;
     private String[] mLastPackagesResourceGranted;
-    private PipNotification mPipNotification;
     private ParceledListSlice<RemoteAction> mCustomActions;
     private WindowManagerShellWrapper mWindowManagerShellWrapper;
     private int mResizeAnimationDuration;
@@ -135,9 +111,7 @@
     private boolean mImeVisible;
     private int mImeHeightAdjustment;
 
-    private final Runnable mResizePinnedStackRunnable =
-            () -> resizePinnedStack(mResumeResizePinnedStackRunnableState);
-    private final Runnable mClosePipRunnable = () -> closePip();
+    private final Runnable mClosePipRunnable = this::closePip;
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -237,8 +211,6 @@
         mPipTaskOrganizer.registerPipTransitionCallback(this);
         mActivityTaskManager = ActivityTaskManager.getService();
 
-        addListener(mPipNotification);
-
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(ACTION_CLOSE);
         intentFilter.addAction(ACTION_MENU);
@@ -297,6 +269,7 @@
     /**
      * Updates the PIP per configuration changed.
      */
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         loadConfigurationsAndApply(newConfig);
         mPipNotification.onConfigurationChanged(mContext);
@@ -340,9 +313,8 @@
                 mPinnedStackId = INVALID_STACK_ID;
             }
         }
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onPipActivityClosed();
-        }
+        mPipNotification.dismiss();
+        mTvPipMenuController.hideMenu();
         mHandler.removeCallbacks(mClosePipRunnable);
     }
 
@@ -353,9 +325,9 @@
         if (DEBUG) Log.d(TAG, "movePipToFullscreen(), current state=" + getStateDescription());
 
         mPipTaskId = TASK_ID_NO_PIP;
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onMoveToFullscreen();
-        }
+        mTvPipMenuController.hideMenu();
+        mPipNotification.dismiss();
+
         resizePinnedStack(STATE_NO_PIP);
     }
 
@@ -379,9 +351,7 @@
         // Set state to STATE_PIP so we show it when the pinned stack animation ends.
         mState = STATE_PIP;
         mPipMediaController.onActivityPinned();
-        for (int i = mListeners.size() - 1; i >= 0; i--) {
-            mListeners.get(i).onPipEntered(packageName);
-        }
+        mPipNotification.show(packageName);
     }
 
     private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
@@ -428,61 +398,17 @@
     }
 
     /**
-     * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called
-     *
-     * @param reason The reason for suspending resizing operations on the Pip.
-     */
-    public void suspendPipResizing(int reason) {
-        if (DEBUG) {
-            Log.d(TAG,
-                    "suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
-        }
-        mSuspendPipResizingReason |= reason;
-    }
-
-    /**
-     * Resumes resizing operation on the Pip that was previously suspended.
-     *
-     * @param reason The reason resizing operations on the Pip was suspended.
-     */
-    public void resumePipResizing(int reason) {
-        if ((mSuspendPipResizingReason & reason) == 0) {
-            return;
-        }
-        if (DEBUG) {
-            Log.d(TAG,
-                    "resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
-        }
-        mSuspendPipResizingReason &= ~reason;
-        mHandler.post(mResizePinnedStackRunnable);
-    }
-
-    /**
      * Resize the Pip to the appropriate size for the input state.
      *
      * @param state In Pip state also used to determine the new size for the Pip.
      */
     public void resizePinnedStack(int state) {
-
         if (DEBUG) {
             Log.d(TAG, "resizePinnedStack() state=" + stateToName(state) + ", current state="
                     + getStateDescription(), new Exception());
         }
-
-        boolean wasStateNoPip = (mState == STATE_NO_PIP);
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onPipResizeAboutToStart();
-        }
-        if (mSuspendPipResizingReason != 0) {
-            mResumeResizePinnedStackRunnableState = state;
-            if (DEBUG) {
-                Log.d(TAG, "resizePinnedStack() deferring"
-                        + " mSuspendPipResizingReason=" + mSuspendPipResizingReason
-                        + " mResumeResizePinnedStackRunnableState="
-                        + stateToName(mResumeResizePinnedStackRunnableState));
-            }
-            return;
-        }
+        final boolean wasStateNoPip = (mState == STATE_NO_PIP);
+        mTvPipMenuController.hideMenu();
         mState = state;
         final Rect newBounds;
         switch (mState) {
@@ -510,45 +436,20 @@
     }
 
     /**
-     * @return the current state, or the pending state if the state change was previously suspended.
+     * @return the current state.
      */
     private int getState() {
-        if (mSuspendPipResizingReason != 0) {
-            return mResumeResizePinnedStackRunnableState;
-        }
         return mState;
     }
 
-    /**
-     * Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned
-     * stack to the centered PIP bound {@link R.config_centeredPictureInPictureBounds}.
-     */
     private void showPipMenu() {
         if (DEBUG) Log.d(TAG, "showPipMenu(), current state=" + getStateDescription());
 
         mState = STATE_PIP_MENU;
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onShowPipMenu();
-        }
-
         mTvPipMenuController.showMenu();
     }
 
     /**
-     * Adds a {@link Listener} to PipController.
-     */
-    void addListener(Listener listener) {
-        mListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link Listener} from PipController.
-     */
-    void removeListener(Listener listener) {
-        mListeners.remove(listener);
-    }
-
-    /**
      * Returns {@code true} if PIP is shown.
      */
     public boolean isPipShown() {
@@ -619,33 +520,8 @@
         }
     }
 
-    /**
-     * A listener interface to receive notification on changes in PIP.
-     */
-    public interface Listener {
-        /**
-         * Invoked when an activity is pinned and PIP manager is set corresponding information.
-         * Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
-         * because there's no guarantee for the PIP manager be return relavent information
-         * correctly. (e.g. {@link Pip.isPipShown}).
-         */
-        void onPipEntered(String packageName);
-        /** Invoked when a PIPed activity is closed. */
-        void onPipActivityClosed();
-        /** Invoked when the PIP menu gets shown. */
-        void onShowPipMenu();
-        /** Invoked when the PIPed activity is about to return back to the fullscreen. */
-        void onMoveToFullscreen();
-        /** Invoked when we are above to start resizing the Pip. */
-        void onPipResizeAboutToStart();
-    }
-
     private String getStateDescription() {
-        if (mSuspendPipResizingReason == 0) {
-            return stateToName(mState);
-        }
-        return stateToName(mResumeResizePinnedStackRunnableState) + " (while " + stateToName(mState)
-                + " is suspended)";
+        return stateToName(mState);
     }
 
     private static String stateToName(int state) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
index 689c3ed..83cb7ce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuView.java
@@ -16,6 +16,9 @@
 
 package com.android.wm.shell.pip.tv;
 
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.annotation.Nullable;
@@ -36,25 +39,22 @@
 /**
  * The Menu View that shows controls of the PiP. Always fullscreen.
  */
-public class PipMenuView extends FrameLayout implements PipController.Listener {
+public class PipMenuView extends FrameLayout {
     private static final String TAG = "PipMenuView";
     private static final boolean DEBUG = PipController.DEBUG;
 
-    private final PipController mPipController;
     private final Animator mFadeInAnimation;
     private final Animator mFadeOutAnimation;
     private final PipControlsViewController mPipControlsViewController;
-    private boolean mRestorePipSizeWhenClose;
+    @Nullable
+    private OnBackPressListener mOnBackPressListener;
 
     public PipMenuView(Context context, PipController pipController) {
         super(context, null, 0);
-        mPipController = pipController;
-
         inflate(context, R.layout.tv_pip_menu, this);
 
         mPipControlsViewController = new PipControlsViewController(
-                findViewById(R.id.pip_controls), mPipController);
-        mRestorePipSizeWhenClose = true;
+                findViewById(R.id.pip_controls), pipController);
         mFadeInAnimation = AnimatorInflater.loadAnimator(
                 mContext, R.anim.tv_pip_menu_fade_in_animation);
         mFadeInAnimation.setTarget(mPipControlsViewController.getView());
@@ -63,16 +63,6 @@
         mFadeOutAnimation.setTarget(mPipControlsViewController.getView());
     }
 
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
-                && event.getAction() == KeyEvent.ACTION_UP) {
-            restorePipAndFinish();
-            return true;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
     @Nullable
     SurfaceControl getWindowSurfaceControl() {
         final ViewRootImpl root = getViewRootImpl();
@@ -87,53 +77,39 @@
     }
 
     void showMenu() {
-        mPipController.addListener(this);
         mFadeInAnimation.start();
         setAlpha(1.0f);
-        try {
-            WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
-                    getViewRootImpl().getInputToken(), true /* grantFocus */);
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to update focus as menu appears", e);
-        }
+        grantWindowFocus(true);
     }
 
     void hideMenu() {
-        mPipController.removeListener(this);
-        mPipController.resumePipResizing(
-                PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
         mFadeOutAnimation.start();
         setAlpha(0.0f);
+        grantWindowFocus(false);
+    }
+
+    private void grantWindowFocus(boolean grantFocus) {
         try {
             WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
-                    getViewRootImpl().getInputToken(), false /* grantFocus */);
+                    getViewRootImpl().getInputToken(), grantFocus);
         } catch (Exception e) {
             Log.e(TAG, "Unable to update focus as menu disappears", e);
         }
     }
 
-    private void restorePipAndFinish() {
-        if (DEBUG) Log.d(TAG, "restorePipAndFinish()");
+    void setOnBackPressListener(OnBackPressListener onBackPressListener) {
+        mOnBackPressListener = onBackPressListener;
+    }
 
-        if (mRestorePipSizeWhenClose) {
-            if (DEBUG) Log.d(TAG, "   > restoring to the default position");
-
-            // When PIP menu activity is closed, restore to the default position.
-            mPipController.resizePinnedStack(PipController.STATE_PIP);
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getKeyCode() == KEYCODE_BACK && event.getAction() == ACTION_UP
+                && mOnBackPressListener != null) {
+            mOnBackPressListener.onBackPress();
+            return true;
+        } else {
+            return super.dispatchKeyEvent(event);
         }
-        hideMenu();
-    }
-
-    @Override
-    public void onPipEntered(String packageName) {
-        if (DEBUG) Log.d(TAG, "onPipEntered(), packageName=" + packageName);
-    }
-
-    @Override
-    public void onPipActivityClosed() {
-        if (DEBUG) Log.d(TAG, "onPipActivityClosed()");
-
-        hideMenu();
     }
 
     void setAppActions(ParceledListSlice<RemoteAction> actions) {
@@ -144,27 +120,7 @@
                 hasCustomActions ? actions.getList() : Collections.emptyList());
     }
 
-    @Override
-    public void onShowPipMenu() {
-        if (DEBUG) Log.d(TAG, "onShowPipMenu()");
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        if (DEBUG) Log.d(TAG, "onMoveToFullscreen()");
-
-        // Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds.
-        // This conflicts with restoring PIP position, so disable it.
-        mRestorePipSizeWhenClose = false;
-        hideMenu();
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() {
-        if (DEBUG) Log.d(TAG, "onPipResizeAboutToStart()");
-
-        hideMenu();
-        mPipController.suspendPipResizing(
-                PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
+    interface OnBackPressListener {
+        void onBackPress();
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
index d56a888..4e0ab66 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
@@ -39,7 +39,7 @@
  * <p>Once it's created, it will manage the PIP notification UI by itself except for handling
  * configuration changes.
  */
-public class PipNotification implements PipController.Listener {
+public class PipNotification {
     private static final boolean DEBUG = PipController.DEBUG;
     private static final String TAG = "PipNotification";
 
@@ -79,38 +79,21 @@
         onConfigurationChanged(context);
     }
 
-    @Override
-    public void onPipEntered(String packageName) {
+    void show(String packageName) {
         mPackageName = packageName;
-        notifyPipNotification();
+        update();
     }
 
-    @Override
-    public void onPipActivityClosed() {
-        dismissPipNotification();
+    void dismiss() {
+        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
+        mNotified = false;
         mPackageName = null;
     }
 
-    @Override
-    public void onShowPipMenu() {
-        // no-op.
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        dismissPipNotification();
-        mPackageName = null;
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() {
-        // no-op.
-    }
-
     private void onMediaMetadataChanged(MediaMetadata metadata) {
         if (updateMediaControllerMetadata(metadata) && mNotified) {
             // update notification
-            notifyPipNotification();
+            update();
         }
     }
 
@@ -123,11 +106,11 @@
         mDefaultIconResId = R.drawable.pip_icon;
         if (mNotified) {
             // update notification
-            notifyPipNotification();
+            update();
         }
     }
 
-    private void notifyPipNotification() {
+    private void update() {
         mNotified = true;
         mNotificationBuilder
                 .setShowWhen(true)
@@ -144,11 +127,6 @@
                 mNotificationBuilder.build());
     }
 
-    private void dismissPipNotification() {
-        mNotified = false;
-        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
-    }
-
     private boolean updateMediaControllerMetadata(MediaMetadata metadata) {
         String title = null;
         Bitmap art = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index 91aef67..5d0d761 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -21,6 +21,7 @@
 import android.app.RemoteAction;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.util.Log;
 import android.view.SurfaceControl;
 
 import com.android.wm.shell.common.SystemWindows;
@@ -31,6 +32,8 @@
  * Manages the visibility of the PiP Menu as user interacts with PiP.
  */
 public class TvPipMenuController implements PipMenuController {
+    private static final String TAG = "TvPipMenuController";
+    private static final boolean DEBUG = PipController.DEBUG;
 
     private final Context mContext;
     private final SystemWindows mSystemWindows;
@@ -52,6 +55,8 @@
 
     @Override
     public void showMenu() {
+        if (DEBUG) Log.d(TAG, "showMenu()");
+
         if (mMenuView != null) {
             mSystemWindows.updateViewLayout(mMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE,
                     mPipBoundsState.getDisplayBounds().width(),
@@ -68,27 +73,62 @@
         }
     }
 
-    @Override
-    public void attach(SurfaceControl leash) {
-        if (mMenuView == null) {
-            mMenuView = new PipMenuView(mContext, mPipController);
-            mSystemWindows.addView(mMenuView,
-                    getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
-                    0, SHELL_ROOT_LAYER_PIP);
-            mLeash = leash;
+    void hideMenu() {
+        if (DEBUG) Log.d(TAG, "hideMenu()");
+
+        if (isMenuVisible()) {
+            mMenuView.hideMenu();
+            mPipController.resizePinnedStack(PipController.STATE_PIP);
         }
     }
 
     @Override
+    public void attach(SurfaceControl leash) {
+        mLeash = leash;
+        attachPipMenuView();
+    }
+
+    @Override
     public void detach() {
+        hideMenu();
+        detachPipMenuView();
+        mLeash = null;
+    }
+
+    private void attachPipMenuView() {
+        if (DEBUG) Log.d(TAG, "attachPipMenuView()");
+
+        if (mMenuView != null) {
+            detachPipMenuView();
+        }
+
+        mMenuView = new PipMenuView(mContext, mPipController);
+        mMenuView.setOnBackPressListener(this::hideMenu);
+        mSystemWindows.addView(mMenuView,
+                getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
+                0, SHELL_ROOT_LAYER_PIP);
+    }
+
+    private void detachPipMenuView() {
+        if (DEBUG) Log.d(TAG, "detachPipMenuView()");
+
+        if (mMenuView == null) {
+            return;
+        }
+
         mSystemWindows.removeView(mMenuView);
         mMenuView = null;
-        mLeash = null;
     }
 
     @Override
     public void setAppActions(ParceledListSlice<RemoteAction> appActions) {
-        mMenuView.setAppActions(appActions);
+        if (DEBUG) Log.d(TAG, "setAppActions(), actions=" + appActions);
+
+        if (mMenuView != null) {
+            mMenuView.setAppActions(appActions);
+        } else {
+            Log.w(TAG, "Cannot set remote actions, there is no View");
+        }
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
deleted file mode 100644
index 2cb1fff..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.util.Property;
-import android.view.View;
-
-import com.android.wm.shell.R;
-import com.android.wm.shell.animation.Interpolators;
-
-/**
- * View for the handle in the docked stack divider.
- */
-public class DividerHandleView extends View {
-
-    private static final Property<DividerHandleView, Integer> WIDTH_PROPERTY =
-            new Property<DividerHandleView, Integer>(Integer.class, "width") {
-                @Override
-                public Integer get(DividerHandleView object) {
-                    return object.mCurrentWidth;
-                }
-
-                @Override
-                public void set(DividerHandleView object, Integer value) {
-                    object.mCurrentWidth = value;
-                    object.invalidate();
-                }
-            };
-
-    private static final Property<DividerHandleView, Integer> HEIGHT_PROPERTY =
-            new Property<DividerHandleView, Integer>(Integer.class, "height") {
-                @Override
-                public Integer get(DividerHandleView object) {
-                    return object.mCurrentHeight;
-                }
-
-                @Override
-                public void set(DividerHandleView object, Integer value) {
-                    object.mCurrentHeight = value;
-                    object.invalidate();
-                }
-            };
-
-    private final Paint mPaint = new Paint();
-    private final int mWidth;
-    private final int mHeight;
-    private final int mCircleDiameter;
-    private int mCurrentWidth;
-    private int mCurrentHeight;
-    private AnimatorSet mAnimator;
-    private boolean mTouching;
-
-    public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
-        mPaint.setAntiAlias(true);
-        mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
-        mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
-        mCurrentWidth = mWidth;
-        mCurrentHeight = mHeight;
-        mCircleDiameter = (mWidth + mHeight) / 3;
-    }
-
-    void setTouching(boolean touching, boolean animate) {
-        if (touching == mTouching) {
-            return;
-        }
-        if (mAnimator != null) {
-            mAnimator.cancel();
-            mAnimator = null;
-        }
-        if (!animate) {
-            if (touching) {
-                mCurrentWidth = mCircleDiameter;
-                mCurrentHeight = mCircleDiameter;
-            } else {
-                mCurrentWidth = mWidth;
-                mCurrentHeight = mHeight;
-            }
-            invalidate();
-        } else {
-            animateToTarget(touching ? mCircleDiameter : mWidth,
-                    touching ? mCircleDiameter : mHeight, touching);
-        }
-        mTouching = touching;
-    }
-
-    private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
-        ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY,
-                mCurrentWidth, targetWidth);
-        ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY,
-                mCurrentHeight, targetHeight);
-        mAnimator = new AnimatorSet();
-        mAnimator.playTogether(widthAnimator, heightAnimator);
-        mAnimator.setDuration(touching
-                ? DividerView.TOUCH_ANIMATION_DURATION
-                : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
-        mAnimator.setInterpolator(touching
-                ? Interpolators.TOUCH_RESPONSE
-                : Interpolators.FAST_OUT_SLOW_IN);
-        mAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimator = null;
-            }
-        });
-        mAnimator.start();
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        int left = getWidth() / 2 - mCurrentWidth / 2;
-        int top = getHeight() / 2 - mCurrentHeight / 2;
-        int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2;
-        canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
-                radius, radius, mPaint);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
deleted file mode 100644
index eb82357..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
-import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.util.Slog;
-import android.view.SurfaceControl;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.TransactionPool;
-
-class DividerImeController implements DisplayImeController.ImePositionProcessor {
-    private static final String TAG = "DividerImeController";
-    private static final boolean DEBUG = SplitScreenController.DEBUG;
-
-    private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
-
-    private final SplitScreenTaskListener mSplits;
-    private final TransactionPool mTransactionPool;
-    private final Handler mHandler;
-    private final TaskOrganizer mTaskOrganizer;
-
-    /**
-     * These are the y positions of the top of the IME surface when it is hidden and when it is
-     * shown respectively. These are NOT necessarily the top of the visible IME itself.
-     */
-    private int mHiddenTop = 0;
-    private int mShownTop = 0;
-
-    // The following are target states (what we are curretly animating towards).
-    /**
-     * {@code true} if, at the end of the animation, the split task positions should be
-     * adjusted by height of the IME. This happens when the secondary split is the IME target.
-     */
-    private boolean mTargetAdjusted = false;
-    /**
-     * {@code true} if, at the end of the animation, the IME should be shown/visible
-     * regardless of what has focus.
-     */
-    private boolean mTargetShown = false;
-    private float mTargetPrimaryDim = 0.f;
-    private float mTargetSecondaryDim = 0.f;
-
-    // The following are the current (most recent) states set during animation
-    /** {@code true} if the secondary split has IME focus. */
-    private boolean mSecondaryHasFocus = false;
-    /** The dimming currently applied to the primary/secondary splits. */
-    private float mLastPrimaryDim = 0.f;
-    private float mLastSecondaryDim = 0.f;
-    /** The most recent y position of the top of the IME surface */
-    private int mLastAdjustTop = -1;
-
-    // The following are states reached last time an animation fully completed.
-    /** {@code true} if the IME was shown/visible by the last-completed animation. */
-    private boolean mImeWasShown = false;
-    /** {@code true} if the split positions were adjusted by the last-completed animation. */
-    private boolean mAdjusted = false;
-
-    /**
-     * When some aspect of split-screen needs to animate independent from the IME,
-     * this will be non-null and control split animation.
-     */
-    @Nullable
-    private ValueAnimator mAnimation = null;
-
-    private boolean mPaused = true;
-    private boolean mPausedTargetAdjusted = false;
-    private boolean mAdjustedWhileHidden = false;
-
-    DividerImeController(SplitScreenTaskListener splits, TransactionPool pool, Handler handler,
-            TaskOrganizer taskOrganizer) {
-        mSplits = splits;
-        mTransactionPool = pool;
-        mHandler = handler;
-        mTaskOrganizer = taskOrganizer;
-    }
-
-    private DividerView getView() {
-        return mSplits.mSplitScreenController.getDividerView();
-    }
-
-    private SplitDisplayLayout getLayout() {
-        return mSplits.mSplitScreenController.getSplitLayout();
-    }
-
-    private boolean isDividerVisible() {
-        return mSplits.mSplitScreenController.isDividerVisible();
-    }
-
-    private boolean getSecondaryHasFocus(int displayId) {
-        WindowContainerToken imeSplit = mTaskOrganizer.getImeTarget(displayId);
-        return imeSplit != null
-                && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
-    }
-
-    void reset() {
-        mPaused = true;
-        mPausedTargetAdjusted = false;
-        mAdjustedWhileHidden = false;
-        mAnimation = null;
-        mAdjusted = mTargetAdjusted = false;
-        mImeWasShown = mTargetShown = false;
-        mTargetPrimaryDim = mTargetSecondaryDim = mLastPrimaryDim = mLastSecondaryDim = 0.f;
-        mSecondaryHasFocus = false;
-        mLastAdjustTop = -1;
-    }
-
-    private void updateDimTargets() {
-        final boolean splitIsVisible = !getView().isHidden();
-        mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
-                ? ADJUSTED_NONFOCUS_DIM : 0.f;
-        mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
-                ? ADJUSTED_NONFOCUS_DIM : 0.f;
-    }
-
-    @Override
-    @ImeAnimationFlags
-    public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
-            boolean imeShouldShow, boolean imeIsFloating, SurfaceControl.Transaction t) {
-        mHiddenTop = hiddenTop;
-        mShownTop = shownTop;
-        mTargetShown = imeShouldShow;
-        if (!isDividerVisible()) {
-            return 0;
-        }
-        final boolean splitIsVisible = !getView().isHidden();
-        mSecondaryHasFocus = getSecondaryHasFocus(displayId);
-        final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
-                && !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
-                && !mSplits.mSplitScreenController.isMinimized();
-        if (mLastAdjustTop < 0) {
-            mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
-        } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
-            if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
-                // Check for an "interruption" of an existing animation. In this case, we
-                // need to fake-flip the last-known state direction so that the animation
-                // completes in the other direction.
-                mAdjusted = mTargetAdjusted;
-            } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
-                // Already fully adjusted for IME, but IME height has changed; so, force-start
-                // an async animation to the new IME height.
-                mAdjusted = false;
-            }
-        }
-        if (mPaused) {
-            mPausedTargetAdjusted = targetAdjusted;
-            if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
-            return (targetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
-        }
-        mTargetAdjusted = targetAdjusted;
-        updateDimTargets();
-        if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + "  " + dumpState());
-        if (mAnimation != null || (mImeWasShown && imeShouldShow
-                && mTargetAdjusted != mAdjusted)) {
-            // We need to animate adjustment independently of the IME position, so
-            // start our own animation to drive adjustment. This happens when a
-            // different split's editor has gained focus while the IME is still visible.
-            startAsyncAnimation();
-        }
-        if (splitIsVisible) {
-            // If split is hidden, we don't want to trigger any relayouts that would cause the
-            // divider to show again.
-            updateImeAdjustState();
-        } else {
-            mAdjustedWhileHidden = true;
-        }
-        return (mTargetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
-    }
-
-    private void updateImeAdjustState() {
-        updateImeAdjustState(false /* force */);
-    }
-
-    private void updateImeAdjustState(boolean force) {
-        if (mAdjusted != mTargetAdjusted || force) {
-            // Reposition the server's secondary split position so that it evaluates
-            // insets properly.
-            WindowContainerTransaction wct = new WindowContainerTransaction();
-            final SplitDisplayLayout splitLayout = getLayout();
-            if (mTargetAdjusted) {
-                splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
-                wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
-                // "Freeze" the configuration size so that the app doesn't get a config
-                // or relaunch. This is required because normally nav-bar contributes
-                // to configuration bounds (via nondecorframe).
-                Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
-                        .windowConfiguration.getAppBounds());
-                adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top
-                        - splitLayout.mSecondary.top);
-                wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
-                wct.setScreenSizeDp(mSplits.mSecondary.token,
-                        mSplits.mSecondary.configuration.screenWidthDp,
-                        mSplits.mSecondary.configuration.screenHeightDp);
-
-                wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary);
-                adjustAppBounds = new Rect(mSplits.mPrimary.configuration
-                        .windowConfiguration.getAppBounds());
-                adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top
-                        - splitLayout.mPrimary.top);
-                wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
-                wct.setScreenSizeDp(mSplits.mPrimary.token,
-                        mSplits.mPrimary.configuration.screenWidthDp,
-                        mSplits.mPrimary.configuration.screenHeightDp);
-            } else {
-                wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary);
-                wct.setAppBounds(mSplits.mSecondary.token, null);
-                wct.setScreenSizeDp(mSplits.mSecondary.token,
-                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
-                wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary);
-                wct.setAppBounds(mSplits.mPrimary.token, null);
-                wct.setScreenSizeDp(mSplits.mPrimary.token,
-                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
-            }
-
-            if (!mSplits.mSplitScreenController.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
-                mTaskOrganizer.applyTransaction(wct);
-            }
-        }
-
-        // Update all the adjusted-for-ime states
-        if (!mPaused) {
-            final DividerView view = getView();
-            if (view != null) {
-                view.setAdjustedForIme(mTargetShown, mTargetShown
-                        ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
-                        : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
-            }
-        }
-        mSplits.mSplitScreenController.setAdjustedForIme(mTargetShown && !mPaused);
-    }
-
-    public void updateAdjustForIme() {
-        updateImeAdjustState(mAdjustedWhileHidden);
-        mAdjustedWhileHidden = false;
-    }
-
-    @Override
-    public void onImePositionChanged(int displayId, int imeTop,
-            SurfaceControl.Transaction t) {
-        if (mAnimation != null || !isDividerVisible() || mPaused) {
-            // Not synchronized with IME anymore, so return.
-            return;
-        }
-        final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
-        final float progress = mTargetShown ? fraction : 1.f - fraction;
-        onProgress(progress, t);
-    }
-
-    @Override
-    public void onImeEndPositioning(int displayId, boolean cancelled,
-            SurfaceControl.Transaction t) {
-        if (mAnimation != null || !isDividerVisible() || mPaused) {
-            // Not synchronized with IME anymore, so return.
-            return;
-        }
-        onEnd(cancelled, t);
-    }
-
-    private void onProgress(float progress, SurfaceControl.Transaction t) {
-        final DividerView view = getView();
-        if (mTargetAdjusted != mAdjusted && !mPaused) {
-            final SplitDisplayLayout splitLayout = getLayout();
-            final float fraction = mTargetAdjusted ? progress : 1.f - progress;
-            mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
-            splitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
-            view.resizeSplitSurfaces(t, splitLayout.mAdjustedPrimary,
-                    splitLayout.mAdjustedSecondary);
-        }
-        final float invProg = 1.f - progress;
-        view.setResizeDimLayer(t, true /* primary */,
-                mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
-        view.setResizeDimLayer(t, false /* primary */,
-                mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
-    }
-
-    void setDimsHidden(SurfaceControl.Transaction t, boolean hidden) {
-        final DividerView view = getView();
-        if (hidden) {
-            view.setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
-            view.setResizeDimLayer(t, false /* primary */, 0.f /* alpha */);
-        } else {
-            updateDimTargets();
-            view.setResizeDimLayer(t, true /* primary */, mTargetPrimaryDim);
-            view.setResizeDimLayer(t, false /* primary */, mTargetSecondaryDim);
-        }
-    }
-
-    private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
-        if (!cancelled) {
-            onProgress(1.f, t);
-            mAdjusted = mTargetAdjusted;
-            mImeWasShown = mTargetShown;
-            mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
-            mLastPrimaryDim = mTargetPrimaryDim;
-            mLastSecondaryDim = mTargetSecondaryDim;
-        }
-    }
-
-    private void startAsyncAnimation() {
-        if (mAnimation != null) {
-            mAnimation.cancel();
-        }
-        mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
-        mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
-        if (mTargetAdjusted != mAdjusted) {
-            final float fraction =
-                    ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
-            final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
-            mAnimation.setCurrentFraction(progress);
-        }
-
-        mAnimation.addUpdateListener(animation -> {
-            SurfaceControl.Transaction t = mTransactionPool.acquire();
-            float value = (float) animation.getAnimatedValue();
-            onProgress(value, t);
-            t.apply();
-            mTransactionPool.release(t);
-        });
-        mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
-        mAnimation.addListener(new AnimatorListenerAdapter() {
-            private boolean mCancel = false;
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mCancel = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                SurfaceControl.Transaction t = mTransactionPool.acquire();
-                onEnd(mCancel, t);
-                t.apply();
-                mTransactionPool.release(t);
-                mAnimation = null;
-            }
-        });
-        mAnimation.start();
-    }
-
-    private String dumpState() {
-        return "top:" + mHiddenTop + "->" + mShownTop
-                + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
-                + " shw:" + mImeWasShown + "->" + mTargetShown
-                + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
-                + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
-                + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
-                + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
-    }
-
-    /** Completely aborts/resets adjustment state */
-    public void pause(int displayId) {
-        if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
-        mHandler.post(() -> {
-            if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
-            if (mPaused) {
-                return;
-            }
-            mPaused = true;
-            mPausedTargetAdjusted = mTargetAdjusted;
-            mTargetAdjusted = false;
-            mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
-            updateImeAdjustState();
-            startAsyncAnimation();
-            if (mAnimation != null) {
-                mAnimation.end();
-            }
-        });
-    }
-
-    public void resume(int displayId) {
-        if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
-        mHandler.post(() -> {
-            if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
-            if (!mPaused) {
-                return;
-            }
-            mPaused = false;
-            mTargetAdjusted = mPausedTargetAdjusted;
-            updateDimTargets();
-            final DividerView view = getView();
-            if ((mTargetAdjusted != mAdjusted) && !mSplits.mSplitScreenController.isMinimized()
-                    && view != null) {
-                // End unminimize animations since they conflict with adjustment animations.
-                view.finishAnimations();
-            }
-            updateImeAdjustState();
-            startAsyncAnimation();
-        });
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
deleted file mode 100644
index 23d86a0..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-/**
- * Class to hold state of divider that needs to persist across configuration changes.
- */
-final class DividerState {
-    public boolean animateAfterRecentsDrawn;
-    public float mRatioPositionBeforeMinimized;
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
deleted file mode 100644
index c6496ad..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
-import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
-import static android.view.WindowManager.DOCKED_RIGHT;
-
-import android.animation.AnimationHandler;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.Region.Op;
-import android.hardware.display.DisplayManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.view.Display;
-import android.view.MotionEvent;
-import android.view.PointerIcon;
-import android.view.SurfaceControl;
-import android.view.SurfaceControl.Transaction;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewConfiguration;
-import android.view.ViewRootImpl;
-import android.view.ViewTreeObserver.InternalInsetsInfo;
-import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-import android.widget.FrameLayout;
-
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
-import com.android.internal.policy.DockedDividerUtils;
-import com.android.wm.shell.R;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-import com.android.wm.shell.animation.Interpolators;
-
-import java.util.function.Consumer;
-
-/**
- * Docked stack divider.
- */
-public class DividerView extends FrameLayout implements OnTouchListener,
-        OnComputeInternalInsetsListener {
-    private static final String TAG = "DividerView";
-    private static final boolean DEBUG = SplitScreenController.DEBUG;
-
-    interface DividerCallbacks {
-        void onDraggingStart();
-        void onDraggingEnd();
-    }
-
-    static final long TOUCH_ANIMATION_DURATION = 150;
-    static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
-
-    public static final int INVALID_RECENTS_GROW_TARGET = -1;
-
-    private static final int LOG_VALUE_RESIZE_50_50 = 0;
-    private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
-    private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
-
-    private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
-    private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
-
-    private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
-
-    /**
-     * How much the background gets scaled when we are in the minimized dock state.
-     */
-    private static final float MINIMIZE_DOCK_SCALE = 0f;
-    private static final float ADJUSTED_FOR_IME_SCALE = 0.5f;
-
-    private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
-            new PathInterpolator(0.5f, 1f, 0.5f, 1f);
-    private static final PathInterpolator DIM_INTERPOLATOR =
-            new PathInterpolator(.23f, .87f, .52f, -0.11f);
-    private static final Interpolator IME_ADJUST_INTERPOLATOR =
-            new PathInterpolator(0.2f, 0f, 0.1f, 1f);
-
-    private DividerHandleView mHandle;
-    private View mBackground;
-    private MinimizedDockShadow mMinimizedShadow;
-    private int mStartX;
-    private int mStartY;
-    private int mStartPosition;
-    private int mDockSide;
-    private boolean mMoving;
-    private int mTouchSlop;
-    private boolean mBackgroundLifted;
-    private boolean mIsInMinimizeInteraction;
-    SnapTarget mSnapTargetBeforeMinimized;
-
-    private int mDividerInsets;
-    private final Display mDefaultDisplay;
-
-    private int mDividerSize;
-    private int mTouchElevation;
-    private int mLongPressEntraceAnimDuration;
-
-    private final Rect mDockedRect = new Rect();
-    private final Rect mDockedTaskRect = new Rect();
-    private final Rect mOtherTaskRect = new Rect();
-    private final Rect mOtherRect = new Rect();
-    private final Rect mDockedInsetRect = new Rect();
-    private final Rect mOtherInsetRect = new Rect();
-    private final Rect mLastResizeRect = new Rect();
-    private final Rect mTmpRect = new Rect();
-    private SplitScreenController mSplitScreenController;
-    private WindowManagerProxy mWindowManagerProxy;
-    private DividerWindowManager mWindowManager;
-    private VelocityTracker mVelocityTracker;
-    private FlingAnimationUtils mFlingAnimationUtils;
-    private SplitDisplayLayout mSplitLayout;
-    private DividerImeController mImeController;
-    private DividerCallbacks mCallback;
-    private final AnimationHandler mAnimationHandler = new AnimationHandler();
-
-    private ValueAnimator mCurrentAnimator;
-    private boolean mEntranceAnimationRunning;
-    private boolean mExitAnimationRunning;
-    private int mExitStartPosition;
-    private boolean mDockedStackMinimized;
-    private boolean mHomeStackResizable;
-    private boolean mAdjustedForIme;
-    private DividerState mState;
-
-    private SplitScreenTaskListener mTiles;
-    boolean mFirstLayout = true;
-    int mDividerPositionX;
-    int mDividerPositionY;
-
-    private final Matrix mTmpMatrix = new Matrix();
-    private final float[] mTmpValues = new float[9];
-
-    // The view is removed or in the process of been removed from the system.
-    private boolean mRemoved;
-
-    // Whether the surface for this view has been hidden regardless of actual visibility. This is
-    // used interact with keyguard.
-    private boolean mSurfaceHidden = false;
-
-    private final Handler mHandler = new Handler();
-
-    private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
-        @Override
-        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-            super.onInitializeAccessibilityNodeInfo(host, info);
-            final DividerSnapAlgorithm snapAlgorithm = getSnapAlgorithm();
-            if (isHorizontalDivision()) {
-                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
-                        mContext.getString(R.string.accessibility_action_divider_top_full)));
-                if (snapAlgorithm.isFirstSplitTargetAvailable()) {
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
-                            mContext.getString(R.string.accessibility_action_divider_top_70)));
-                }
-                if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
-                    // Only show the middle target if there are more than 1 split target
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
-                            mContext.getString(R.string.accessibility_action_divider_top_50)));
-                }
-                if (snapAlgorithm.isLastSplitTargetAvailable()) {
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
-                            mContext.getString(R.string.accessibility_action_divider_top_30)));
-                }
-                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
-                        mContext.getString(R.string.accessibility_action_divider_bottom_full)));
-            } else {
-                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
-                        mContext.getString(R.string.accessibility_action_divider_left_full)));
-                if (snapAlgorithm.isFirstSplitTargetAvailable()) {
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
-                            mContext.getString(R.string.accessibility_action_divider_left_70)));
-                }
-                if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
-                    // Only show the middle target if there are more than 1 split target
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
-                            mContext.getString(R.string.accessibility_action_divider_left_50)));
-                }
-                if (snapAlgorithm.isLastSplitTargetAvailable()) {
-                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
-                            mContext.getString(R.string.accessibility_action_divider_left_30)));
-                }
-                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
-                        mContext.getString(R.string.accessibility_action_divider_right_full)));
-            }
-        }
-
-        @Override
-        public boolean performAccessibilityAction(View host, int action, Bundle args) {
-            int currentPosition = getCurrentPosition();
-            SnapTarget nextTarget = null;
-            DividerSnapAlgorithm snapAlgorithm = mSplitLayout.getSnapAlgorithm();
-            if (action == R.id.action_move_tl_full) {
-                nextTarget = snapAlgorithm.getDismissEndTarget();
-            } else if (action == R.id.action_move_tl_70) {
-                nextTarget = snapAlgorithm.getLastSplitTarget();
-            } else if (action == R.id.action_move_tl_50) {
-                nextTarget = snapAlgorithm.getMiddleTarget();
-            } else if (action == R.id.action_move_tl_30) {
-                nextTarget = snapAlgorithm.getFirstSplitTarget();
-            } else if (action == R.id.action_move_rb_full) {
-                nextTarget = snapAlgorithm.getDismissStartTarget();
-            }
-            if (nextTarget != null) {
-                startDragging(true /* animate */, false /* touching */);
-                stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
-                return true;
-            }
-            return super.performAccessibilityAction(host, action, args);
-        }
-    };
-
-    private final Runnable mResetBackgroundRunnable = new Runnable() {
-        @Override
-        public void run() {
-            resetBackground();
-        }
-    };
-
-    private Runnable mUpdateEmbeddedMatrix = () -> {
-        if (getViewRootImpl() == null) {
-            return;
-        }
-        if (isHorizontalDivision()) {
-            mTmpMatrix.setTranslate(0, mDividerPositionY - mDividerInsets);
-        } else {
-            mTmpMatrix.setTranslate(mDividerPositionX - mDividerInsets, 0);
-        }
-        mTmpMatrix.getValues(mTmpValues);
-        try {
-            getViewRootImpl().getAccessibilityEmbeddedConnection().setScreenMatrix(mTmpValues);
-        } catch (RemoteException e) {
-        }
-    };
-
-    public DividerView(Context context) {
-        this(context, null);
-    }
-
-    public DividerView(Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        final DisplayManager displayManager =
-                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
-        mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mHandle = findViewById(R.id.docked_divider_handle);
-        mBackground = findViewById(R.id.docked_divider_background);
-        mMinimizedShadow = findViewById(R.id.minimized_dock_shadow);
-        mHandle.setOnTouchListener(this);
-        final int dividerWindowWidth = getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_thickness);
-        mDividerInsets = getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_insets);
-        mDividerSize = dividerWindowWidth - 2 * mDividerInsets;
-        mTouchElevation = getResources().getDimensionPixelSize(
-                R.dimen.docked_stack_divider_lift_elevation);
-        mLongPressEntraceAnimDuration = getResources().getInteger(
-                R.integer.long_press_dock_anim_duration);
-        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
-        mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f);
-        boolean landscape = getResources().getConfiguration().orientation
-                == Configuration.ORIENTATION_LANDSCAPE;
-        mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
-                landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW));
-        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-        mHandle.setAccessibilityDelegate(mHandleDelegate);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        // Save the current target if not minimized once attached to window
-        if (mDockSide != WindowManager.DOCKED_INVALID && !mIsInMinimizeInteraction) {
-            saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized);
-        }
-        mFirstLayout = true;
-    }
-
-    void onDividerRemoved() {
-        mRemoved = true;
-        mCallback = null;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (mFirstLayout) {
-            // Wait for first layout so that the ViewRootImpl surface has been created.
-            initializeSurfaceState();
-            mFirstLayout = false;
-        }
-        int minimizeLeft = 0;
-        int minimizeTop = 0;
-        if (mDockSide == WindowManager.DOCKED_TOP) {
-            minimizeTop = mBackground.getTop();
-        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
-            minimizeLeft = mBackground.getLeft();
-        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
-            minimizeLeft = mBackground.getRight() - mMinimizedShadow.getWidth();
-        }
-        mMinimizedShadow.layout(minimizeLeft, minimizeTop,
-                minimizeLeft + mMinimizedShadow.getMeasuredWidth(),
-                minimizeTop + mMinimizedShadow.getMeasuredHeight());
-        if (changed) {
-            notifySplitScreenBoundsChanged();
-        }
-    }
-
-    void injectDependencies(SplitScreenController splitScreenController,
-            DividerWindowManager windowManager, DividerState dividerState,
-            DividerCallbacks callback, SplitScreenTaskListener tiles, SplitDisplayLayout sdl,
-            DividerImeController imeController, WindowManagerProxy wmProxy) {
-        mSplitScreenController = splitScreenController;
-        mWindowManager = windowManager;
-        mState = dividerState;
-        mCallback = callback;
-        mTiles = tiles;
-        mSplitLayout = sdl;
-        mImeController = imeController;
-        mWindowManagerProxy = wmProxy;
-
-        if (mState.mRatioPositionBeforeMinimized == 0) {
-            // Set the middle target as the initial state
-            mSnapTargetBeforeMinimized = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
-        } else {
-            repositionSnapTargetBeforeMinimized();
-        }
-    }
-
-    /** Gets non-minimized secondary bounds of split screen. */
-    public Rect getNonMinimizedSplitScreenSecondaryBounds() {
-        mOtherTaskRect.set(mSplitLayout.mSecondary);
-        return mOtherTaskRect;
-    }
-
-    private boolean inSplitMode() {
-        return getVisibility() == VISIBLE;
-    }
-
-    /** Unlike setVisible, this directly hides the surface without changing view visibility. */
-    void setHidden(boolean hidden) {
-        if (mSurfaceHidden == hidden) {
-            return;
-        }
-        mSurfaceHidden = hidden;
-        post(() -> {
-            final SurfaceControl sc = getWindowSurfaceControl();
-            if (sc == null) {
-                return;
-            }
-            Transaction t = mTiles.getTransaction();
-            if (hidden) {
-                t.hide(sc);
-            } else {
-                t.show(sc);
-            }
-            mImeController.setDimsHidden(t, hidden);
-            t.apply();
-            mTiles.releaseTransaction(t);
-        });
-    }
-
-    boolean isHidden() {
-        return mSurfaceHidden;
-    }
-
-    /** Starts dragging the divider bar. */
-    public boolean startDragging(boolean animate, boolean touching) {
-        cancelFlingAnimation();
-        if (touching) {
-            mHandle.setTouching(true, animate);
-        }
-        mDockSide = mSplitLayout.getPrimarySplitSide();
-
-        mWindowManagerProxy.setResizing(true);
-        if (touching) {
-            mWindowManager.setSlippery(false);
-            liftBackground();
-        }
-        if (mCallback != null) {
-            mCallback.onDraggingStart();
-        }
-        return inSplitMode();
-    }
-
-    /** Stops dragging the divider bar. */
-    public void stopDragging(int position, float velocity, boolean avoidDismissStart,
-            boolean logMetrics) {
-        mHandle.setTouching(false, true /* animate */);
-        fling(position, velocity, avoidDismissStart, logMetrics);
-        mWindowManager.setSlippery(true);
-        releaseBackground();
-    }
-
-    private void stopDragging(int position, SnapTarget target, long duration,
-            Interpolator interpolator) {
-        stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator);
-    }
-
-    private void stopDragging(int position, SnapTarget target, long duration,
-            Interpolator interpolator, long endDelay) {
-        stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator);
-    }
-
-    private void stopDragging(int position, SnapTarget target, long duration, long startDelay,
-            long endDelay, Interpolator interpolator) {
-        mHandle.setTouching(false, true /* animate */);
-        flingTo(position, target, duration, startDelay, endDelay, interpolator);
-        mWindowManager.setSlippery(true);
-        releaseBackground();
-    }
-
-    private void stopDragging() {
-        mHandle.setTouching(false, true /* animate */);
-        mWindowManager.setSlippery(true);
-        releaseBackground();
-    }
-
-    private void updateDockSide() {
-        mDockSide = mSplitLayout.getPrimarySplitSide();
-        mMinimizedShadow.setDockSide(mDockSide);
-    }
-
-    public DividerSnapAlgorithm getSnapAlgorithm() {
-        return mDockedStackMinimized ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
-                        : mSplitLayout.getSnapAlgorithm();
-    }
-
-    public int getCurrentPosition() {
-        return isHorizontalDivision() ? mDividerPositionY : mDividerPositionX;
-    }
-
-    public boolean isMinimized() {
-        return mDockedStackMinimized;
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-        convertToScreenCoordinates(event);
-        final int action = event.getAction() & MotionEvent.ACTION_MASK;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVelocityTracker = VelocityTracker.obtain();
-                mVelocityTracker.addMovement(event);
-                mStartX = (int) event.getX();
-                mStartY = (int) event.getY();
-                boolean result = startDragging(true /* animate */, true /* touching */);
-                if (!result) {
-
-                    // Weren't able to start dragging successfully, so cancel it again.
-                    stopDragging();
-                }
-                mStartPosition = getCurrentPosition();
-                mMoving = false;
-                return result;
-            case MotionEvent.ACTION_MOVE:
-                mVelocityTracker.addMovement(event);
-                int x = (int) event.getX();
-                int y = (int) event.getY();
-                boolean exceededTouchSlop =
-                        isHorizontalDivision() && Math.abs(y - mStartY) > mTouchSlop
-                                || (!isHorizontalDivision() && Math.abs(x - mStartX) > mTouchSlop);
-                if (!mMoving && exceededTouchSlop) {
-                    mStartX = x;
-                    mStartY = y;
-                    mMoving = true;
-                }
-                if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
-                    SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget(
-                            mStartPosition, 0 /* velocity */, false /* hardDismiss */);
-                    resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget,
-                            null /* transaction */);
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mVelocityTracker.addMovement(event);
-
-                x = (int) event.getRawX();
-                y = (int) event.getRawY();
-
-                mVelocityTracker.computeCurrentVelocity(1000);
-                int position = calculatePosition(x, y);
-                stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
-                        : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,
-                        true /* log */);
-                mMoving = false;
-                break;
-        }
-        return true;
-    }
-
-    private void logResizeEvent(SnapTarget snapTarget) {
-        if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissStartTarget()) {
-            MetricsLogger.action(
-                    mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
-                            ? LOG_VALUE_UNDOCK_MAX_OTHER
-                            : LOG_VALUE_UNDOCK_MAX_DOCKED);
-        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissEndTarget()) {
-            MetricsLogger.action(
-                    mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
-                            ? LOG_VALUE_UNDOCK_MAX_OTHER
-                            : LOG_VALUE_UNDOCK_MAX_DOCKED);
-        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getMiddleTarget()) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
-                    LOG_VALUE_RESIZE_50_50);
-        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getFirstSplitTarget()) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
-                    dockSideTopLeft(mDockSide)
-                            ? LOG_VALUE_RESIZE_DOCKED_SMALLER
-                            : LOG_VALUE_RESIZE_DOCKED_LARGER);
-        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getLastSplitTarget()) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
-                    dockSideTopLeft(mDockSide)
-                            ? LOG_VALUE_RESIZE_DOCKED_LARGER
-                            : LOG_VALUE_RESIZE_DOCKED_SMALLER);
-        }
-    }
-
-    private void convertToScreenCoordinates(MotionEvent event) {
-        event.setLocation(event.getRawX(), event.getRawY());
-    }
-
-    private void fling(int position, float velocity, boolean avoidDismissStart,
-            boolean logMetrics) {
-        DividerSnapAlgorithm currentSnapAlgorithm = getSnapAlgorithm();
-        SnapTarget snapTarget = currentSnapAlgorithm.calculateSnapTarget(position, velocity);
-        if (avoidDismissStart && snapTarget == currentSnapAlgorithm.getDismissStartTarget()) {
-            snapTarget = currentSnapAlgorithm.getFirstSplitTarget();
-        }
-        if (logMetrics) {
-            logResizeEvent(snapTarget);
-        }
-        ValueAnimator anim = getFlingAnimator(position, snapTarget, 0 /* endDelay */);
-        mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity);
-        anim.start();
-    }
-
-    private void flingTo(int position, SnapTarget target, long duration, long startDelay,
-            long endDelay, Interpolator interpolator) {
-        ValueAnimator anim = getFlingAnimator(position, target, endDelay);
-        anim.setDuration(duration);
-        anim.setStartDelay(startDelay);
-        anim.setInterpolator(interpolator);
-        anim.start();
-    }
-
-    private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget,
-            final long endDelay) {
-        if (mCurrentAnimator != null) {
-            cancelFlingAnimation();
-            updateDockSide();
-        }
-        if (DEBUG) Slog.d(TAG, "Getting fling " + position + "->" + snapTarget.position);
-        final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
-        ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
-        anim.addUpdateListener(animation -> resizeStackSurfaces((int) animation.getAnimatedValue(),
-                taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
-                        ? TASK_POSITION_SAME
-                        : snapTarget.taskPosition,
-                snapTarget, null /* transaction */));
-        Consumer<Boolean> endAction = cancelled -> {
-            if (DEBUG) Slog.d(TAG, "End Fling " + cancelled + " min:" + mIsInMinimizeInteraction);
-            final boolean wasMinimizeInteraction = mIsInMinimizeInteraction;
-            // Reset minimized divider position after unminimized state animation finishes.
-            if (!cancelled && !mDockedStackMinimized && mIsInMinimizeInteraction) {
-                mIsInMinimizeInteraction = false;
-            }
-            boolean dismissed = commitSnapFlags(snapTarget);
-            mWindowManagerProxy.setResizing(false);
-            updateDockSide();
-            mCurrentAnimator = null;
-            mEntranceAnimationRunning = false;
-            mExitAnimationRunning = false;
-            if (!dismissed && !wasMinimizeInteraction) {
-                mWindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout);
-            }
-            if (mCallback != null) {
-                mCallback.onDraggingEnd();
-            }
-
-            // Record last snap target the divider moved to
-            if (!mIsInMinimizeInteraction) {
-                // The last snapTarget position can be negative when the last divider position was
-                // offscreen. In that case, save the middle (default) SnapTarget so calculating next
-                // position isn't negative.
-                final SnapTarget saveTarget;
-                if (snapTarget.position < 0) {
-                    saveTarget = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
-                } else {
-                    saveTarget = snapTarget;
-                }
-                final DividerSnapAlgorithm snapAlgo = mSplitLayout.getSnapAlgorithm();
-                if (saveTarget.position != snapAlgo.getDismissEndTarget().position
-                        && saveTarget.position != snapAlgo.getDismissStartTarget().position) {
-                    saveSnapTargetBeforeMinimized(saveTarget);
-                }
-            }
-            notifySplitScreenBoundsChanged();
-        };
-        anim.addListener(new AnimatorListenerAdapter() {
-
-            private boolean mCancelled;
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mCancelled = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                long delay = 0;
-                if (endDelay != 0) {
-                    delay = endDelay;
-                } else if (mCancelled) {
-                    delay = 0;
-                }
-                if (delay == 0) {
-                    endAction.accept(mCancelled);
-                } else {
-                    final Boolean cancelled = mCancelled;
-                    if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms");
-                    mHandler.postDelayed(() -> endAction.accept(cancelled), delay);
-                }
-            }
-        });
-        anim.setAnimationHandler(mAnimationHandler);
-        mCurrentAnimator = anim;
-        return anim;
-    }
-
-    private void notifySplitScreenBoundsChanged() {
-        if (mSplitLayout.mPrimary == null || mSplitLayout.mSecondary == null) {
-            return;
-        }
-        mOtherTaskRect.set(mSplitLayout.mSecondary);
-
-        mTmpRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), mHandle.getBottom());
-        if (isHorizontalDivision()) {
-            mTmpRect.offsetTo(0, mDividerPositionY);
-        } else {
-            mTmpRect.offsetTo(mDividerPositionX, 0);
-        }
-        mWindowManagerProxy.setTouchRegion(mTmpRect);
-
-        mTmpRect.set(mSplitLayout.mDisplayLayout.stableInsets());
-        switch (mSplitLayout.getPrimarySplitSide()) {
-            case WindowManager.DOCKED_LEFT:
-                mTmpRect.left = 0;
-                break;
-            case WindowManager.DOCKED_RIGHT:
-                mTmpRect.right = 0;
-                break;
-            case WindowManager.DOCKED_TOP:
-                mTmpRect.top = 0;
-                break;
-        }
-        mSplitScreenController.notifyBoundsChanged(mOtherTaskRect, mTmpRect);
-    }
-
-    private void cancelFlingAnimation() {
-        if (mCurrentAnimator != null) {
-            mCurrentAnimator.cancel();
-        }
-    }
-
-    private boolean commitSnapFlags(SnapTarget target) {
-        if (target.flag == SnapTarget.FLAG_NONE) {
-            return false;
-        }
-        final boolean dismissOrMaximize;
-        if (target.flag == SnapTarget.FLAG_DISMISS_START) {
-            dismissOrMaximize = mDockSide == WindowManager.DOCKED_LEFT
-                    || mDockSide == WindowManager.DOCKED_TOP;
-        } else {
-            dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT
-                    || mDockSide == WindowManager.DOCKED_BOTTOM;
-        }
-        mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, mSplitLayout, dismissOrMaximize);
-        Transaction t = mTiles.getTransaction();
-        setResizeDimLayer(t, true /* primary */, 0f);
-        setResizeDimLayer(t, false /* primary */, 0f);
-        t.apply();
-        mTiles.releaseTransaction(t);
-        return true;
-    }
-
-    private void liftBackground() {
-        if (mBackgroundLifted) {
-            return;
-        }
-        if (isHorizontalDivision()) {
-            mBackground.animate().scaleY(1.4f);
-        } else {
-            mBackground.animate().scaleX(1.4f);
-        }
-        mBackground.animate()
-                .setInterpolator(Interpolators.TOUCH_RESPONSE)
-                .setDuration(TOUCH_ANIMATION_DURATION)
-                .translationZ(mTouchElevation)
-                .start();
-
-        // Lift handle as well so it doesn't get behind the background, even though it doesn't
-        // cast shadow.
-        mHandle.animate()
-                .setInterpolator(Interpolators.TOUCH_RESPONSE)
-                .setDuration(TOUCH_ANIMATION_DURATION)
-                .translationZ(mTouchElevation)
-                .start();
-        mBackgroundLifted = true;
-    }
-
-    private void releaseBackground() {
-        if (!mBackgroundLifted) {
-            return;
-        }
-        mBackground.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
-                .translationZ(0)
-                .scaleX(1f)
-                .scaleY(1f)
-                .start();
-        mHandle.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
-                .translationZ(0)
-                .start();
-        mBackgroundLifted = false;
-    }
-
-    private void initializeSurfaceState() {
-        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
-        // Recalculate the split-layout's internal tile bounds
-        mSplitLayout.resizeSplits(midPos);
-        Transaction t = mTiles.getTransaction();
-        if (mDockedStackMinimized) {
-            int position = mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
-                    .getMiddleTarget().position;
-            calculateBoundsForPosition(position, mDockSide, mDockedRect);
-            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
-                    mOtherRect);
-            mDividerPositionX = mDividerPositionY = position;
-            resizeSplitSurfaces(t, mDockedRect, mSplitLayout.mPrimary,
-                    mOtherRect, mSplitLayout.mSecondary);
-        } else {
-            resizeSplitSurfaces(t, mSplitLayout.mPrimary, null,
-                    mSplitLayout.mSecondary, null);
-        }
-        setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
-        setResizeDimLayer(t, false /* secondary */, 0.f /* alpha */);
-        t.apply();
-        mTiles.releaseTransaction(t);
-
-        // Get the actually-visible bar dimensions (relative to full window). This is a thin
-        // bar going through the center.
-        final Rect dividerBar = isHorizontalDivision()
-                ? new Rect(0, mDividerInsets, mSplitLayout.mDisplayLayout.width(),
-                mDividerInsets + mDividerSize)
-                : new Rect(mDividerInsets, 0, mDividerInsets + mDividerSize,
-                mSplitLayout.mDisplayLayout.height());
-        final Region touchRegion = new Region(dividerBar);
-        // Add in the "draggable" portion. While not visible, this is an expanded area that the
-        // user can interact with.
-        touchRegion.union(new Rect(mHandle.getLeft(), mHandle.getTop(),
-                mHandle.getRight(), mHandle.getBottom()));
-        mWindowManager.setTouchRegion(touchRegion);
-    }
-
-    void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable,
-            Transaction t) {
-        mHomeStackResizable = isHomeStackResizable;
-        updateDockSide();
-        if (!minimized) {
-            resetBackground();
-        }
-        mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
-        if (mDockedStackMinimized != minimized) {
-            mDockedStackMinimized = minimized;
-            if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) {
-                // Splitscreen to minimize is about to starts after rotating landscape to seascape,
-                // update display info and snap algorithm targets
-                repositionSnapTargetBeforeMinimized();
-            }
-            if (mIsInMinimizeInteraction != minimized || mCurrentAnimator != null) {
-                cancelFlingAnimation();
-                if (minimized) {
-                    // Relayout to recalculate the divider shadow when minimizing
-                    requestLayout();
-                    mIsInMinimizeInteraction = true;
-                    resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
-                            .getMiddleTarget(), t);
-                } else {
-                    resizeStackSurfaces(mSnapTargetBeforeMinimized, t);
-                    mIsInMinimizeInteraction = false;
-                }
-            }
-        }
-    }
-
-    void enterSplitMode(boolean isHomeStackResizable) {
-        setHidden(false);
-
-        SnapTarget miniMid =
-                mSplitLayout.getMinimizedSnapAlgorithm(isHomeStackResizable).getMiddleTarget();
-        if (mDockedStackMinimized) {
-            mDividerPositionY = mDividerPositionX = miniMid.position;
-        }
-    }
-
-    /**
-     * Tries to grab a surface control from ViewRootImpl. If this isn't available for some reason
-     * (ie. the window isn't ready yet), it will get the surfacecontrol that the WindowlessWM has
-     * assigned to it.
-     */
-    private SurfaceControl getWindowSurfaceControl() {
-        final ViewRootImpl root = getViewRootImpl();
-        if (root == null) {
-            return null;
-        }
-        SurfaceControl out = root.getSurfaceControl();
-        if (out != null && out.isValid()) {
-            return out;
-        }
-        return mWindowManager.mSystemWindows.getViewSurface(this);
-    }
-
-    void exitSplitMode() {
-        // The view is going to be removed right after this function involved, updates the surface
-        // in the current thread instead of posting it to the view's UI thread.
-        final SurfaceControl sc = getWindowSurfaceControl();
-        if (sc == null) {
-            return;
-        }
-        Transaction t = mTiles.getTransaction();
-        t.hide(sc);
-        mImeController.setDimsHidden(t, true);
-        t.apply();
-        mTiles.releaseTransaction(t);
-
-        // Reset tile bounds
-        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
-        mWindowManagerProxy.applyResizeSplits(midPos, mSplitLayout);
-    }
-
-    void setMinimizedDockStack(boolean minimized, long animDuration,
-            boolean isHomeStackResizable) {
-        if (DEBUG) Slog.d(TAG, "setMinDock: " + mDockedStackMinimized + "->" + minimized);
-        mHomeStackResizable = isHomeStackResizable;
-        updateDockSide();
-        if (mDockedStackMinimized != minimized) {
-            mIsInMinimizeInteraction = true;
-            mDockedStackMinimized = minimized;
-            stopDragging(minimized
-                            ? mSnapTargetBeforeMinimized.position
-                            : getCurrentPosition(),
-                    minimized
-                            ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable)
-                                    .getMiddleTarget()
-                            : mSnapTargetBeforeMinimized,
-                    animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
-            setAdjustedForIme(false, animDuration);
-        }
-        if (!minimized) {
-            mBackground.animate().withEndAction(mResetBackgroundRunnable);
-        }
-        mBackground.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .setDuration(animDuration)
-                .start();
-    }
-
-    // Needed to end any currently playing animations when they might compete with other anims
-    // (specifically, IME adjust animation immediately after leaving minimized). Someday maybe
-    // these can be unified, but not today.
-    void finishAnimations() {
-        if (mCurrentAnimator != null) {
-            mCurrentAnimator.end();
-        }
-    }
-
-    void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
-        if (mAdjustedForIme == adjustedForIme) {
-            return;
-        }
-        updateDockSide();
-        mHandle.animate()
-                .setInterpolator(IME_ADJUST_INTERPOLATOR)
-                .setDuration(animDuration)
-                .alpha(adjustedForIme ? 0f : 1f)
-                .start();
-        if (mDockSide == WindowManager.DOCKED_TOP) {
-            mBackground.setPivotY(0);
-            mBackground.animate()
-                    .scaleY(adjustedForIme ? ADJUSTED_FOR_IME_SCALE : 1f);
-        }
-        if (!adjustedForIme) {
-            mBackground.animate().withEndAction(mResetBackgroundRunnable);
-        }
-        mBackground.animate()
-                .setInterpolator(IME_ADJUST_INTERPOLATOR)
-                .setDuration(animDuration)
-                .start();
-        mAdjustedForIme = adjustedForIme;
-    }
-
-    private void saveSnapTargetBeforeMinimized(SnapTarget target) {
-        mSnapTargetBeforeMinimized = target;
-        mState.mRatioPositionBeforeMinimized = (float) target.position
-                / (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
-                        : mSplitLayout.mDisplayLayout.width());
-    }
-
-    private void resetBackground() {
-        mBackground.setPivotX(mBackground.getWidth() / 2);
-        mBackground.setPivotY(mBackground.getHeight() / 2);
-        mBackground.setScaleX(1f);
-        mBackground.setScaleY(1f);
-        mMinimizedShadow.setAlpha(0f);
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-    }
-
-    private void repositionSnapTargetBeforeMinimized() {
-        int position = (int) (mState.mRatioPositionBeforeMinimized
-                * (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
-                        : mSplitLayout.mDisplayLayout.width()));
-
-        // Set the snap target before minimized but do not save until divider is attached and not
-        // minimized because it does not know its minimized state yet.
-        mSnapTargetBeforeMinimized =
-                mSplitLayout.getSnapAlgorithm().calculateNonDismissingSnapTarget(position);
-    }
-
-    private int calculatePosition(int touchX, int touchY) {
-        return isHorizontalDivision() ? calculateYPosition(touchY) : calculateXPosition(touchX);
-    }
-
-    public boolean isHorizontalDivision() {
-        return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
-    }
-
-    private int calculateXPosition(int touchX) {
-        return mStartPosition + touchX - mStartX;
-    }
-
-    private int calculateYPosition(int touchY) {
-        return mStartPosition + touchY - mStartY;
-    }
-
-    private void alignTopLeft(Rect containingRect, Rect rect) {
-        int width = rect.width();
-        int height = rect.height();
-        rect.set(containingRect.left, containingRect.top,
-                containingRect.left + width, containingRect.top + height);
-    }
-
-    private void alignBottomRight(Rect containingRect, Rect rect) {
-        int width = rect.width();
-        int height = rect.height();
-        rect.set(containingRect.right - width, containingRect.bottom - height,
-                containingRect.right, containingRect.bottom);
-    }
-
-    private void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
-        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect,
-                mSplitLayout.mDisplayLayout.width(), mSplitLayout.mDisplayLayout.height(),
-                mDividerSize);
-    }
-
-    private void resizeStackSurfaces(SnapTarget taskSnapTarget, Transaction t) {
-        resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget, t);
-    }
-
-    void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect otherRect) {
-        resizeSplitSurfaces(t, dockedRect, null, otherRect, null);
-    }
-
-    private void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect dockedTaskRect,
-            Rect otherRect, Rect otherTaskRect) {
-        dockedTaskRect = dockedTaskRect == null ? dockedRect : dockedTaskRect;
-        otherTaskRect = otherTaskRect == null ? otherRect : otherTaskRect;
-
-        mDividerPositionX = mSplitLayout.getPrimarySplitSide() == DOCKED_RIGHT
-                ? otherRect.right : dockedRect.right;
-        mDividerPositionY = dockedRect.bottom;
-
-        if (DEBUG) {
-            Slog.d(TAG, "Resizing split surfaces: " + dockedRect + " " + dockedTaskRect
-                    + " " + otherRect + " " + otherTaskRect);
-        }
-
-        t.setPosition(mTiles.mPrimarySurface, dockedTaskRect.left, dockedTaskRect.top);
-        Rect crop = new Rect(dockedRect);
-        crop.offsetTo(-Math.min(dockedTaskRect.left - dockedRect.left, 0),
-                -Math.min(dockedTaskRect.top - dockedRect.top, 0));
-        t.setWindowCrop(mTiles.mPrimarySurface, crop);
-        t.setPosition(mTiles.mSecondarySurface, otherTaskRect.left, otherTaskRect.top);
-        crop.set(otherRect);
-        crop.offsetTo(-(otherTaskRect.left - otherRect.left),
-                -(otherTaskRect.top - otherRect.top));
-        t.setWindowCrop(mTiles.mSecondarySurface, crop);
-        final SurfaceControl dividerCtrl = getWindowSurfaceControl();
-        if (dividerCtrl != null) {
-            if (isHorizontalDivision()) {
-                t.setPosition(dividerCtrl, 0, mDividerPositionY - mDividerInsets);
-            } else {
-                t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0);
-            }
-        }
-        if (getViewRootImpl() != null) {
-            mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
-            mHandler.post(mUpdateEmbeddedMatrix);
-        }
-    }
-
-    void setResizeDimLayer(Transaction t, boolean primary, float alpha) {
-        SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim;
-        if (alpha <= 0.001f) {
-            t.hide(dim);
-        } else {
-            t.setAlpha(dim, alpha);
-            t.show(dim);
-        }
-    }
-
-    void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget,
-            Transaction transaction) {
-        if (mRemoved) {
-            // This divider view has been removed so shouldn't have any additional influence.
-            return;
-        }
-        calculateBoundsForPosition(position, mDockSide, mDockedRect);
-        calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
-                mOtherRect);
-
-        if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
-            return;
-        }
-
-        // Make sure shadows are updated
-        if (mBackground.getZ() > 0f) {
-            mBackground.invalidate();
-        }
-
-        final boolean ownTransaction = transaction == null;
-        final Transaction t = ownTransaction ? mTiles.getTransaction() : transaction;
-        mLastResizeRect.set(mDockedRect);
-        if (mIsInMinimizeInteraction) {
-            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
-                    mDockedTaskRect);
-            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
-                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
-
-            // Move a right-docked-app to line up with the divider while dragging it
-            if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
-                        - mDockedTaskRect.left + mDividerSize, 0);
-            }
-            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
-            if (ownTransaction) {
-                t.apply();
-                mTiles.releaseTransaction(t);
-            }
-            return;
-        }
-
-        if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
-            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
-
-            // Move a docked app if from the right in position with the divider up to insets
-            if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
-                        - mDockedTaskRect.left + mDividerSize, 0);
-            }
-            calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
-                    mOtherTaskRect);
-            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
-        } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
-            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
-            mDockedInsetRect.set(mDockedTaskRect);
-            calculateBoundsForPosition(mExitStartPosition,
-                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
-            mOtherInsetRect.set(mOtherTaskRect);
-            applyExitAnimationParallax(mOtherTaskRect, position);
-
-            // Move a right-docked-app to line up with the divider while dragging it
-            if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(position + mDividerSize, 0);
-            }
-            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
-        } else if (taskPosition != TASK_POSITION_SAME) {
-            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
-                    mOtherRect);
-            int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide);
-            int taskPositionDocked =
-                    restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget);
-            int taskPositionOther =
-                    restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
-            calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
-            calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
-            mTmpRect.set(0, 0, mSplitLayout.mDisplayLayout.width(),
-                    mSplitLayout.mDisplayLayout.height());
-            alignTopLeft(mDockedRect, mDockedTaskRect);
-            alignTopLeft(mOtherRect, mOtherTaskRect);
-            mDockedInsetRect.set(mDockedTaskRect);
-            mOtherInsetRect.set(mOtherTaskRect);
-            if (dockSideTopLeft(mDockSide)) {
-                alignTopLeft(mTmpRect, mDockedInsetRect);
-                alignBottomRight(mTmpRect, mOtherInsetRect);
-            } else {
-                alignBottomRight(mTmpRect, mDockedInsetRect);
-                alignTopLeft(mTmpRect, mOtherInsetRect);
-            }
-            applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
-                    taskPositionDocked);
-            applyDismissingParallax(mOtherTaskRect, dockSideInverted, taskSnapTarget, position,
-                    taskPositionOther);
-            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
-        } else {
-            resizeSplitSurfaces(t, mDockedRect, null, mOtherRect, null);
-        }
-        SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position);
-        float dimFraction = getDimFraction(position, closestDismissTarget);
-        setResizeDimLayer(t, isDismissTargetPrimary(closestDismissTarget), dimFraction);
-        if (ownTransaction) {
-            t.apply();
-            mTiles.releaseTransaction(t);
-        }
-    }
-
-    private void applyExitAnimationParallax(Rect taskRect, int position) {
-        if (mDockSide == WindowManager.DOCKED_TOP) {
-            taskRect.offset(0, (int) ((position - mExitStartPosition) * 0.25f));
-        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
-            taskRect.offset((int) ((position - mExitStartPosition) * 0.25f), 0);
-        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
-            taskRect.offset((int) ((mExitStartPosition - position) * 0.25f), 0);
-        }
-    }
-
-    private float getDimFraction(int position, SnapTarget dismissTarget) {
-        if (mEntranceAnimationRunning) {
-            return 0f;
-        }
-        float fraction = getSnapAlgorithm().calculateDismissingFraction(position);
-        fraction = Math.max(0, Math.min(fraction, 1f));
-        fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
-        return fraction;
-    }
-
-    /**
-     * When the snap target is dismissing one side, make sure that the dismissing side doesn't get
-     * 0 size.
-     */
-    private int restrictDismissingTaskPosition(int taskPosition, int dockSide,
-            SnapTarget snapTarget) {
-        if (snapTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(dockSide)) {
-            return Math.max(mSplitLayout.getSnapAlgorithm().getFirstSplitTarget().position,
-                    mStartPosition);
-        } else if (snapTarget.flag == SnapTarget.FLAG_DISMISS_END
-                && dockSideBottomRight(dockSide)) {
-            return Math.min(mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position,
-                    mStartPosition);
-        } else {
-            return taskPosition;
-        }
-    }
-
-    /**
-     * Applies a parallax to the task when dismissing.
-     */
-    private void applyDismissingParallax(Rect taskRect, int dockSide, SnapTarget snapTarget,
-            int position, int taskPosition) {
-        float fraction = Math.min(1, Math.max(0,
-                mSplitLayout.getSnapAlgorithm().calculateDismissingFraction(position)));
-        SnapTarget dismissTarget = null;
-        SnapTarget splitTarget = null;
-        int start = 0;
-        if (position <= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
-                && dockSideTopLeft(dockSide)) {
-            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
-            splitTarget = mSplitLayout.getSnapAlgorithm().getFirstSplitTarget();
-            start = taskPosition;
-        } else if (position >= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
-                && dockSideBottomRight(dockSide)) {
-            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissEndTarget();
-            splitTarget = mSplitLayout.getSnapAlgorithm().getLastSplitTarget();
-            start = splitTarget.position;
-        }
-        if (dismissTarget != null && fraction > 0f
-                && isDismissing(splitTarget, position, dockSide)) {
-            fraction = calculateParallaxDismissingFraction(fraction, dockSide);
-            int offsetPosition = (int) (start + fraction
-                    * (dismissTarget.position - splitTarget.position));
-            int width = taskRect.width();
-            int height = taskRect.height();
-            switch (dockSide) {
-                case WindowManager.DOCKED_LEFT:
-                    taskRect.left = offsetPosition - width;
-                    taskRect.right = offsetPosition;
-                    break;
-                case WindowManager.DOCKED_RIGHT:
-                    taskRect.left = offsetPosition + mDividerSize;
-                    taskRect.right = offsetPosition + width + mDividerSize;
-                    break;
-                case WindowManager.DOCKED_TOP:
-                    taskRect.top = offsetPosition - height;
-                    taskRect.bottom = offsetPosition;
-                    break;
-                case WindowManager.DOCKED_BOTTOM:
-                    taskRect.top = offsetPosition + mDividerSize;
-                    taskRect.bottom = offsetPosition + height + mDividerSize;
-                    break;
-            }
-        }
-    }
-
-    /**
-     * @return for a specified {@code fraction}, this returns an adjusted value that simulates a
-     *         slowing down parallax effect
-     */
-    private static float calculateParallaxDismissingFraction(float fraction, int dockSide) {
-        float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
-
-        // Less parallax at the top, just because.
-        if (dockSide == WindowManager.DOCKED_TOP) {
-            result /= 2f;
-        }
-        return result;
-    }
-
-    private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) {
-        if (dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT) {
-            return position < snapTarget.position;
-        } else {
-            return position > snapTarget.position;
-        }
-    }
-
-    private boolean isDismissTargetPrimary(SnapTarget dismissTarget) {
-        return (dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
-                || (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END
-                        && dockSideBottomRight(mDockSide));
-    }
-
-    /**
-     * @return true if and only if {@code dockSide} is top or left
-     */
-    private static boolean dockSideTopLeft(int dockSide) {
-        return dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT;
-    }
-
-    /**
-     * @return true if and only if {@code dockSide} is bottom or right
-     */
-    private static boolean dockSideBottomRight(int dockSide) {
-        return dockSide == WindowManager.DOCKED_BOTTOM || dockSide == WindowManager.DOCKED_RIGHT;
-    }
-
-    @Override
-    public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
-        inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-        inoutInfo.touchableRegion.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
-                mHandle.getBottom());
-        inoutInfo.touchableRegion.op(mBackground.getLeft(), mBackground.getTop(),
-                mBackground.getRight(), mBackground.getBottom(), Op.UNION);
-    }
-
-    void onUndockingTask() {
-        int dockSide = mSplitLayout.getPrimarySplitSide();
-        if (inSplitMode()) {
-            startDragging(false /* animate */, false /* touching */);
-            SnapTarget target = dockSideTopLeft(dockSide)
-                    ? mSplitLayout.getSnapAlgorithm().getDismissEndTarget()
-                    : mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
-
-            // Don't start immediately - give a little bit time to settle the drag resize change.
-            mExitAnimationRunning = true;
-            mExitStartPosition = getCurrentPosition();
-            stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */,
-                    0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
-        }
-    }
-
-    private int calculatePositionForInsetBounds() {
-        mSplitLayout.mDisplayLayout.getStableBounds(mTmpRect);
-        return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
deleted file mode 100644
index 5078371..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
-import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
-import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER;
-
-import android.graphics.PixelFormat;
-import android.graphics.Region;
-import android.os.Binder;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.wm.shell.common.SystemWindows;
-
-/**
- * Manages the window parameters of the docked stack divider.
- */
-final class DividerWindowManager {
-
-    private static final String WINDOW_TITLE = "DockedStackDivider";
-
-    final SystemWindows mSystemWindows;
-    private WindowManager.LayoutParams mLp;
-    private View mView;
-
-    DividerWindowManager(SystemWindows systemWindows) {
-        mSystemWindows = systemWindows;
-    }
-
-    /** Add a divider view */
-    void add(View view, int width, int height, int displayId) {
-        mLp = new WindowManager.LayoutParams(
-                width, height, TYPE_DOCK_DIVIDER,
-                FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
-                        | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY,
-                PixelFormat.TRANSLUCENT);
-        mLp.token = new Binder();
-        mLp.setTitle(WINDOW_TITLE);
-        mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
-        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
-                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-        mSystemWindows.addView(view, mLp, displayId, SHELL_ROOT_LAYER_DIVIDER);
-        mView = view;
-    }
-
-    void remove() {
-        if (mView != null) {
-            mSystemWindows.removeView(mView);
-        }
-        mView = null;
-    }
-
-    void setSlippery(boolean slippery) {
-        boolean changed = false;
-        if (slippery && (mLp.flags & FLAG_SLIPPERY) == 0) {
-            mLp.flags |= FLAG_SLIPPERY;
-            changed = true;
-        } else if (!slippery && (mLp.flags & FLAG_SLIPPERY) != 0) {
-            mLp.flags &= ~FLAG_SLIPPERY;
-            changed = true;
-        }
-        if (changed) {
-            mSystemWindows.updateViewLayout(mView, mLp);
-        }
-    }
-
-    void setTouchable(boolean touchable) {
-        if (mView == null) {
-            return;
-        }
-        boolean changed = false;
-        if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) {
-            mLp.flags |= FLAG_NOT_TOUCHABLE;
-            changed = true;
-        } else if (touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) != 0) {
-            mLp.flags &= ~FLAG_NOT_TOUCHABLE;
-            changed = true;
-        }
-        if (changed) {
-            mSystemWindows.updateViewLayout(mView, mLp);
-        }
-    }
-
-    /** Sets the touch region to `touchRegion`. Use null to unset.*/
-    void setTouchRegion(Region touchRegion) {
-        if (mView == null) {
-            return;
-        }
-        mSystemWindows.setTouchableRegion(mView, touchRegion);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
deleted file mode 100644
index 7a16335..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
-import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
-
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.widget.TextView;
-
-import com.android.wm.shell.R;
-
-/**
- * Translucent activity that gets started on top of a task in multi-window to inform the user that
- * we forced the activity below to be resizable.
- */
-public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {
-
-    public static final String EXTRA_FORCED_RESIZEABLE_REASON = "extra_forced_resizeable_reason";
-
-    private static final long DISMISS_DELAY = 2500;
-
-    private final Runnable mFinishRunnable = new Runnable() {
-        @Override
-        public void run() {
-            finish();
-        }
-    };
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.forced_resizable_activity);
-        TextView tv = findViewById(com.android.internal.R.id.message);
-        int reason = getIntent().getIntExtra(EXTRA_FORCED_RESIZEABLE_REASON, -1);
-        String text;
-        switch (reason) {
-            case FORCED_RESIZEABLE_REASON_SPLIT_SCREEN:
-                text = getString(R.string.dock_forced_resizable);
-                break;
-            case FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY:
-                text = getString(R.string.forced_resizable_secondary_display);
-                break;
-            default:
-                throw new IllegalArgumentException("Unexpected forced resizeable reason: "
-                        + reason);
-        }
-        tv.setText(text);
-        getWindow().setTitle(text);
-        getWindow().getDecorView().setOnTouchListener(this);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        getWindow().getDecorView().postDelayed(mFinishRunnable, DISMISS_DELAY);
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        finish();
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-        finish();
-        return true;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        finish();
-        return true;
-    }
-
-    @Override
-    public void finish() {
-        super.finish();
-        overridePendingTransition(0, R.anim.forced_resizable_exit);
-    }
-
-    @Override
-    public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
-        // Do nothing
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
deleted file mode 100644
index 1ef142d..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-
-import static com.android.wm.shell.splitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
-
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.widget.Toast;
-
-import com.android.wm.shell.R;
-
-import java.util.function.Consumer;
-
-/**
- * Controller that decides when to show the {@link ForcedResizableInfoActivity}.
- */
-final class ForcedResizableInfoActivityController implements DividerView.DividerCallbacks {
-
-    private static final String SELF_PACKAGE_NAME = "com.android.systemui";
-
-    private static final int TIMEOUT = 1000;
-    private final Context mContext;
-    private final Handler mHandler = new Handler();
-    private final ArraySet<PendingTaskRecord> mPendingTasks = new ArraySet<>();
-    private final ArraySet<String> mPackagesShownInSession = new ArraySet<>();
-    private boolean mDividerDragging;
-
-    private final Runnable mTimeoutRunnable = this::showPending;
-
-    private final Consumer<Boolean> mDockedStackExistsListener = exists -> {
-        if (!exists) {
-            mPackagesShownInSession.clear();
-        }
-    };
-
-    /** Record of force resized task that's pending to be handled. */
-    private class PendingTaskRecord {
-        int mTaskId;
-        /**
-         * {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SPLIT_SCREEN} or
-         * {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY}
-         */
-        int mReason;
-
-        PendingTaskRecord(int taskId, int reason) {
-            this.mTaskId = taskId;
-            this.mReason = reason;
-        }
-    }
-
-    ForcedResizableInfoActivityController(Context context,
-            SplitScreenController splitScreenController) {
-        mContext = context;
-        splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
-    }
-
-    @Override
-    public void onDraggingStart() {
-        mDividerDragging = true;
-        mHandler.removeCallbacks(mTimeoutRunnable);
-    }
-
-    @Override
-    public void onDraggingEnd() {
-        mDividerDragging = false;
-        showPending();
-    }
-
-    void onAppTransitionFinished() {
-        if (!mDividerDragging) {
-            showPending();
-        }
-    }
-
-    void activityForcedResizable(String packageName, int taskId, int reason) {
-        if (debounce(packageName)) {
-            return;
-        }
-        mPendingTasks.add(new PendingTaskRecord(taskId, reason));
-        postTimeout();
-    }
-
-    void activityDismissingSplitScreen() {
-        Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
-                Toast.LENGTH_SHORT).show();
-    }
-
-    void activityLaunchOnSecondaryDisplayFailed() {
-        Toast.makeText(mContext, R.string.activity_launch_on_secondary_display_failed_text,
-                Toast.LENGTH_SHORT).show();
-    }
-
-    private void showPending() {
-        mHandler.removeCallbacks(mTimeoutRunnable);
-        for (int i = mPendingTasks.size() - 1; i >= 0; i--) {
-            PendingTaskRecord pendingRecord = mPendingTasks.valueAt(i);
-            Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
-            ActivityOptions options = ActivityOptions.makeBasic();
-            options.setLaunchTaskId(pendingRecord.mTaskId);
-            // Set as task overlay and allow to resume, so that when an app enters split-screen and
-            // becomes paused, the overlay will still be shown.
-            options.setTaskOverlay(true, true /* canResume */);
-            intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.mReason);
-            mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
-        }
-        mPendingTasks.clear();
-    }
-
-    private void postTimeout() {
-        mHandler.removeCallbacks(mTimeoutRunnable);
-        mHandler.postDelayed(mTimeoutRunnable, TIMEOUT);
-    }
-
-    private boolean debounce(String packageName) {
-        if (packageName == null) {
-            return false;
-        }
-
-        // We launch ForcedResizableInfoActivity into a task that was forced resizable, so that
-        // triggers another notification. So ignore our own activity.
-        if (SELF_PACKAGE_NAME.equals(packageName)) {
-            return true;
-        }
-        boolean debounce = mPackagesShownInSession.contains(packageName);
-        mPackagesShownInSession.add(packageName);
-        return debounce;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
deleted file mode 100644
index 06f4ef1..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Shader;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.wm.shell.R;
-
-/**
- * Shadow for the minimized dock state on homescreen.
- */
-public class MinimizedDockShadow extends View {
-
-    private final Paint mShadowPaint = new Paint();
-
-    private int mDockSide = WindowManager.DOCKED_INVALID;
-
-    public MinimizedDockShadow(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    void setDockSide(int dockSide) {
-        if (dockSide != mDockSide) {
-            mDockSide = dockSide;
-            updatePaint(getLeft(), getTop(), getRight(), getBottom());
-            invalidate();
-        }
-    }
-
-    private void updatePaint(int left, int top, int right, int bottom) {
-        int startColor = mContext.getResources().getColor(
-                R.color.minimize_dock_shadow_start, null);
-        int endColor = mContext.getResources().getColor(
-                R.color.minimize_dock_shadow_end, null);
-        final int middleColor = Color.argb(
-                (Color.alpha(startColor) + Color.alpha(endColor)) / 2, 0, 0, 0);
-        final int quarter = Color.argb(
-                (int) (Color.alpha(startColor) * 0.25f + Color.alpha(endColor) * 0.75f),
-                0, 0, 0);
-        if (mDockSide == WindowManager.DOCKED_TOP) {
-            mShadowPaint.setShader(new LinearGradient(
-                    0, 0, 0, bottom - top,
-                    new int[] { startColor, middleColor, quarter, endColor },
-                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
-        } else if (mDockSide == WindowManager.DOCKED_LEFT) {
-            mShadowPaint.setShader(new LinearGradient(
-                    0, 0, right - left, 0,
-                    new int[] { startColor, middleColor, quarter, endColor },
-                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
-        } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
-            mShadowPaint.setShader(new LinearGradient(
-                    right - left, 0, 0, 0,
-                    new int[] { startColor, middleColor, quarter, endColor },
-                    new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (changed) {
-            updatePaint(left, top, right, bottom);
-            invalidate();
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        canvas.drawRect(0, 0, getWidth(), getHeight(), mShadowPaint);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
deleted file mode 100644
index 7d5e1a8..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.util.TypedValue;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.internal.policy.DockedDividerUtils;
-import com.android.wm.shell.common.DisplayLayout;
-
-/**
- * Handles split-screen related internal display layout. In general, this represents the
- * WM-facing understanding of the splits.
- */
-public class SplitDisplayLayout {
-    /** 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;
-    DisplayLayout mDisplayLayout;
-    Context mContext;
-
-    // Lazy stuff
-    boolean mResourcesValid = false;
-    int mDividerSize;
-    int mDividerSizeInactive;
-    private DividerSnapAlgorithm mSnapAlgorithm = null;
-    private DividerSnapAlgorithm mMinimizedSnapAlgorithm = null;
-    Rect mPrimary = null;
-    Rect mSecondary = null;
-    Rect mAdjustedPrimary = null;
-    Rect mAdjustedSecondary = null;
-
-    public SplitDisplayLayout(Context ctx, DisplayLayout dl, SplitScreenTaskListener taskTiles) {
-        mTiles = taskTiles;
-        mDisplayLayout = dl;
-        mContext = ctx;
-    }
-
-    void rotateTo(int newRotation) {
-        mDisplayLayout.rotateTo(mContext.getResources(), newRotation);
-        final Configuration config = new Configuration();
-        config.unset();
-        config.orientation = mDisplayLayout.getOrientation();
-        Rect tmpRect = new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
-        tmpRect.inset(mDisplayLayout.nonDecorInsets());
-        config.windowConfiguration.setAppBounds(tmpRect);
-        tmpRect.set(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
-        tmpRect.inset(mDisplayLayout.stableInsets());
-        config.screenWidthDp = (int) (tmpRect.width() / mDisplayLayout.density());
-        config.screenHeightDp = (int) (tmpRect.height() / mDisplayLayout.density());
-        mContext = mContext.createConfigurationContext(config);
-        mSnapAlgorithm = null;
-        mMinimizedSnapAlgorithm = null;
-        mResourcesValid = false;
-    }
-
-    private void updateResources() {
-        if (mResourcesValid) {
-            return;
-        }
-        mResourcesValid = true;
-        Resources res = mContext.getResources();
-        mDividerSize = DockedDividerUtils.getDividerSize(res,
-                DockedDividerUtils.getDividerInsets(res));
-        mDividerSizeInactive = (int) TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP, DIVIDER_WIDTH_INACTIVE_DP, res.getDisplayMetrics());
-    }
-
-    int getPrimarySplitSide() {
-        switch (mDisplayLayout.getNavigationBarPosition(mContext.getResources())) {
-            case DisplayLayout.NAV_BAR_BOTTOM:
-                return mDisplayLayout.isLandscape() ? DOCKED_LEFT : DOCKED_TOP;
-            case DisplayLayout.NAV_BAR_LEFT:
-                return DOCKED_RIGHT;
-            case DisplayLayout.NAV_BAR_RIGHT:
-                return DOCKED_LEFT;
-            default:
-                return DOCKED_INVALID;
-        }
-    }
-
-    DividerSnapAlgorithm getSnapAlgorithm() {
-        if (mSnapAlgorithm == null) {
-            updateResources();
-            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
-            mSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
-                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
-                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide());
-        }
-        return mSnapAlgorithm;
-    }
-
-    DividerSnapAlgorithm getMinimizedSnapAlgorithm(boolean homeStackResizable) {
-        if (mMinimizedSnapAlgorithm == null) {
-            updateResources();
-            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
-            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
-                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
-                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide(),
-                    true /* isMinimized */, homeStackResizable);
-        }
-        return mMinimizedSnapAlgorithm;
-    }
-
-    void resizeSplits(int position) {
-        mPrimary = mPrimary == null ? new Rect() : mPrimary;
-        mSecondary = mSecondary == null ? new Rect() : mSecondary;
-        calcSplitBounds(position, mPrimary, mSecondary);
-    }
-
-    void resizeSplits(int position, WindowContainerTransaction t) {
-        resizeSplits(position);
-        t.setBounds(mTiles.mPrimary.token, mPrimary);
-        t.setBounds(mTiles.mSecondary.token, mSecondary);
-
-        t.setSmallestScreenWidthDp(mTiles.mPrimary.token,
-                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mPrimary));
-        t.setSmallestScreenWidthDp(mTiles.mSecondary.token,
-                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mSecondary));
-    }
-
-    void calcSplitBounds(int position, @NonNull Rect outPrimary, @NonNull Rect outSecondary) {
-        int dockSide = getPrimarySplitSide();
-        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outPrimary,
-                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
-
-        DockedDividerUtils.calculateBoundsForPosition(position,
-                DockedDividerUtils.invertDockSide(dockSide), outSecondary, mDisplayLayout.width(),
-                mDisplayLayout.height(), mDividerSize);
-    }
-
-    Rect calcResizableMinimizedHomeStackBounds() {
-        DividerSnapAlgorithm.SnapTarget miniMid =
-                getMinimizedSnapAlgorithm(true /* resizable */).getMiddleTarget();
-        Rect homeBounds = new Rect();
-        DockedDividerUtils.calculateBoundsForPosition(miniMid.position,
-                DockedDividerUtils.invertDockSide(getPrimarySplitSide()), homeBounds,
-                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
-        return homeBounds;
-    }
-
-    /**
-     * Updates the adjustment depending on it's current state.
-     */
-    void updateAdjustedBounds(int currImeTop, int hiddenTop, int shownTop) {
-        adjustForIME(mDisplayLayout, currImeTop, hiddenTop, shownTop, mDividerSize,
-                mDividerSizeInactive, mPrimary, mSecondary);
-    }
-
-    /** Assumes top/bottom split. Splits are not adjusted for left/right splits. */
-    private void adjustForIME(DisplayLayout dl, int currImeTop, int hiddenTop, int shownTop,
-            int dividerWidth, int dividerWidthInactive, Rect primaryBounds, Rect secondaryBounds) {
-        if (mAdjustedPrimary == null) {
-            mAdjustedPrimary = new Rect();
-            mAdjustedSecondary = new Rect();
-        }
-
-        final Rect displayStableRect = new Rect();
-        dl.getStableBounds(displayStableRect);
-
-        final float shownFraction = ((float) (currImeTop - hiddenTop)) / (shownTop - hiddenTop);
-        final int currDividerWidth =
-                (int) (dividerWidthInactive * shownFraction + dividerWidth * (1.f - shownFraction));
-
-        // Calculate the highest we can move the bottom of the top stack to keep 30% visible.
-        final int minTopStackBottom = displayStableRect.top
-                + (int) ((mPrimary.bottom - displayStableRect.top) * ADJUSTED_STACK_FRACTION_MIN);
-        // Based on that, calculate the maximum amount we'll allow the ime to shift things.
-        final int maxOffset = mPrimary.bottom - minTopStackBottom;
-        // Calculate how much we would shift things without limits (basically the height of ime).
-        final int desiredOffset = hiddenTop - shownTop;
-        // Calculate an "adjustedTop" which is the currImeTop but restricted by our constraints.
-        // We want an effect where the adjustment only occurs during the "highest" portion of the
-        // ime animation. This is done by shifting the adjustment values by the difference in
-        // offsets (effectively playing the whole adjustment animation some fixed amount of pixels
-        // below the ime top).
-        final int topCorrection = Math.max(0, desiredOffset - maxOffset);
-        final int adjustedTop = currImeTop + topCorrection;
-        // The actual yOffset is the distance between adjustedTop and the bottom of the display.
-        // Since our adjustedTop values are playing "below" the ime, we clamp at 0 so we only
-        // see adjustment upward.
-        final int yOffset = Math.max(0, dl.height() - adjustedTop);
-
-        // TOP
-        // Reduce the offset by an additional small amount to squish the divider bar.
-        mAdjustedPrimary.set(primaryBounds);
-        mAdjustedPrimary.offset(0, -yOffset + (dividerWidth - currDividerWidth));
-
-        // BOTTOM
-        mAdjustedSecondary.set(secondaryBounds);
-        mAdjustedSecondary.offset(0, -yOffset);
-    }
-
-    static int getSmallestWidthDpForBounds(@NonNull Context context, DisplayLayout dl,
-            Rect bounds) {
-        int dividerSize = DockedDividerUtils.getDividerSize(context.getResources(),
-                DockedDividerUtils.getDividerInsets(context.getResources()));
-
-        int minWidth = Integer.MAX_VALUE;
-
-        // Go through all screen orientations and find the orientation in which the task has the
-        // smallest width.
-        Rect tmpRect = new Rect();
-        Rect rotatedDisplayRect = new Rect();
-        Rect displayRect = new Rect(0, 0, dl.width(), dl.height());
-
-        DisplayLayout tmpDL = new DisplayLayout();
-        for (int rotation = 0; rotation < 4; rotation++) {
-            tmpDL.set(dl);
-            tmpDL.rotateTo(context.getResources(), rotation);
-            DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);
-
-            tmpRect.set(bounds);
-            DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
-            rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
-            final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
-                    tmpDL.getOrientation());
-            final int position = DockedDividerUtils.calculatePositionForBounds(tmpRect, dockSide,
-                    dividerSize);
-
-            final int snappedPosition =
-                    snap.calculateNonDismissingSnapTarget(position).position;
-            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, tmpRect,
-                    tmpDL.width(), tmpDL.height(), dividerSize);
-            Rect insettedDisplay = new Rect(rotatedDisplayRect);
-            insettedDisplay.inset(tmpDL.stableInsets());
-            tmpRect.intersect(insettedDisplay);
-            minWidth = Math.min(tmpRect.width(), minWidth);
-        }
-        return (int) (minWidth / dl.density());
-    }
-
-    static DividerSnapAlgorithm initSnapAlgorithmForRotation(Context context, DisplayLayout dl,
-            int dividerSize) {
-        final Configuration config = new Configuration();
-        config.unset();
-        config.orientation = dl.getOrientation();
-        Rect tmpRect = new Rect(0, 0, dl.width(), dl.height());
-        tmpRect.inset(dl.nonDecorInsets());
-        config.windowConfiguration.setAppBounds(tmpRect);
-        tmpRect.set(0, 0, dl.width(), dl.height());
-        tmpRect.inset(dl.stableInsets());
-        config.screenWidthDp = (int) (tmpRect.width() / dl.density());
-        config.screenHeightDp = (int) (tmpRect.height() / dl.density());
-        final Context rotationContext = context.createConfigurationContext(config);
-        return new DividerSnapAlgorithm(
-                rotationContext.getResources(), dl.width(), dl.height(), dividerSize,
-                config.orientation == ORIENTATION_PORTRAIT, dl.stableInsets());
-    }
-
-    /**
-     * Get the current primary-split side. Determined by its location of {@param bounds} within
-     * {@param displayRect} but if both are the same, it will try to dock to each side and determine
-     * if allowed in its respected {@param orientation}.
-     *
-     * @param bounds bounds of the primary split task to get which side is docked
-     * @param displayRect bounds of the display that contains the primary split task
-     * @param orientation the origination of device
-     * @return current primary-split side
-     */
-    static int getPrimarySplitSide(Rect bounds, Rect displayRect, int orientation) {
-        if (orientation == ORIENTATION_PORTRAIT) {
-            // Portrait mode, docked either at the top or the bottom.
-            final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
-            if (diff < 0) {
-                return DOCKED_BOTTOM;
-            } else {
-                // Top is default
-                return DOCKED_TOP;
-            }
-        } else if (orientation == ORIENTATION_LANDSCAPE) {
-            // Landscape mode, docked either on the left or on the right.
-            final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
-            if (diff < 0) {
-                return DOCKED_RIGHT;
-            }
-            return DOCKED_LEFT;
-        }
-        return DOCKED_INVALID;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
deleted file mode 100644
index 7c70a4efa..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import android.graphics.Rect;
-import android.window.WindowContainerToken;
-
-import com.android.wm.shell.common.annotations.ExternalThread;
-
-import java.io.PrintWriter;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-
-/**
- * Interface to engage split screen feature.
- */
-@ExternalThread
-public interface SplitScreen {
-    /** Called when keyguard showing state changed. */
-    void onKeyguardVisibilityChanged(boolean isShowing);
-
-    /** Returns {@link DividerView}. */
-    DividerView getDividerView();
-
-    /** Returns {@code true} if one of the split screen is in minimized mode. */
-    boolean isMinimized();
-
-    /** Returns {@code true} if the home stack is resizable. */
-    boolean isHomeStackResizable();
-
-    /** Returns {@code true} if the divider is visible. */
-    boolean isDividerVisible();
-
-    /** Switch to minimized state if appropriate. */
-    void setMinimized(boolean minimized);
-
-    /** Called when there's a task undocking. */
-    void onUndockingTask();
-
-    /** Called when app transition finished. */
-    void onAppTransitionFinished();
-
-    /** Dumps current status of Split Screen. */
-    void dump(PrintWriter pw);
-
-    /** Registers listener that gets called whenever the existence of the divider changes. */
-    void registerInSplitScreenListener(Consumer<Boolean> listener);
-
-    /** Unregisters listener that gets called whenever the existence of the divider changes. */
-    void unregisterInSplitScreenListener(Consumer<Boolean> listener);
-
-    /** Registers listener that gets called whenever the split screen bounds changes. */
-    void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener);
-
-    /** @return the container token for the secondary split root task. */
-    WindowContainerToken getSecondaryRoot();
-
-    /**
-     * Splits the primary task if feasible, this is to preserve legacy way to toggle split screen.
-     * Like triggering split screen through long pressing recents app button or through
-     * {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN}.
-     *
-     * @return {@code true} if it successes to split the primary task.
-     */
-    boolean splitPrimaryTask();
-
-    /**
-     * Exits the split to make the primary task fullscreen.
-     */
-    void dismissSplitToPrimaryTask();
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
deleted file mode 100644
index 6d6c761..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Slog;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Toast;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.wm.shell.R;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayChangeController;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.SystemWindows;
-import com.android.wm.shell.common.TaskStackListenerCallback;
-import com.android.wm.shell.common.TaskStackListenerImpl;
-import com.android.wm.shell.common.TransactionPool;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-
-/**
- * Controls split screen feature.
- */
-public class SplitScreenController implements SplitScreen,
-        DisplayController.OnDisplaysChangedListener {
-    static final boolean DEBUG = false;
-
-    private static final String TAG = "SplitScreenCtrl";
-    private static final int DEFAULT_APP_TRANSITION_DURATION = 336;
-
-    private final Context mContext;
-    private final DisplayChangeController.OnDisplayChangingListener mRotationController;
-    private final DisplayController mDisplayController;
-    private final DisplayImeController mImeController;
-    private final DividerImeController mImePositionProcessor;
-    private final DividerState mDividerState = new DividerState();
-    private final ForcedResizableInfoActivityController mForcedResizableController;
-    private final Handler mHandler;
-    private final SplitScreenTaskListener mSplits;
-    private final SystemWindows mSystemWindows;
-    final TransactionPool mTransactionPool;
-    private final WindowManagerProxy mWindowManagerProxy;
-    private final TaskOrganizer mTaskOrganizer;
-
-    private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
-            = new CopyOnWriteArrayList<>();
-    private final ArrayList<WeakReference<BiConsumer<Rect, Rect>>> mBoundsChangedListeners =
-            new ArrayList<>();
-
-
-    private DividerWindowManager mWindowManager;
-    private DividerView mView;
-
-    // Keeps track of real-time split geometry including snap positions and ime adjustments
-    private SplitDisplayLayout 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 boolean mIsKeyguardShowing;
-    private boolean mVisible = false;
-    private boolean mMinimized = false;
-    private boolean mAdjustedForIme = false;
-    private boolean mHomeStackResizable = false;
-
-    public SplitScreenController(Context context,
-            DisplayController displayController, SystemWindows systemWindows,
-            DisplayImeController imeController, Handler handler, TransactionPool transactionPool,
-            ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
-            TaskStackListenerImpl taskStackListener) {
-        mContext = context;
-        mDisplayController = displayController;
-        mSystemWindows = systemWindows;
-        mImeController = imeController;
-        mHandler = handler;
-        mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
-        mTransactionPool = transactionPool;
-        mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
-        mTaskOrganizer = shellTaskOrganizer;
-        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
-        mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
-                shellTaskOrganizer);
-        mRotationController =
-                (display, fromRotation, toRotation, wct) -> {
-                    if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) {
-                        return;
-                    }
-                    WindowContainerTransaction t = new WindowContainerTransaction();
-                    DisplayLayout displayLayout =
-                            new DisplayLayout(mDisplayController.getDisplayLayout(display));
-                    SplitDisplayLayout sdl =
-                            new SplitDisplayLayout(mContext, displayLayout, mSplits);
-                    sdl.rotateTo(toRotation);
-                    mRotateSplitLayout = sdl;
-                    final int position = isDividerVisible()
-                            ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
-                            : mView.getCurrentPosition())
-                            // snap resets to middle target when not in split-mode
-                            : sdl.getSnapAlgorithm().getMiddleTarget().position;
-                    DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
-                    final DividerSnapAlgorithm.SnapTarget target =
-                            snap.calculateNonDismissingSnapTarget(position);
-                    sdl.resizeSplits(target.position, t);
-
-                    if (isSplitActive() && mHomeStackResizable) {
-                        mWindowManagerProxy
-                                .applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
-                    }
-                    if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) {
-                        // Because sync transactions are serialized, its possible for an "older"
-                        // bounds-change to get applied after a screen rotation. In that case, we
-                        // want to actually defer on that rather than apply immediately. Of course,
-                        // this means that the bounds may not change until after the rotation so
-                        // the user might see some artifacts. This should be rare.
-                        Slog.w(TAG, "Screen rotated while other operations were pending, this may"
-                                + " result in some graphical artifacts.");
-                    } else {
-                        wct.merge(t, true /* transfer */);
-                    }
-                };
-
-        mWindowManager = new DividerWindowManager(mSystemWindows);
-        mDisplayController.addDisplayWindowListener(this);
-        // Don't initialize the divider or anything until we get the default display.
-
-        taskStackListener.addListener(
-                new TaskStackListenerCallback() {
-                    @Override
-                    public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
-                            boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
-                        if (!wasVisible || task.getWindowingMode()
-                                != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
-                                || !mSplits.isSplitScreenSupported()) {
-                            return;
-                        }
-
-                        if (isMinimized()) {
-                            onUndockingTask();
-                        }
-                    }
-
-                    @Override
-                    public void onActivityForcedResizable(String packageName, int taskId,
-                            int reason) {
-                        mForcedResizableController.activityForcedResizable(packageName, taskId,
-                                reason);
-                    }
-
-                    @Override
-                    public void onActivityDismissingDockedStack() {
-                        mForcedResizableController.activityDismissingSplitScreen();
-                    }
-
-                    @Override
-                    public void onActivityLaunchOnSecondaryDisplayFailed() {
-                        mForcedResizableController.activityLaunchOnSecondaryDisplayFailed();
-                    }
-                });
-    }
-
-    void onSplitScreenSupported() {
-        // Set starting tile bounds based on middle target
-        final WindowContainerTransaction tct = new WindowContainerTransaction();
-        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
-        mSplitLayout.resizeSplits(midPos, tct);
-        mTaskOrganizer.applyTransaction(tct);
-    }
-
-    @Override
-    public void onKeyguardVisibilityChanged(boolean showing) {
-        if (!isSplitActive() || mView == null) {
-            return;
-        }
-        mView.setHidden(showing);
-        if (!showing) {
-            mImePositionProcessor.updateAdjustForIme();
-        }
-        mIsKeyguardShowing = showing;
-    }
-
-    @Override
-    public void onDisplayAdded(int displayId) {
-        if (displayId != DEFAULT_DISPLAY) {
-            return;
-        }
-        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
-                mDisplayController.getDisplayLayout(displayId), mSplits);
-        mImeController.addPositionProcessor(mImePositionProcessor);
-        mDisplayController.addDisplayChangingController(mRotationController);
-        if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
-            removeDivider();
-            return;
-        }
-        try {
-            mSplits.init();
-        } catch (Exception e) {
-            Slog.e(TAG, "Failed to register docked stack listener", e);
-            removeDivider();
-            return;
-        }
-    }
-
-    @Override
-    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
-        if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
-            return;
-        }
-        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
-                mDisplayController.getDisplayLayout(displayId), mSplits);
-        if (mRotateSplitLayout == null) {
-            int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
-            final WindowContainerTransaction tct = new WindowContainerTransaction();
-            mSplitLayout.resizeSplits(midPos, tct);
-            mTaskOrganizer.applyTransaction(tct);
-        } else if (mSplitLayout.mDisplayLayout.rotation()
-                == mRotateSplitLayout.mDisplayLayout.rotation()) {
-            mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
-            mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
-            mRotateSplitLayout = null;
-        }
-        if (isSplitActive()) {
-            update(newConfig);
-        }
-    }
-
-    /** Posts task to handler dealing with divider. */
-    void post(Runnable task) {
-        mHandler.post(task);
-    }
-
-    @Override
-    public DividerView getDividerView() {
-        return mView;
-    }
-
-    @Override
-    public boolean isMinimized() {
-        return mMinimized;
-    }
-
-    @Override
-    public boolean isHomeStackResizable() {
-        return mHomeStackResizable;
-    }
-
-    @Override
-    public boolean isDividerVisible() {
-        return mView != null && mView.getVisibility() == View.VISIBLE;
-    }
-
-    /**
-     * This indicates that at-least one of the splits has content. This differs from
-     * isDividerVisible because the divider is only visible once *everything* is in split mode
-     * while this only cares if some things are (eg. while entering/exiting as well).
-     */
-    private boolean isSplitActive() {
-        return mSplits.mPrimary != null && mSplits.mSecondary != null
-                && (mSplits.mPrimary.topActivityType != ACTIVITY_TYPE_UNDEFINED
-                || mSplits.mSecondary.topActivityType != ACTIVITY_TYPE_UNDEFINED);
-    }
-
-    private void addDivider(Configuration configuration) {
-        Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
-        mView = (DividerView)
-                LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
-        DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
-        mView.injectDependencies(this, mWindowManager, mDividerState, mForcedResizableController,
-                mSplits, mSplitLayout, mImePositionProcessor, mWindowManagerProxy);
-        mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
-        mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, null /* transaction */);
-        final int size = dctx.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_thickness);
-        final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
-        final int width = landscape ? size : displayLayout.width();
-        final int height = landscape ? displayLayout.height() : size;
-        mWindowManager.add(mView, width, height, mContext.getDisplayId());
-    }
-
-    private void removeDivider() {
-        if (mView != null) {
-            mView.onDividerRemoved();
-        }
-        mWindowManager.remove();
-    }
-
-    private void update(Configuration configuration) {
-        final boolean isDividerHidden = mView != null && mIsKeyguardShowing;
-
-        removeDivider();
-        addDivider(configuration);
-
-        if (mMinimized) {
-            mView.setMinimizedDockStack(true, mHomeStackResizable, null /* transaction */);
-            updateTouchable();
-        }
-        mView.setHidden(isDividerHidden);
-    }
-
-    void onTaskVanished() {
-        mHandler.post(this::removeDivider);
-    }
-
-    private void updateVisibility(final boolean visible) {
-        if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
-        if (mVisible != visible) {
-            mVisible = visible;
-            mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-
-            if (visible) {
-                mView.enterSplitMode(mHomeStackResizable);
-                // Update state because animations won't finish.
-                mWindowManagerProxy.runInSync(
-                        t -> mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, t));
-
-            } else {
-                mView.exitSplitMode();
-                mWindowManagerProxy.runInSync(
-                        t -> mView.setMinimizedDockStack(false, mHomeStackResizable, t));
-            }
-            // Notify existence listeners
-            synchronized (mDockedStackExistsListeners) {
-                mDockedStackExistsListeners.removeIf(wf -> {
-                    Consumer<Boolean> l = wf.get();
-                    if (l != null) l.accept(visible);
-                    return l == null;
-                });
-            }
-        }
-    }
-
-    @Override
-    public void setMinimized(final boolean minimized) {
-        if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
-        mHandler.post(() -> {
-            if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
-            if (!mVisible) {
-                return;
-            }
-            setHomeMinimized(minimized);
-        });
-    }
-
-    private void setHomeMinimized(final boolean minimized) {
-        if (DEBUG) {
-            Slog.d(TAG, "setHomeMinimized  min:" + mMinimized + "->" + minimized + " hrsz:"
-                    + mHomeStackResizable + " split:" + isDividerVisible());
-        }
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        final boolean minimizedChanged = mMinimized != minimized;
-        // Update minimized state
-        if (minimizedChanged) {
-            mMinimized = minimized;
-        }
-        // Always set this because we could be entering split when mMinimized is already true
-        wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
-
-        // Sync state to DividerView if it exists.
-        if (mView != null) {
-            final int displayId = mView.getDisplay() != null
-                    ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY;
-            // pause ime here (before updateMinimizedDockedStack)
-            if (mMinimized) {
-                mImePositionProcessor.pause(displayId);
-            }
-            if (minimizedChanged) {
-                // This conflicts with IME adjustment, so only call it when things change.
-                mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable);
-            }
-            if (!mMinimized) {
-                // afterwards so it can end any animations started in view
-                mImePositionProcessor.resume(displayId);
-            }
-        }
-        updateTouchable();
-
-        // If we are only setting focusability, a sync transaction isn't necessary (in fact it
-        // can interrupt other animations), so see if it can be submitted on pending instead.
-        if (!mWindowManagerProxy.queueSyncTransactionIfWaiting(wct)) {
-            mTaskOrganizer.applyTransaction(wct);
-        }
-    }
-
-    void setAdjustedForIme(boolean adjustedForIme) {
-        if (mAdjustedForIme == adjustedForIme) {
-            return;
-        }
-        mAdjustedForIme = adjustedForIme;
-        updateTouchable();
-    }
-
-    private void updateTouchable() {
-        mWindowManager.setTouchable(!mAdjustedForIme);
-    }
-
-    @Override
-    public void onUndockingTask() {
-        if (mView != null) {
-            mView.onUndockingTask();
-        }
-    }
-
-    @Override
-    public void onAppTransitionFinished() {
-        if (mView == null) {
-            return;
-        }
-        mForcedResizableController.onAppTransitionFinished();
-    }
-
-    @Override
-    public void dump(PrintWriter pw) {
-        pw.print("  mVisible="); pw.println(mVisible);
-        pw.print("  mMinimized="); pw.println(mMinimized);
-        pw.print("  mAdjustedForIme="); pw.println(mAdjustedForIme);
-    }
-
-    long getAnimDuration() {
-        float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
-                Settings.Global.TRANSITION_ANIMATION_SCALE,
-                mContext.getResources().getFloat(
-                        com.android.internal.R.dimen
-                                .config_appTransitionAnimationDurationScaleDefault));
-        final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
-        return (long) (transitionDuration * transitionScale);
-    }
-
-    @Override
-    public void registerInSplitScreenListener(Consumer<Boolean> listener) {
-        listener.accept(isDividerVisible());
-        synchronized (mDockedStackExistsListeners) {
-            mDockedStackExistsListeners.add(new WeakReference<>(listener));
-        }
-    }
-
-    @Override
-    public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
-        synchronized (mDockedStackExistsListeners) {
-            for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
-                if (mDockedStackExistsListeners.get(i) == listener) {
-                    mDockedStackExistsListeners.remove(i);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
-        synchronized (mBoundsChangedListeners) {
-            mBoundsChangedListeners.add(new WeakReference<>(listener));
-        }
-    }
-
-    @Override
-    public boolean splitPrimaryTask() {
-        try {
-            if (ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED
-                    || isSplitActive()) {
-                return false;
-            }
-
-            // Try fetching the top running task.
-            final List<RunningTaskInfo> runningTasks =
-                    ActivityTaskManager.getInstance().getTasks(1 /* maxNum */);
-            if (runningTasks == null || runningTasks.isEmpty()) {
-                return false;
-            }
-            // Note: The set of running tasks from the system is ordered by recency.
-            final RunningTaskInfo topRunningTask = runningTasks.get(0);
-            final int activityType = topRunningTask.getActivityType();
-            if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
-                return false;
-            }
-
-            if (!topRunningTask.supportsSplitScreenMultiWindow) {
-                Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
-                        Toast.LENGTH_SHORT).show();
-                return false;
-            }
-
-            return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(
-                    topRunningTask.taskId, true /* onTop */);
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    @Override
-    public void dismissSplitToPrimaryTask() {
-        startDismissSplit(true /* toPrimaryTask */);
-    }
-
-    /** Notifies the bounds of split screen changed. */
-    void notifyBoundsChanged(Rect secondaryWindowBounds, Rect secondaryWindowInsets) {
-        synchronized (mBoundsChangedListeners) {
-            mBoundsChangedListeners.removeIf(wf -> {
-                BiConsumer<Rect, Rect> l = wf.get();
-                if (l != null) l.accept(secondaryWindowBounds, secondaryWindowInsets);
-                return l == null;
-            });
-        }
-    }
-
-    void startEnterSplit() {
-        update(mDisplayController.getDisplayContext(
-                mContext.getDisplayId()).getResources().getConfiguration());
-        // Set resizable directly here because applyEnterSplit already resizes home stack.
-        mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
-    }
-
-    void startDismissSplit(boolean toPrimaryTask) {
-        mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, !toPrimaryTask);
-        updateVisibility(false /* visible */);
-        mMinimized = false;
-        // Resets divider bar position to undefined, so new divider bar will apply default position
-        // next time entering split mode.
-        mDividerState.mRatioPositionBeforeMinimized = 0;
-        removeDivider();
-        mImePositionProcessor.reset();
-    }
-
-    void ensureMinimizedSplit() {
-        setHomeMinimized(true /* minimized */);
-        if (mView != null && !isDividerVisible()) {
-            // Wasn't in split-mode yet, so enter now.
-            if (DEBUG) {
-                Slog.d(TAG, " entering split mode with minimized=true");
-            }
-            updateVisibility(true /* visible */);
-        }
-    }
-
-    void ensureNormalSplit() {
-        setHomeMinimized(false /* minimized */);
-        if (mView != null && !isDividerVisible()) {
-            // Wasn't in split-mode, so enter now.
-            if (DEBUG) {
-                Slog.d(TAG, " enter split mode unminimized ");
-            }
-            updateVisibility(true /* visible */);
-        }
-    }
-
-    SplitDisplayLayout getSplitLayout() {
-        return mSplitLayout;
-    }
-
-    WindowManagerProxy getWmProxy() {
-        return mWindowManagerProxy;
-    }
-
-    @Override
-    public WindowContainerToken getSecondaryRoot() {
-        if (mSplits == null || mSplits.mSecondary == null) {
-            return null;
-        }
-        return mSplits.mSecondary.token;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
deleted file mode 100644
index 5b2b38b..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.Transitions;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-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;
-
-    private final ShellTaskOrganizer mTaskOrganizer;
-    private final SyncTransactionQueue mSyncQueue;
-    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
-
-    RunningTaskInfo mPrimary;
-    RunningTaskInfo mSecondary;
-    SurfaceControl mPrimarySurface;
-    SurfaceControl mSecondarySurface;
-    SurfaceControl mPrimaryDim;
-    SurfaceControl mSecondaryDim;
-    Rect mHomeBounds = new Rect();
-    final SplitScreenController mSplitScreenController;
-    private boolean mSplitScreenSupported = false;
-
-    final SurfaceSession mSurfaceSession = new SurfaceSession();
-
-    SplitScreenTaskListener(SplitScreenController splitScreenController,
-                    ShellTaskOrganizer shellTaskOrganizer,
-                    SyncTransactionQueue syncQueue) {
-        mSplitScreenController = splitScreenController;
-        mTaskOrganizer = shellTaskOrganizer;
-        mSyncQueue = syncQueue;
-    }
-
-    void init() {
-        synchronized (this) {
-            try {
-                mTaskOrganizer.createRootTask(
-                        DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, this);
-                mTaskOrganizer.createRootTask(
-                        DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, this);
-            } catch (Exception e) {
-                // teardown to prevent callbacks
-                mTaskOrganizer.removeListener(this);
-                throw e;
-            }
-        }
-    }
-
-    boolean isSplitScreenSupported() {
-        return mSplitScreenSupported;
-    }
-
-    SurfaceControl.Transaction getTransaction() {
-        return mSplitScreenController.mTransactionPool.acquire();
-    }
-
-    void releaseTransaction(SurfaceControl.Transaction t) {
-        mSplitScreenController.mTransactionPool.release(t);
-    }
-
-    @Override
-    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
-        synchronized (this) {
-            if (taskInfo.hasParentTask()) {
-                handleChildTaskAppeared(taskInfo, leash);
-                return;
-            }
-
-            final int winMode = taskInfo.getWindowingMode();
-            if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                ProtoLog.v(WM_SHELL_TASK_ORG,
-                        "%s onTaskAppeared Primary taskId=%d", TAG, taskInfo.taskId);
-                mPrimary = taskInfo;
-                mPrimarySurface = leash;
-            } else if (winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-                ProtoLog.v(WM_SHELL_TASK_ORG,
-                        "%s onTaskAppeared Secondary taskId=%d", TAG, taskInfo.taskId);
-                mSecondary = taskInfo;
-                mSecondarySurface = leash;
-            } else {
-                ProtoLog.v(WM_SHELL_TASK_ORG, "%s onTaskAppeared unknown taskId=%d winMode=%d",
-                        TAG, taskInfo.taskId, winMode);
-            }
-
-            if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) {
-                mSplitScreenSupported = true;
-                mSplitScreenController.onSplitScreenSupported();
-                ProtoLog.v(WM_SHELL_TASK_ORG, "%s onTaskAppeared Supported", TAG);
-
-                // Initialize dim surfaces:
-                mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
-                        .setParent(mPrimarySurface).setColorLayer()
-                        .setName("Primary Divider Dim")
-                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
-                        .build();
-                mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
-                        .setParent(mSecondarySurface).setColorLayer()
-                        .setName("Secondary Divider Dim")
-                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
-                        .build();
-                SurfaceControl.Transaction t = getTransaction();
-                t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
-                t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
-                t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
-                t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
-                t.apply();
-                releaseTransaction(t);
-            }
-        }
-    }
-
-    @Override
-    public void onTaskVanished(RunningTaskInfo taskInfo) {
-        synchronized (this) {
-            if (taskInfo.hasParentTask()) {
-                mLeashByTaskId.remove(taskInfo.taskId);
-                return;
-            }
-
-            final boolean isPrimaryTask = mPrimary != null
-                    && taskInfo.token.equals(mPrimary.token);
-            final boolean isSecondaryTask = mSecondary != null
-                    && taskInfo.token.equals(mSecondary.token);
-
-            if (mSplitScreenSupported && (isPrimaryTask || isSecondaryTask)) {
-                mSplitScreenSupported = false;
-
-                SurfaceControl.Transaction t = getTransaction();
-                t.remove(mPrimaryDim);
-                t.remove(mSecondaryDim);
-                t.remove(mPrimarySurface);
-                t.remove(mSecondarySurface);
-                t.apply();
-                releaseTransaction(t);
-
-                mSplitScreenController.onTaskVanished();
-            }
-        }
-    }
-
-    @Override
-    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
-        if (taskInfo.displayId != DEFAULT_DISPLAY) {
-            return;
-        }
-        synchronized (this) {
-            if (taskInfo.hasParentTask()) {
-                handleChildTaskChanged(taskInfo);
-                return;
-            }
-
-            mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
-        }
-    }
-
-    private void handleChildTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
-        mLeashByTaskId.put(taskInfo.taskId, leash);
-        updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
-    }
-
-    private void handleChildTaskChanged(RunningTaskInfo taskInfo) {
-        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
-        updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
-    }
-
-    private void updateChildTaskSurface(
-            RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) {
-        final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
-        final Point taskPositionInParent = taskInfo.positionInParent;
-        final Rect corp =  new Rect(taskBounds);
-        corp.offset(-taskBounds.left, -taskBounds.top);
-        mSyncQueue.runInSync(t -> {
-            t.setWindowCrop(leash, corp);
-            t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
-            if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
-                t.setAlpha(leash, 1f);
-                t.setMatrix(leash, 1, 0, 0, 1);
-                t.show(leash);
-            }
-        });
-    }
-
-    /**
-     * This is effectively a finite state machine which moves between the various split-screen
-     * presentations based on the contents of the split regions.
-     */
-    private void handleTaskInfoChanged(RunningTaskInfo info) {
-        if (!mSplitScreenSupported) {
-            // This shouldn't happen; but apparently there is a chance that SysUI crashes without
-            // system server receiving binder-death (or maybe it receives binder-death too late?).
-            // In this situation, when sys-ui restarts, the split root-tasks will still exist so
-            // there is a small window of time during init() where WM might send messages here
-            // before init() fails. So, avoid a cycle of crashes by returning early.
-            Log.e(TAG, "Got handleTaskInfoChanged when not initialized: " + info);
-            return;
-        }
-        final boolean secondaryImpliedMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
-                || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
-                        && mSplitScreenController.isHomeStackResizable());
-        final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
-        final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
-        if (info.token.asBinder() == mPrimary.token.asBinder()) {
-            mPrimary = info;
-        } else if (info.token.asBinder() == mSecondary.token.asBinder()) {
-            mSecondary = info;
-        }
-        final boolean primaryIsEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
-        final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
-        final boolean secondaryImpliesMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
-                || (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
-                        && mSplitScreenController.isHomeStackResizable());
-        if (DEBUG) {
-            Log.d(TAG, "onTaskInfoChanged " + mPrimary + "  " + mSecondary);
-        }
-        if (primaryIsEmpty == primaryWasEmpty && secondaryWasEmpty == secondaryIsEmpty
-                && secondaryImpliedMinimize == secondaryImpliesMinimize) {
-            // No relevant changes
-            return;
-        }
-        if (primaryIsEmpty || secondaryIsEmpty) {
-            // At-least one of the splits is empty which means we are currently transitioning
-            // into or out-of split-screen mode.
-            if (DEBUG) {
-                Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
-                        + "  " + mSecondary.topActivityType);
-            }
-            if (mSplitScreenController.isDividerVisible()) {
-                // Was in split-mode, which means we are leaving split, so continue that.
-                // This happens when the stack in the primary-split is dismissed.
-                if (DEBUG) {
-                    Log.d(TAG, "    was in split, so this means leave it "
-                            + mPrimary.topActivityType + "  " + mSecondary.topActivityType);
-                }
-                mSplitScreenController.startDismissSplit(false /* toPrimaryTask */);
-            } else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) {
-                // Wasn't in split-mode (both were empty), but now that the primary split is
-                // populated, we should fully enter split by moving everything else into secondary.
-                // This just tells window-manager to reparent things, the UI will respond
-                // when it gets new task info for the secondary split.
-                if (DEBUG) {
-                    Log.d(TAG, "   was not in split, but primary is populated, so enter it");
-                }
-                mSplitScreenController.startEnterSplit();
-            }
-        } else if (secondaryImpliesMinimize) {
-            // Workaround for b/172686383, we can't rely on the sync bounds change transaction for
-            // the home task to finish before the last updateChildTaskSurface() call even if it's
-            // queued on the sync transaction queue, so ensure that the home task surface is updated
-            // again before we minimize
-            final ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
-            mSplitScreenController.getWmProxy().getHomeAndRecentsTasks(tasks,
-                    mSplitScreenController.getSecondaryRoot());
-            for (int i = 0; i < tasks.size(); i++) {
-                final RunningTaskInfo taskInfo = tasks.get(i);
-                final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
-                if (leash != null) {
-                    updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
-                }
-            }
-
-            // Both splits are populated but the secondary split has a home/recents stack on top,
-            // so enter minimized mode.
-            mSplitScreenController.ensureMinimizedSplit();
-        } else {
-            // Both splits are populated by normal activities, so make sure we aren't minimized.
-            mSplitScreenController.ensureNormalSplit();
-        }
-    }
-
-    @Override
-    public void dump(@NonNull PrintWriter pw, String prefix) {
-        final String innerPrefix = prefix + "  ";
-        final String childPrefix = innerPrefix + "  ";
-        pw.println(prefix + this);
-        pw.println(innerPrefix + "mSplitScreenSupported=" + mSplitScreenSupported);
-        if (mPrimary != null) pw.println(innerPrefix + "mPrimary.taskId=" + mPrimary.taskId);
-        if (mSecondary != null) pw.println(innerPrefix + "mSecondary.taskId=" + mSecondary.taskId);
-    }
-
-    @Override
-    public String toString() {
-        return TAG;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
deleted file mode 100644
index 0307206..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.splitscreen;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.annotation.NonNull;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.graphics.Rect;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.Display;
-import android.view.SurfaceControl;
-import android.view.WindowManagerGlobal;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Proxy to simplify calls into window manager/activity manager
- */
-class WindowManagerProxy {
-
-    private static final String TAG = "WindowManagerProxy";
-    private static final int[] HOME_AND_RECENTS = {ACTIVITY_TYPE_HOME, ACTIVITY_TYPE_RECENTS};
-
-    @GuardedBy("mDockedRect")
-    private final Rect mDockedRect = new Rect();
-
-    private final Rect mTmpRect1 = new Rect();
-
-    @GuardedBy("mDockedRect")
-    private final Rect mTouchableRegion = new Rect();
-
-    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
-
-    private final SyncTransactionQueue mSyncTransactionQueue;
-
-    private final Runnable mSetTouchableRegionRunnable = new Runnable() {
-        @Override
-        public void run() {
-            try {
-                synchronized (mDockedRect) {
-                    mTmpRect1.set(mTouchableRegion);
-                }
-                WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
-                        mTmpRect1);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to set touchable region: " + e);
-            }
-        }
-    };
-
-    private final TaskOrganizer mTaskOrganizer;
-
-    WindowManagerProxy(SyncTransactionQueue syncQueue, TaskOrganizer taskOrganizer) {
-        mSyncTransactionQueue = syncQueue;
-        mTaskOrganizer = taskOrganizer;
-    }
-
-    void dismissOrMaximizeDocked(final SplitScreenTaskListener tiles, SplitDisplayLayout layout,
-            final boolean dismissOrMaximize) {
-        mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
-    }
-
-    public void setResizing(final boolean resizing) {
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    ActivityTaskManager.getService().setSplitScreenResizing(resizing);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Error calling setDockedStackResizing: " + e);
-                }
-            }
-        });
-    }
-
-    /** Sets a touch region */
-    public void setTouchRegion(Rect region) {
-        synchronized (mDockedRect) {
-            mTouchableRegion.set(region);
-        }
-        mExecutor.execute(mSetTouchableRegionRunnable);
-    }
-
-    void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
-        WindowContainerTransaction t = new WindowContainerTransaction();
-        splitLayout.resizeSplits(position, t);
-        new WindowOrganizer().applyTransaction(t);
-    }
-
-    boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out,
-            WindowContainerToken parent) {
-        boolean resizable = false;
-        List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
-                ? mTaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
-                : mTaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
-        for (int i = 0, n = rootTasks.size(); i < n; ++i) {
-            final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
-            out.add(ti);
-            if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
-                resizable = ti.isResizeable;
-            }
-        }
-        return resizable;
-    }
-
-    /**
-     * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary
-     * 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,
-            @NonNull WindowContainerTransaction wct) {
-        // Resize the home/recents stacks to the larger minimized-state size
-        final Rect homeBounds;
-        final ArrayList<ActivityManager.RunningTaskInfo> homeStacks = new ArrayList<>();
-        boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
-        if (isHomeResizable) {
-            homeBounds = layout.calcResizableMinimizedHomeStackBounds();
-        } else {
-            // home is not resizable, so lock it to its inherent orientation size.
-            homeBounds = new Rect(0, 0, 0, 0);
-            for (int i = homeStacks.size() - 1; i >= 0; --i) {
-                if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_HOME) {
-                    final int orient = homeStacks.get(i).configuration.orientation;
-                    final boolean displayLandscape = layout.mDisplayLayout.isLandscape();
-                    final boolean isLandscape = orient == ORIENTATION_LANDSCAPE
-                            || (orient == ORIENTATION_UNDEFINED && displayLandscape);
-                    homeBounds.right = isLandscape == displayLandscape
-                            ? layout.mDisplayLayout.width() : layout.mDisplayLayout.height();
-                    homeBounds.bottom = isLandscape == displayLandscape
-                            ? layout.mDisplayLayout.height() : layout.mDisplayLayout.width();
-                    break;
-                }
-            }
-        }
-        for (int i = homeStacks.size() - 1; i >= 0; --i) {
-            // For non-resizable homes, the minimized size is actually the fullscreen-size. As a
-            // result, we don't minimize for recents since it only shows half-size screenshots.
-            if (!isHomeResizable) {
-                if (homeStacks.get(i).topActivityType == ACTIVITY_TYPE_RECENTS) {
-                    continue;
-                }
-                wct.setWindowingMode(homeStacks.get(i).token, WINDOWING_MODE_FULLSCREEN);
-            }
-            wct.setBounds(homeStacks.get(i).token, homeBounds);
-        }
-        layout.mTiles.mHomeBounds.set(homeBounds);
-        return isHomeResizable;
-    }
-
-    /**
-     * Finishes entering split-screen by reparenting all FULLSCREEN tasks into the secondary split.
-     * This assumes there is already something in the primary split since that is usually what
-     * triggers a call to this. In the same transaction, this overrides the home task bounds via
-     * {@link #applyHomeTasksMinimized}.
-     *
-     * @return whether the home stack is resizable
-     */
-    boolean applyEnterSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout) {
-        // Set launchtile first so that any stack created after
-        // getAllRootTaskInfos and before reparent (even if unlikely) are placed
-        // correctly.
-        mTaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
-        List<ActivityManager.RunningTaskInfo> rootTasks =
-                mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        if (rootTasks.isEmpty()) {
-            return false;
-        }
-        ActivityManager.RunningTaskInfo topHomeTask = null;
-        for (int i = rootTasks.size() - 1; i >= 0; --i) {
-            final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
-            // Only move resizeable task to split secondary. However, we have an exception
-            // for non-resizable home because we will minimize to show it.
-            if (!rootTask.isResizeable && rootTask.topActivityType != ACTIVITY_TYPE_HOME) {
-                continue;
-            }
-            // Only move fullscreen tasks to split secondary.
-            if (rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
-                continue;
-            }
-            // Since this iterates from bottom to top, update topHomeTask for every fullscreen task
-            // so it will be left with the status of the top one.
-            topHomeTask = isHomeOrRecentTask(rootTask) ? rootTask : null;
-            wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
-        }
-        // Move the secondary split-forward.
-        wct.reorder(tiles.mSecondary.token, true /* onTop */);
-        boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
-        if (topHomeTask != null) {
-            // Translate/update-crop of secondary out-of-band with sync transaction -- Until BALST
-            // is enabled, this temporarily syncs the home surface position with offset until
-            // sync transaction finishes.
-            wct.setBoundsChangeTransaction(topHomeTask.token, tiles.mHomeBounds);
-        }
-        applySyncTransaction(wct);
-        return isHomeResizable;
-    }
-
-    boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
-        final int atype = ti.getActivityType();
-        return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS;
-    }
-
-    /**
-     * Reparents all tile members back to their display and resets home task override bounds.
-     * @param dismissOrMaximize When {@code true} this resolves the split by closing the primary
-     *                          split (thus resulting in the top of the secondary split becoming
-     *                          fullscreen. {@code false} resolves the other way.
-     */
-    void applyDismissSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout,
-            boolean dismissOrMaximize) {
-        // Set launch root first so that any task created after getChildContainers and
-        // before reparent (pretty unlikely) are put into fullscreen.
-        mTaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
-        // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
-        //                 plus specific APIs to clean this up.
-        List<ActivityManager.RunningTaskInfo> primaryChildren =
-                mTaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
-        List<ActivityManager.RunningTaskInfo> secondaryChildren =
-                mTaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
-        // In some cases (eg. non-resizable is launched), system-server will leave split-screen.
-        // as a result, the above will not capture any tasks; yet, we need to clean-up the
-        // home task bounds.
-        List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
-                mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, HOME_AND_RECENTS);
-        // Filter out the root split tasks
-        freeHomeAndRecents.removeIf(p -> p.token.equals(tiles.mSecondary.token)
-                || p.token.equals(tiles.mPrimary.token));
-
-        if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
-                && freeHomeAndRecents.isEmpty()) {
-            return;
-        }
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        if (dismissOrMaximize) {
-            // Dismissing, so move all primary split tasks first
-            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
-                wct.reparent(primaryChildren.get(i).token, null /* parent */,
-                        true /* onTop */);
-            }
-            boolean homeOnTop = false;
-            // Don't need to worry about home tasks because they are already in the "proper"
-            // order within the secondary split.
-            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
-                wct.reparent(ti.token, null /* parent */, true /* onTop */);
-                if (isHomeOrRecentTask(ti)) {
-                    wct.setBounds(ti.token, null);
-                    wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
-                    if (i == 0) {
-                        homeOnTop = true;
-                    }
-                }
-            }
-            if (homeOnTop) {
-                // Translate/update-crop of secondary out-of-band with sync transaction -- instead
-                // play this in sync with new home-app frame because until BALST is enabled this
-                // shows up on screen before the syncTransaction returns.
-                // We only have access to the secondary root surface, though, so in order to
-                // position things properly, we have to take into account the existing negative
-                // offset/crop of the minimized-home task.
-                final boolean landscape = layout.mDisplayLayout.isLandscape();
-                final int posX = landscape ? layout.mSecondary.left - tiles.mHomeBounds.left
-                        : layout.mSecondary.left;
-                final int posY = landscape ? layout.mSecondary.top
-                        : layout.mSecondary.top - tiles.mHomeBounds.top;
-                final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
-                sft.setPosition(tiles.mSecondarySurface, posX, posY);
-                final Rect crop = new Rect(0, 0, layout.mDisplayLayout.width(),
-                        layout.mDisplayLayout.height());
-                crop.offset(-posX, -posY);
-                sft.setWindowCrop(tiles.mSecondarySurface, crop);
-                wct.setBoundsChangeTransaction(tiles.mSecondary.token, sft);
-            }
-        } else {
-            // Maximize, so move non-home secondary split first
-            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                if (isHomeOrRecentTask(secondaryChildren.get(i))) {
-                    continue;
-                }
-                wct.reparent(secondaryChildren.get(i).token, null /* parent */,
-                        true /* onTop */);
-            }
-            // Find and place home tasks in-between. This simulates the fact that there was
-            // nothing behind the primary split's tasks.
-            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
-                if (isHomeOrRecentTask(ti)) {
-                    wct.reparent(ti.token, null /* parent */, true /* onTop */);
-                    // reset bounds and mode too
-                    wct.setBounds(ti.token, null);
-                    wct.setWindowingMode(ti.token, WINDOWING_MODE_UNDEFINED);
-                }
-            }
-            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
-                wct.reparent(primaryChildren.get(i).token, null /* parent */,
-                        true /* onTop */);
-            }
-        }
-        for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
-            wct.setBounds(freeHomeAndRecents.get(i).token, null);
-            wct.setWindowingMode(freeHomeAndRecents.get(i).token, WINDOWING_MODE_UNDEFINED);
-        }
-        // Reset focusable to true
-        wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
-        applySyncTransaction(wct);
-    }
-
-    /**
-     * Utility to apply a sync transaction serially with other sync transactions.
-     *
-     * @see SyncTransactionQueue#queue
-     */
-    void applySyncTransaction(WindowContainerTransaction wct) {
-        mSyncTransactionQueue.queue(wct);
-    }
-
-    /**
-     * @see SyncTransactionQueue#queueIfWaiting
-     */
-    boolean queueSyncTransactionIfWaiting(WindowContainerTransaction wct) {
-        return mSyncTransactionQueue.queueIfWaiting(wct);
-    }
-
-    /**
-     * @see SyncTransactionQueue#runInSync
-     */
-    void runInSync(SyncTransactionQueue.TransactionRunnable runnable) {
-        mSyncTransactionQueue.runInSync(runnable);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index ee79824..e144ca3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,11 +16,18 @@
 
 package com.android.wm.shell.startingsurface;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.content.Context.CONTEXT_RESTRICTED;
 import static android.content.res.Configuration.EMPTY;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
 
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -30,18 +37,20 @@
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
+import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.View;
 import android.view.WindowManager;
+import android.window.StartingWindowInfo;
 import android.window.TaskOrganizer;
+import android.window.TaskSnapshot;
 
 import com.android.internal.R;
 import com.android.internal.policy.PhoneWindow;
+import com.android.wm.shell.common.ShellExecutor;
 
 import java.util.function.Consumer;
 
@@ -56,22 +65,24 @@
  * @hide
  */
 public class StartingSurfaceDrawer {
-    private static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
-    private static final boolean DEBUG_SPLASH_SCREEN = false;
+    static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
+    static final boolean DEBUG_SPLASH_SCREEN = false;
+    static final boolean DEBUG_TASK_SNAPSHOT = false;
 
     private final Context mContext;
     private final DisplayManager mDisplayManager;
+    final ShellExecutor mMainExecutor;
 
     // TODO(b/131727939) remove this when clearing ActivityRecord
     private static final int REMOVE_WHEN_TIMEOUT = 2000;
 
-    public StartingSurfaceDrawer(Context context) {
+    public StartingSurfaceDrawer(Context context, ShellExecutor mainExecutor) {
         mContext = context;
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
+        mMainExecutor = mainExecutor;
     }
 
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private final SparseArray<TaskScreenView> mTaskScreenViews = new SparseArray<>();
+    private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
 
     /** Obtain proper context for showing splash screen on the provided display. */
     private Context getDisplayContext(Context context, int displayId) {
@@ -90,12 +101,111 @@
         return context.createDisplayContext(targetDisplay);
     }
 
+    private static class PreferredStartingTypeHelper {
+        private static final int STARTING_TYPE_NO = 0;
+        private static final int STARTING_TYPE_SPLASH_SCREEN = 1;
+        private static final int STARTING_TYPE_SNAPSHOT = 2;
+
+        TaskSnapshot mSnapshot;
+        int mPreferredType;
+
+        PreferredStartingTypeHelper(StartingWindowInfo taskInfo) {
+            final int parameter = taskInfo.startingWindowTypeParameter;
+            final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
+            final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
+            final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
+            final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
+            final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
+            mPreferredType = preferredStartingWindowType(taskInfo, newTask, taskSwitch,
+                    processRunning, allowTaskSnapshot, activityCreated);
+        }
+
+        // reference from ActivityRecord#getStartingWindowType
+        private int preferredStartingWindowType(StartingWindowInfo windowInfo,
+                boolean newTask, boolean taskSwitch, boolean processRunning,
+                boolean allowTaskSnapshot, boolean activityCreated) {
+            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
+                        + " taskSwitch " + taskSwitch
+                        + " processRunning " + processRunning
+                        + " allowTaskSnapshot " + allowTaskSnapshot
+                        + " activityCreated " + activityCreated);
+            }
+
+            if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+                return STARTING_TYPE_SPLASH_SCREEN;
+            } else if (taskSwitch && allowTaskSnapshot) {
+                final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
+                if (isSnapshotCompatible(windowInfo, snapshot)) {
+                    return STARTING_TYPE_SNAPSHOT;
+                }
+                if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
+                    return STARTING_TYPE_SPLASH_SCREEN;
+                }
+                return STARTING_TYPE_NO;
+            } else {
+                return STARTING_TYPE_NO;
+            }
+        }
+
+        /**
+         * Returns {@code true} if the task snapshot is compatible with this activity (at least the
+         * rotation must be the same).
+         */
+        private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
+            if (snapshot == null) {
+                if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                    Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
+                }
+                return false;
+            }
+
+            final int taskRotation = windowInfo.taskInfo.configuration
+                    .windowConfiguration.getRotation();
+            final int snapshotRotation = snapshot.getRotation();
+            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+                Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
+                        + " snapshot " + snapshotRotation);
+            }
+            return taskRotation == snapshotRotation;
+        }
+
+        private TaskSnapshot getTaskSnapshot(int taskId) {
+            if (mSnapshot != null) {
+                return mSnapshot;
+            }
+            try {
+                mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
+                        false/* isLowResolution */);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
+                return null;
+            }
+            return mSnapshot;
+        }
+    }
+
     /**
      * Called when a task need a starting window.
      */
-    public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) {
+    public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+        final PreferredStartingTypeHelper helper =
+                new PreferredStartingTypeHelper(windowInfo);
+        final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
+        if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SPLASH_SCREEN) {
+            addSplashScreenStartingWindow(runningTaskInfo, appToken);
+        } else if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SNAPSHOT) {
+            final TaskSnapshot snapshot = helper.mSnapshot;
+            makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+        }
+        // If prefer don't show, then don't show!
+    }
 
+    private void addSplashScreenStartingWindow(RunningTaskInfo taskInfo, IBinder appToken) {
         final ActivityInfo activityInfo = taskInfo.topActivityInfo;
+        if (activityInfo == null) {
+            return;
+        }
         final int displayId = taskInfo.displayId;
         if (activityInfo.packageName == null) {
             return;
@@ -250,18 +360,34 @@
     }
 
     /**
+     * Called when a task need a snapshot starting window.
+     */
+    private void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo,
+            IBinder appToken, TaskSnapshot snapshot) {
+        final int taskId = startingWindowInfo.taskInfo.taskId;
+        final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
+                snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */);
+        mMainExecutor.execute(() -> {
+            mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
+            final StartingWindowRecord tView =
+                    new StartingWindowRecord(null/* decorView */, surface);
+            mStartingWindowRecords.put(taskId, tView);
+        });
+    }
+
+    /**
      * Called when the content of a task is ready to show, starting window can be removed.
      */
-    public void removeStartingWindow(ActivityManager.RunningTaskInfo taskInfo) {
-        if (DEBUG_SPLASH_SCREEN) {
-            Slog.d(TAG, "Task start finish, remove starting surface for task " + taskInfo.taskId);
+    public void removeStartingWindow(int taskId) {
+        if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+            Slog.d(TAG, "Task start finish, remove starting surface for task " + taskId);
         }
-        mHandler.post(() -> removeWindowSynced(taskInfo.taskId));
+        mMainExecutor.execute(() -> removeWindowSynced(taskId));
     }
 
     protected void postAddWindow(int taskId, IBinder appToken,
             View view, WindowManager wm, WindowManager.LayoutParams params) {
-        mHandler.post(() -> {
+        mMainExecutor.execute(() -> {
             boolean shouldSaveView = true;
             try {
                 wm.addView(view, params);
@@ -286,25 +412,32 @@
 
             if (shouldSaveView) {
                 removeWindowSynced(taskId);
-                mHandler.postDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
-                final TaskScreenView tView = new TaskScreenView(view);
-                mTaskScreenViews.put(taskId, tView);
+                mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
+                final StartingWindowRecord tView =
+                        new StartingWindowRecord(view, null /* TaskSnapshotWindow */);
+                mStartingWindowRecords.put(taskId, tView);
             }
         });
     }
 
     protected void removeWindowSynced(int taskId) {
-        final TaskScreenView preView = mTaskScreenViews.get(taskId);
-        if (preView != null) {
-            if (preView.mDecorView != null) {
+        final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+        if (record != null) {
+            if (record.mDecorView != null) {
                 if (DEBUG_SPLASH_SCREEN) {
                     Slog.v(TAG, "Removing splash screen window for task: " + taskId);
                 }
-                final WindowManager wm = preView.mDecorView.getContext()
+                final WindowManager wm = record.mDecorView.getContext()
                         .getSystemService(WindowManager.class);
-                wm.removeView(preView.mDecorView);
+                wm.removeView(record.mDecorView);
             }
-            mTaskScreenViews.remove(taskId);
+            if (record.mTaskSnapshotWindow != null) {
+                if (DEBUG_TASK_SNAPSHOT) {
+                    Slog.v(TAG, "Removing task snapshot window for " + taskId);
+                }
+                record.mTaskSnapshotWindow.remove(mMainExecutor);
+            }
+            mStartingWindowRecords.remove(taskId);
         }
     }
 
@@ -315,13 +448,15 @@
     }
 
     /**
-     * Record the views in a starting window.
+     * Record the view or surface for a starting window.
      */
-    private static class TaskScreenView {
+    private static class StartingWindowRecord {
         private final View mDecorView;
+        private final TaskSnapshotWindow mTaskSnapshotWindow;
 
-        TaskScreenView(View decorView) {
+        StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) {
             mDecorView = decorView;
+            mTaskSnapshotWindow = taskSnapshotWindow;
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
new file mode 100644
index 0000000..e66d85f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -0,0 +1,622 @@
+/*
+ * 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.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManager.TaskDescription;
+import android.app.ActivityThread;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.hardware.HardwareBuffer;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.MergedConfiguration;
+import android.util.Slog;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.InsetsSourceControl;
+import android.view.InsetsState;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.window.ClientWindowFrames;
+import android.window.StartingWindowInfo;
+import android.window.TaskSnapshot;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
+import com.android.internal.view.BaseIWindow;
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * This class represents a starting window that shows a snapshot.
+ *
+ * @hide
+ */
+public class TaskSnapshotWindow {
+
+    private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+    /**
+     * When creating the starting window, we use the exact same layout flags such that we end up
+     * with a window with the exact same dimensions etc. However, these flags are not used in layout
+     * and might cause other side effects so we exclude them.
+     */
+    static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+            | FLAG_NOT_TOUCHABLE
+            | FLAG_NOT_TOUCH_MODAL
+            | FLAG_ALT_FOCUSABLE_IM
+            | FLAG_NOT_FOCUSABLE
+            | FLAG_HARDWARE_ACCELERATED
+            | FLAG_IGNORE_CHEEK_PRESSES
+            | FLAG_LOCAL_FOCUS_MODE
+            | FLAG_SLIPPERY
+            | FLAG_WATCH_OUTSIDE_TOUCH
+            | FLAG_SPLIT_TOUCH
+            | FLAG_SCALED
+            | FLAG_SECURE;
+
+    private static final String TAG = StartingSurfaceDrawer.TAG;
+    private static final boolean DEBUG = StartingSurfaceDrawer.DEBUG_TASK_SNAPSHOT;
+    private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
+
+    //tmp vars for unused relayout params
+    private static final Point TMP_SURFACE_SIZE = new Point();
+
+    private final Window mWindow;
+    private final Surface mSurface;
+    private final Runnable mClearWindowHandler;
+    private SurfaceControl mSurfaceControl;
+    private SurfaceControl mChildSurfaceControl;
+    private final IWindowSession mSession;
+    private final Rect mTaskBounds;
+    private final Rect mFrame = new Rect();
+    private final Rect mSystemBarInsets = new Rect();
+    private TaskSnapshot mSnapshot;
+    private final RectF mTmpSnapshotSize = new RectF();
+    private final RectF mTmpDstFrame = new RectF();
+    private final CharSequence mTitle;
+    private boolean mHasDrawn;
+    private long mShownTime;
+    private boolean mSizeMismatch;
+    private final Paint mBackgroundPaint = new Paint();
+    private final int mActivityType;
+    private final int mStatusBarColor;
+    private final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
+    private final int mOrientationOnCreation;
+    private final SurfaceControl.Transaction mTransaction;
+    private final Matrix mSnapshotMatrix = new Matrix();
+    private final float[] mTmpFloat9 = new float[9];
+
+    static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
+            TaskSnapshot snapshot, ShellExecutor mainExecutor, Runnable clearWindowHandler) {
+        final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
+        final int taskId = runningTaskInfo.taskId;
+        if (DEBUG) {
+            Slog.d(TAG, "create taskSnapshot surface for task: " + taskId);
+        }
+
+        final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
+        final WindowManager.LayoutParams mainWindowParams = info.mainWindowLayoutParams;
+        final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
+        if (attrs == null || mainWindowParams == null || topWindowInsetsState == null) {
+            Slog.w(TAG, "unable to create taskSnapshot surface for task: " + taskId);
+            return null;
+        }
+        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+
+        final int appearance = attrs.insetsFlags.appearance;
+        final int windowFlags = attrs.flags;
+        final int windowPrivateFlags = attrs.privateFlags;
+
+        layoutParams.packageName = mainWindowParams.packageName;
+        layoutParams.windowAnimations = mainWindowParams.windowAnimations;
+        layoutParams.dimAmount = mainWindowParams.dimAmount;
+        layoutParams.type = TYPE_APPLICATION_STARTING;
+        layoutParams.format = snapshot.getHardwareBuffer().getFormat();
+        layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
+                | FLAG_NOT_FOCUSABLE
+                | FLAG_NOT_TOUCHABLE;
+        // Setting as trusted overlay to let touches pass through. This is safe because this
+        // window is controlled by the system.
+        layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS)
+                | PRIVATE_FLAG_TRUSTED_OVERLAY;
+        layoutParams.token = appToken;
+        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+        layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+        layoutParams.insetsFlags.appearance = appearance;
+        layoutParams.insetsFlags.behavior = attrs.insetsFlags.behavior;
+        layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
+        layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
+        layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
+        layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
+
+        layoutParams.setTitle(String.format(TITLE_FORMAT, taskId));
+
+        final Point taskSize = snapshot.getTaskSize();
+        final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
+        final int orientation = snapshot.getOrientation();
+
+        final int activityType = runningTaskInfo.topActivityType;
+        final int displayId = runningTaskInfo.displayId;
+
+        final IWindowSession session = WindowManagerGlobal.getWindowSession();
+        final SurfaceControl surfaceControl = new SurfaceControl();
+        final ClientWindowFrames tmpFrames = new ClientWindowFrames();
+
+        final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
+        final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
+
+        final TaskDescription taskDescription;
+        if (runningTaskInfo.taskDescription != null) {
+            taskDescription = runningTaskInfo.taskDescription;
+        } else {
+            taskDescription = new TaskDescription();
+            taskDescription.setBackgroundColor(WHITE);
+        }
+
+        final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
+                surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance,
+                windowFlags, windowPrivateFlags, taskBounds, orientation, activityType,
+                topWindowInsetsState, clearWindowHandler);
+        final Window window = snapshotSurface.mWindow;
+
+        final InsetsState mTmpInsetsState = new InsetsState();
+        final InputChannel tmpInputChannel = new InputChannel();
+        mainExecutor.execute(() -> {
+            try {
+                final int res = session.addToDisplay(window, layoutParams, View.GONE,
+                        displayId, mTmpInsetsState, tmpFrames.frame,
+                        tmpFrames.displayCutout, tmpInputChannel/* outInputChannel */,
+                        mTmpInsetsState, mTempControls);
+                if (res < 0) {
+                    Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
+                    return;
+                }
+            } catch (RemoteException e) {
+                snapshotSurface.clearWindowSynced();
+            }
+            window.setOuter(snapshotSurface, mainExecutor);
+            try {
+                session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
+                        tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
+                        mTempControls, TMP_SURFACE_SIZE);
+            } catch (RemoteException e) {
+                snapshotSurface.clearWindowSynced();
+            }
+
+            final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, topWindowInsetsState);
+            snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets);
+            snapshotSurface.drawSnapshot();
+        });
+        return snapshotSurface;
+    }
+
+    public TaskSnapshotWindow(SurfaceControl surfaceControl,
+            TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
+            int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds,
+            int currentOrientation, int activityType, InsetsState topWindowInsetsState,
+            Runnable clearWindowHandler) {
+        mSurface = new Surface();
+        mSession = WindowManagerGlobal.getWindowSession();
+        mWindow = new Window();
+        mWindow.setSession(mSession);
+        mSurfaceControl = surfaceControl;
+        mSnapshot = snapshot;
+        mTitle = title;
+        int backgroundColor = taskDescription.getBackgroundColor();
+        mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+        mTaskBounds = taskBounds;
+        mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
+                windowPrivateFlags, appearance, taskDescription, 1f, topWindowInsetsState);
+        mStatusBarColor = taskDescription.getStatusBarColor();
+        mOrientationOnCreation = currentOrientation;
+        mActivityType = activityType;
+        mTransaction = new SurfaceControl.Transaction();
+        mClearWindowHandler = clearWindowHandler;
+    }
+
+    /**
+     * Ask system bar background painter to draw status bar background.
+     * @hide
+     */
+    public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+        mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
+                mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
+    }
+
+    /**
+     * Ask system bar background painter to draw navigation bar background.
+     * @hide
+     */
+    public void drawNavigationBarBackground(Canvas c) {
+        mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
+    }
+
+    void remove(ShellExecutor mainExecutor) {
+        final long now = SystemClock.uptimeMillis();
+        if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
+                // Show the latest content as soon as possible for unlocking to home.
+                && mActivityType != ACTIVITY_TYPE_HOME) {
+            final long delayTime = mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS - now;
+            mainExecutor.executeDelayed(() -> remove(mainExecutor), delayTime);
+            if (DEBUG) {
+                Slog.d(TAG, "Defer removing snapshot surface in " + delayTime);
+            }
+            return;
+        }
+        mainExecutor.execute(() -> {
+            try {
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn);
+                }
+                mSession.remove(mWindow);
+            } catch (RemoteException e) {
+                // nothing
+            }
+        });
+    }
+
+    /**
+     * Set frame size.
+     * @hide
+     */
+    public void setFrames(Rect frame, Rect systemBarInsets) {
+        mFrame.set(frame);
+        mSystemBarInsets.set(systemBarInsets);
+        final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+        mSizeMismatch = (mFrame.width() != snapshot.getWidth()
+                || mFrame.height() != snapshot.getHeight());
+        mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+    }
+
+    static Rect getSystemBarInsets(Rect frame, InsetsState state) {
+        return state.calculateInsets(frame, WindowInsets.Type.systemBars(),
+                false /* ignoreVisibility */);
+    }
+
+    private void drawSnapshot() {
+        mSurface.copyFrom(mSurfaceControl);
+        if (DEBUG) {
+            Slog.d(TAG, "Drawing snapshot surface sizeMismatch= " + mSizeMismatch);
+        }
+        if (mSizeMismatch) {
+            // The dimensions of the buffer and the window don't match, so attaching the buffer
+            // will fail. Better create a child window with the exact dimensions and fill the parent
+            // window with the background color!
+            drawSizeMismatchSnapshot();
+        } else {
+            drawSizeMatchSnapshot();
+        }
+        mShownTime = SystemClock.uptimeMillis();
+        mHasDrawn = true;
+        reportDrawn();
+
+        // In case window manager leaks us, make sure we don't retain the snapshot.
+        mSnapshot = null;
+    }
+
+    private void drawSizeMatchSnapshot() {
+        mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getHardwareBuffer(),
+                mSnapshot.getColorSpace());
+        mSurface.release();
+    }
+
+    private void drawSizeMismatchSnapshot() {
+        if (!mSurface.isValid()) {
+            throw new IllegalStateException("mSurface does not hold a valid surface.");
+        }
+        final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
+        final SurfaceSession session = new SurfaceSession();
+
+        // We consider nearly matched dimensions as there can be rounding errors and the user won't
+        // notice very minute differences from scaling one dimension more than the other
+        final boolean aspectRatioMismatch = Math.abs(
+                ((float) buffer.getWidth() / buffer.getHeight())
+                - ((float) mFrame.width() / mFrame.height())) > 0.01f;
+
+        // Keep a reference to it such that it doesn't get destroyed when finalized.
+        mChildSurfaceControl = new SurfaceControl.Builder(session)
+                .setName(mTitle + " - task-snapshot-surface")
+                .setBufferSize(buffer.getWidth(), buffer.getHeight())
+                .setFormat(buffer.getFormat())
+                .setParent(mSurfaceControl)
+                .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot")
+                .build();
+        Surface surface = new Surface();
+        surface.copyFrom(mChildSurfaceControl);
+
+        final Rect frame;
+        // We can just show the surface here as it will still be hidden as the parent is
+        // still hidden.
+        mTransaction.show(mChildSurfaceControl);
+        if (aspectRatioMismatch) {
+            // Clip off ugly navigation bar.
+            final Rect crop = calculateSnapshotCrop();
+            frame = calculateSnapshotFrame(crop);
+            mTransaction.setWindowCrop(mChildSurfaceControl, crop);
+            mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top);
+            mTmpSnapshotSize.set(crop);
+            mTmpDstFrame.set(frame);
+        } else {
+            frame = null;
+            mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
+            mTmpDstFrame.set(mFrame);
+            mTmpDstFrame.offsetTo(0, 0);
+        }
+
+        // Scale the mismatch dimensions to fill the task bounds
+        mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
+        mTransaction.setMatrix(mChildSurfaceControl, mSnapshotMatrix, mTmpFloat9);
+
+        mTransaction.apply();
+        surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
+        surface.release();
+
+        if (aspectRatioMismatch) {
+            final Canvas c = mSurface.lockCanvas(null);
+            drawBackgroundAndBars(c, frame);
+            mSurface.unlockCanvasAndPost(c);
+            mSurface.release();
+        }
+    }
+
+    /**
+     * Calculates the snapshot crop in snapshot coordinate space.
+     *
+     * @return crop rect in snapshot coordinate space.
+     */
+    public Rect calculateSnapshotCrop() {
+        final Rect rect = new Rect();
+        final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+        rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
+        final Rect insets = mSnapshot.getContentInsets();
+
+        final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
+        final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+
+        // Let's remove all system decorations except the status bar, but only if the task is at the
+        // very top of the screen.
+        final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
+        rect.inset((int) (insets.left * scaleX),
+                isTop ? 0 : (int) (insets.top * scaleY),
+                (int) (insets.right * scaleX),
+                (int) (insets.bottom * scaleY));
+        return rect;
+    }
+
+    /**
+     * Calculates the snapshot frame in window coordinate space from crop.
+     *
+     * @param crop rect that is in snapshot coordinate space.
+     */
+    public Rect calculateSnapshotFrame(Rect crop) {
+        final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+        final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
+        final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+
+        // Rescale the frame from snapshot to window coordinate space
+        final Rect frame = new Rect(0, 0,
+                (int) (crop.width() / scaleX + 0.5f),
+                (int) (crop.height() / scaleY + 0.5f)
+        );
+
+        // However, we also need to make space for the navigation bar on the left side.
+        frame.offset(mSystemBarInsets.left, 0);
+        return frame;
+    }
+
+    /**
+     * Draw status bar and navigation bar background.
+     * @hide
+     */
+    public void drawBackgroundAndBars(Canvas c, Rect frame) {
+        final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
+        final boolean fillHorizontally = c.getWidth() > frame.right;
+        final boolean fillVertically = c.getHeight() > frame.bottom;
+        if (fillHorizontally) {
+            c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+                    c.getWidth(), fillVertically
+                            ? frame.bottom
+                            : c.getHeight(),
+                    mBackgroundPaint);
+        }
+        if (fillVertically) {
+            c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+        }
+        mSystemBarBackgroundPainter.drawDecors(c, frame);
+    }
+
+    /**
+     * Clear window from drawer, must be post on main executor.
+     */
+    private void clearWindowSynced() {
+        if (mClearWindowHandler != null) {
+            mClearWindowHandler.run();
+        }
+    }
+
+    private void reportDrawn() {
+        try {
+            mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+        } catch (RemoteException e) {
+            clearWindowSynced();
+        }
+    }
+
+    static class Window extends BaseIWindow {
+        private TaskSnapshotWindow mOuter;
+        private ShellExecutor mMainExecutor;
+
+        public void setOuter(TaskSnapshotWindow outer, ShellExecutor mainExecutor) {
+            mOuter = outer;
+            mMainExecutor = mainExecutor;
+        }
+
+        @Override
+        public void resized(ClientWindowFrames frames, boolean reportDraw,
+                MergedConfiguration mergedConfiguration, boolean forceLayout,
+                boolean alwaysConsumeSystemBars, int displayId) {
+            if (mOuter != null) {
+                if (mergedConfiguration != null
+                        && mOuter.mOrientationOnCreation
+                        != mergedConfiguration.getMergedConfiguration().orientation) {
+                    // The orientation of the screen is changing. We better remove the snapshot ASAP
+                    // as we are going to wait on the new window in any case to unfreeze the screen,
+                    // and the starting window is not needed anymore.
+                    mMainExecutor.execute(() -> {
+                        mOuter.clearWindowSynced();
+                    });
+                } else if (reportDraw) {
+                    mMainExecutor.execute(() -> {
+                        if (mOuter.mHasDrawn) {
+                            mOuter.reportDrawn();
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    /**
+     * Helper class to draw the background of the system bars in regions the task snapshot isn't
+     * filling the window.
+     */
+    static class SystemBarBackgroundPainter {
+        private final Paint mStatusBarPaint = new Paint();
+        private final Paint mNavigationBarPaint = new Paint();
+        private final int mStatusBarColor;
+        private final int mNavigationBarColor;
+        private final int mWindowFlags;
+        private final int mWindowPrivateFlags;
+        private final float mScale;
+        private final InsetsState mInsetsState;
+        private final Rect mSystemBarInsets = new Rect();
+
+        SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
+                TaskDescription taskDescription, float scale, InsetsState insetsState) {
+            mWindowFlags = windowFlags;
+            mWindowPrivateFlags = windowPrivateFlags;
+            mScale = scale;
+            final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
+            final int semiTransparent = context.getColor(
+                    R.color.system_bar_background_semi_transparent);
+            mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
+                    semiTransparent, taskDescription.getStatusBarColor(), appearance,
+                    APPEARANCE_LIGHT_STATUS_BARS,
+                    taskDescription.getEnsureStatusBarContrastWhenTransparent());
+            mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
+                    FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
+                    taskDescription.getNavigationBarColor(), appearance,
+                    APPEARANCE_LIGHT_NAVIGATION_BARS,
+                    taskDescription.getEnsureNavigationBarContrastWhenTransparent()
+                            && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
+            mStatusBarPaint.setColor(mStatusBarColor);
+            mNavigationBarPaint.setColor(mNavigationBarColor);
+            mInsetsState = insetsState;
+        }
+
+        void setInsets(Rect systemBarInsets) {
+            mSystemBarInsets.set(systemBarInsets);
+        }
+
+        int getStatusBarColorViewHeight() {
+            final boolean forceBarBackground =
+                    (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+            if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+                    mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
+                return (int) (mSystemBarInsets.top * mScale);
+            } else {
+                return 0;
+            }
+        }
+
+        private boolean isNavigationBarColorViewVisible() {
+            final boolean forceBarBackground =
+                    (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+            return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+                    mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
+        }
+
+        void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+            drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
+            drawNavigationBarBackground(c);
+        }
+
+        void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
+                int statusBarHeight) {
+            if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
+                    && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
+                final int rightInset = (int) (mSystemBarInsets.right * mScale);
+                final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
+                c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+            }
+        }
+
+        @VisibleForTesting
+        void drawNavigationBarBackground(Canvas c) {
+            final Rect navigationBarRect = new Rect();
+            getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
+                    mScale);
+            final boolean visible = isNavigationBarColorViewVisible();
+            if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
+                c.drawRect(navigationBarRect, mNavigationBarPaint);
+            }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 3ed53fb..e3ac3f0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -16,8 +16,11 @@
 
 package com.android.wm.shell.flicker
 
+import android.graphics.Region
+import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
 import com.android.server.wm.flicker.dsl.EventLogAssertion
 import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
 
 @JvmOverloads
 fun LayersAssertion.appPairsDividerIsVisible(
@@ -25,7 +28,7 @@
     enabled: Boolean = bugId == 0
 ) {
     end("appPairsDividerIsVisible", bugId, enabled) {
-        this.showsLayer(FlickerTestBase.APP_PAIRS_DIVIDER)
+        this.showsLayer(FlickerTestBase.SPLIT_DIVIDER)
     }
 }
 
@@ -35,7 +38,7 @@
     enabled: Boolean = bugId == 0
 ) {
     end("appPairsDividerIsInVisible", bugId, enabled) {
-        this.hasNotLayer(FlickerTestBase.APP_PAIRS_DIVIDER)
+        this.hasNotLayer(FlickerTestBase.SPLIT_DIVIDER)
     }
 }
 
@@ -50,6 +53,30 @@
 }
 
 @JvmOverloads
+fun LayersAssertion.dockedStackDividerBecomesVisible(
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("dividerLayerBecomesVisible") {
+        this.hidesLayer(DOCKED_STACK_DIVIDER)
+                .then()
+                .showsLayer(DOCKED_STACK_DIVIDER)
+    }
+}
+
+@JvmOverloads
+fun LayersAssertion.dockedStackDividerBecomesInvisible(
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("dividerLayerBecomesInvisible") {
+        this.showsLayer(DOCKED_STACK_DIVIDER)
+                .then()
+                .hidesLayer(DOCKED_STACK_DIVIDER)
+    }
+}
+
+@JvmOverloads
 fun LayersAssertion.dockedStackDividerIsInvisible(
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
@@ -59,6 +86,50 @@
     }
 }
 
+@JvmOverloads
+fun LayersAssertion.dockedStackPrimaryBoundsIsVisible(
+    rotation: Int,
+    primaryLayerName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    end("PrimaryAppBounds", bugId, enabled) {
+        val entry = this.trace.entries.firstOrNull()
+                ?: throw IllegalStateException("Trace is empty")
+        val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+        this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+    }
+}
+
+@JvmOverloads
+fun LayersAssertion.dockedStackSecondaryBoundsIsVisible(
+    rotation: Int,
+    secondaryLayerName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    end("SecondaryAppBounds", bugId, enabled) {
+        val entry = this.trace.entries.firstOrNull()
+                ?: throw IllegalStateException("Trace is empty")
+        val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+        this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+    }
+}
+
+fun getPrimaryRegion(dividerRegion: Region, rotation: Int): Region {
+    val displayBounds = WindowUtils.getDisplayBounds(rotation)
+    return Region(0, 0, displayBounds.getBounds().right,
+            dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset)
+}
+
+fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region {
+    val displayBounds = WindowUtils.getDisplayBounds(rotation)
+    return Region(0,
+            dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset,
+            displayBounds.getBounds().right,
+            displayBounds.getBounds().bottom - WindowUtils.navigationBarHeight)
+}
+
 fun EventLogAssertion.focusChanges(
     vararg windows: String,
     bugId: Int = 0,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 96234fc..5125a39 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -37,3 +37,4 @@
 // Test App > SplitScreen Activity
 const val TEST_APP_SPLITSCREEN_PRIMARY_LABEL = "SplitScreenPrimaryApp"
 const val TEST_APP_SPLITSCREEN_SECONDARY_LABEL = "SplitScreenSecondaryApp"
+const val TEST_APP_NONRESIZEABLE_LABEL = "NonResizeableApp"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
index 54b8fdc..7809be0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -130,7 +130,7 @@
         const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
         const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
         const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
-        const val APP_PAIRS_DIVIDER = "AppPairDivider"
+        const val SPLIT_DIVIDER = "SplitDivider"
         const val IMAGE_WALLPAPER = "ImageWallpaper"
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
index 7ac91b0..379ec95 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
@@ -61,10 +61,9 @@
             setup {
                 eachRun {
                     uiDevice.wakeUpAndGoToHomeScreen()
-                    primaryApp.open()
-                    uiDevice.pressHome()
-                    secondaryApp.open()
-                    uiDevice.pressHome()
+                    primaryApp.launchViaIntent()
+                    secondaryApp.launchViaIntent()
+                    nonResizeableApp.launchViaIntent()
                     updateTaskId()
                 }
             }
@@ -90,7 +89,7 @@
 
     @Test
     fun testAppPairs_pairPrimaryAndSecondaryApps() {
-        val testTag = "testAppPaired_pairPrimaryAndSecondary"
+        val testTag = "testAppPairs_pairPrimaryAndSecondaryApps"
         runWithFlicker(appPairsSetup) {
             withTestName { testTag }
             repeat {
@@ -108,7 +107,7 @@
                     end("appsEndingBounds", enabled = false) {
                         val entry = this.trace.entries.firstOrNull()
                                 ?: throw IllegalStateException("Trace is empty")
-                        val dividerRegion = entry.getVisibleBounds(APP_PAIRS_DIVIDER)
+                        val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER)
                         this.hasVisibleRegion(primaryApp.defaultWindowName,
                                 appPairsHelper.getPrimaryBounds(dividerRegion))
                                 .and()
@@ -152,7 +151,7 @@
                     start("appsStartingBounds", enabled = false) {
                         val entry = this.trace.entries.firstOrNull()
                                 ?: throw IllegalStateException("Trace is empty")
-                        val dividerRegion = entry.getVisibleBounds(APP_PAIRS_DIVIDER)
+                        val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER)
                         this.hasVisibleRegion(primaryApp.defaultWindowName,
                                 appPairsHelper.getPrimaryBounds(dividerRegion))
                                 .and()
@@ -176,6 +175,36 @@
         }
     }
 
+    @Test
+    fun testAppPairs_canNotPairNonResizeableApps() {
+        val testTag = "testAppPairs_canNotPairNonResizeableApps"
+        runWithFlicker(appPairsSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                nonResizeableApp.launchViaIntent()
+                // TODO pair apps through normal UX flow
+                executeShellCommand(composePairsCommand(
+                    primaryTaskId, nonResizeableTaskId, true /* pair */))
+                SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+            }
+            assertions {
+                layersTrace {
+                    appPairsDividerIsInvisible()
+                }
+                windowManagerTrace {
+                    end {
+                        showsAppWindow(nonResizeableApp.defaultWindowName)
+                            .and()
+                            .hidesAppWindow(primaryApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
     private fun composePairsCommand(
         primaryApp: String,
         secondaryApp: String,
@@ -202,6 +231,7 @@
     private fun updateTaskId() {
         val primaryAppComponent = primaryApp.openAppIntent.component
         val secondaryAppComponent = secondaryApp.openAppIntent.component
+        val nonResizeableAppComponent = nonResizeableApp.openAppIntent.component
         if (primaryAppComponent != null) {
             primaryTaskId = appPairsHelper.getTaskIdForActivity(
                     primaryAppComponent.packageName, primaryAppComponent.className).toString()
@@ -210,11 +240,17 @@
             secondaryTaskId = appPairsHelper.getTaskIdForActivity(
                     secondaryAppComponent.packageName, secondaryAppComponent.className).toString()
         }
+        if (nonResizeableAppComponent != null) {
+            nonResizeableTaskId = appPairsHelper.getTaskIdForActivity(
+                nonResizeableAppComponent.packageName,
+                nonResizeableAppComponent.className).toString()
+        }
     }
 
     companion object {
         var primaryTaskId = ""
         var secondaryTaskId = ""
+        var nonResizeableTaskId = ""
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<Array<Any>> {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
index f32cd88..4d46f28 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
@@ -17,6 +17,7 @@
 package com.android.wm.shell.flicker.apppairs
 
 import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
 import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
 import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
@@ -36,4 +37,7 @@
     protected val secondaryApp = SplitScreenHelper(instrumentation,
             TEST_APP_SPLITSCREEN_SECONDARY_LABEL,
             Components.SplitScreenSecondaryActivity())
+    protected val nonResizeableApp = SplitScreenHelper(instrumentation,
+        TEST_APP_NONRESIZEABLE_LABEL,
+        Components.NonResizeableActivity())
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
index d580104..c546a4d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
@@ -20,7 +20,6 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.helpers.FIND_TIMEOUT
-import com.android.server.wm.flicker.helpers.waitForIME
 import com.android.wm.shell.flicker.TEST_APP_IME_ACTIVITY_LABEL
 import com.android.wm.shell.flicker.testapp.Components
 import org.junit.Assert
@@ -39,14 +38,9 @@
         Assert.assertNotNull("Text field not found, this usually happens when the device " +
                 "was left in an unknown state (e.g. in split screen)", editText)
         editText.click()
-        if (!uiDevice.waitForIME()) {
-            Assert.fail("IME did not appear")
-        }
     }
 
     fun closeIME() {
         uiDevice.pressBack()
-        // Using only the AccessibilityInfo it is not possible to identify if the IME is active
-        uiDevice.waitForIdle(1000)
     }
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index ed5f8a4..bc74daf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -20,20 +20,17 @@
 import android.media.session.MediaController
 import android.media.session.MediaSessionManager
 import android.os.SystemClock
-import android.view.KeyEvent.KEYCODE_WINDOW
 import androidx.test.uiautomator.By
-import androidx.test.uiautomator.Until
+import androidx.test.uiautomator.BySelector
 import com.android.server.wm.flicker.helpers.closePipWindow
 import com.android.server.wm.flicker.helpers.hasPipWindow
-import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
 import com.android.wm.shell.flicker.TEST_APP_PIP_ACTIVITY_LABEL
+import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
+import com.android.wm.shell.flicker.pip.tv.isFocusedOrHasFocusedChild
 import com.android.wm.shell.flicker.testapp.Components
-import org.junit.Assert.assertNotNull
 import org.junit.Assert.fail
 
-class PipAppHelper(
-    instrumentation: Instrumentation
-) : BaseAppHelper(
+class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
         instrumentation,
         TEST_APP_PIP_ACTIVITY_LABEL,
         Components.PipActivity()
@@ -47,12 +44,34 @@
             it.packageName == packageName
         }
 
-    fun clickButton(resourceId: String) =
-            uiDevice.findObject(By.res(packageName, resourceId))?.click()
-                ?: fail("$resourceId button is not found")
+    fun clickObject(resId: String) {
+        val selector = By.res(packageName, resId)
+        val obj = uiDevice.findObject(selector) ?: error("Could not find `$resId` object")
+
+        if (!isTelevision) {
+            obj.click()
+        } else {
+            focusOnObject(selector) || error("Could not focus on `$resId` object")
+            uiDevice.pressDPadCenter()
+        }
+    }
+
+    private fun focusOnObject(selector: BySelector): Boolean {
+        // We expect all the focusable UI elements to be arranged in a way so that it is possible
+        // to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top"
+        // from "the bottom".
+        repeat(FOCUS_ATTEMPTS) {
+            uiDevice.findObject(selector)?.apply { if (isFocusedOrHasFocusedChild) return true }
+                    ?: error("The object we try to focus on is gone.")
+
+            uiDevice.pressDPadDown()
+            uiDevice.waitForIdle()
+        }
+        return false
+    }
 
     fun clickEnterPipButton() {
-        clickButton("enter_pip")
+        clickObject(ENTER_PIP_BUTTON_ID)
 
         // TODO(b/172321238): remove this check once hasPipWindow is fixed on TVs
         if (!isTelevision) {
@@ -64,17 +83,14 @@
     }
 
     fun clickStartMediaSessionButton() {
-        val startButton = uiDevice.findObject(By.res(packageName, "media_session_start"))
-        assertNotNull("Start button not found, this usually happens when the device " +
-                "was left in an unknown state (e.g. in split screen)", startButton)
-        startButton.click()
+        clickObject(MEDIA_SESSION_START_RADIO_BUTTON_ID)
     }
 
     fun checkWithCustomActionsCheckbox() = uiDevice
-            .findObject(By.res(packageName, "with_custom_actions"))
-            ?.takeIf { it.isCheckable }
-            ?.apply { if (!isChecked) click() }
-            ?: error("'With custom actions' checkbox not found")
+            .findObject(By.res(packageName, WITH_CUSTOM_ACTIONS_BUTTON_ID))
+                ?.takeIf { it.isCheckable }
+                ?.apply { if (!isChecked) clickObject(WITH_CUSTOM_ACTIONS_BUTTON_ID) }
+                ?: error("'With custom actions' checkbox not found")
 
     fun pauseMedia() = mediaController?.transportControls?.pause()
             ?: error("No active media session found")
@@ -83,21 +99,21 @@
             ?: error("No active media session found")
 
     fun closePipWindow() {
-        // TODO(b/172321238): remove this check once and simply call closePipWindow once the TV
-        //  logic is integrated there.
-        if (!isTelevision) {
-            uiDevice.closePipWindow()
+        if (isTelevision) {
+            uiDevice.closeTvPipWindow()
         } else {
-            // Bring up Pip menu
-            uiDevice.pressKeyCode(KEYCODE_WINDOW)
-
-            // Wait for the menu to come up and render the close button
-            val closeButton = uiDevice.wait(
-                    Until.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, "close_button")), 3_000)
-            assertNotNull("Pip menu close button is not found", closeButton)
-            closeButton.click()
-
-            waitUntilClosed()
+            uiDevice.closePipWindow()
         }
+
+        if (!waitUntilClosed()) {
+            fail("Couldn't close Pip")
+        }
+    }
+
+    companion object {
+        private const val FOCUS_ATTEMPTS = 20
+        private const val ENTER_PIP_BUTTON_ID = "enter_pip"
+        private const val WITH_CUSTOM_ACTIONS_BUTTON_ID = "with_custom_actions"
+        private const val MEDIA_SESSION_START_RADIO_BUTTON_ID = "media_session_start"
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index e67fc97..fb795c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -17,9 +17,7 @@
 package com.android.wm.shell.flicker.helpers
 
 import android.app.Instrumentation
-import android.graphics.Region
 import android.os.SystemClock
-import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.wm.shell.flicker.testapp.Components
 
 class SplitScreenHelper(
@@ -43,20 +41,6 @@
         SystemClock.sleep(TIMEOUT_MS)
     }
 
-    fun getPrimaryBounds(dividerBounds: Region): android.graphics.Region {
-        val primaryAppBounds = Region(0, 0, dividerBounds.bounds.right,
-                dividerBounds.bounds.bottom + WindowUtils.dockedStackDividerInset)
-        return primaryAppBounds
-    }
-
-    fun getSecondaryBounds(dividerBounds: Region): android.graphics.Region {
-        val displayBounds = WindowUtils.displayBounds
-        val secondaryAppBounds = Region(0,
-                dividerBounds.bounds.bottom - WindowUtils.dockedStackDividerInset,
-                displayBounds.right, displayBounds.bottom - WindowUtils.navigationBarHeight)
-        return secondaryAppBounds
-    }
-
     companion object {
         const val TEST_REPETITIONS = 1
         const val TIMEOUT_MS = 3_000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
new file mode 100644
index 0000000..b33fa55
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
@@ -0,0 +1,276 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.platform.test.annotations.Presubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.canSplitScreen
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickstep
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
+import org.junit.Assert
+import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test SplitScreen launch.
+ * To run this test: `atest WMShellFlickerTests:EnterLegacySplitScreenTest`
+ */
+@Presubmit
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class EnterLegacySplitScreenTest(
+    rotationName: String,
+    rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+    private val letterBox = "Letterbox"
+
+    private val splitScreenSetup: FlickerBuilder
+        get() = FlickerBuilder(instrumentation).apply {
+            val testLaunchActivity = "launch_splitScreen_test_activity"
+            withTestName {
+                testLaunchActivity
+            }
+            setup {
+                eachRun {
+                    uiDevice.wakeUpAndGoToHomeScreen()
+                    uiDevice.openQuickStepAndClearRecentAppsFromOverview()
+                }
+            }
+            teardown {
+                eachRun {
+                    if (uiDevice.isInSplitScreen()) {
+                        uiDevice.exitSplitScreen()
+                    }
+                    splitScreenApp.exit()
+                    secondaryApp.exit()
+                    nonResizeableApp.exit()
+                }
+            }
+            assertions {
+                layersTrace {
+                    navBarLayerIsAlwaysVisible()
+                    statusBarLayerIsAlwaysVisible()
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(launcherPackageName))
+                }
+            }
+        }
+
+    @Test
+    fun testEnterSplitScreen_dockActivity() {
+        val testTag = "testEnterSplitScreen_dockActivity"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+            }
+            assertions {
+                layersTrace {
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                    dockedStackDividerBecomesVisible()
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName, splitScreenApp.defaultWindowName)
+                    )
+                }
+                windowManagerTrace {
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testEnterSplitScreen_launchToSide() {
+        val testTag = "testEnterSplitScreen_launchToSide"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                secondaryApp.launchViaIntent()
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+                splitScreenApp.reopenAppFromOverview()
+            }
+            assertions {
+                layersTrace {
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                    dockedStackSecondaryBoundsIsVisible(
+                            rotation, secondaryApp.defaultWindowName, 169271943)
+                    dockedStackDividerBecomesVisible()
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+                                    secondaryApp.defaultWindowName)
+                    )
+                }
+                windowManagerTrace {
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                                .and().showsAppWindow(secondaryApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testNonResizeableNotDocked() {
+        val testTag = "testNonResizeableNotDocked"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                nonResizeableApp.launchViaIntent()
+                uiDevice.openQuickstep()
+                if (uiDevice.canSplitScreen()) {
+                    Assert.fail("Non-resizeable app should not enter split screen")
+                }
+            }
+            assertions {
+                layersTrace {
+                    dockedStackDividerIsInvisible()
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName, nonResizeableApp.defaultWindowName)
+                    )
+                }
+                windowManagerTrace {
+                    end {
+                        hidesAppWindow(nonResizeableApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testNonResizeableWhenAlreadyInSplitScreenPrimary() {
+        val testTag = "testNonResizeableWhenAlreadyInSplitScreenPrimary"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                nonResizeableApp.launchViaIntent()
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+                nonResizeableApp.reopenAppFromOverview()
+            }
+            assertions {
+                layersTrace {
+                    dockedStackDividerIsInvisible()
+                    end("appsEndingBounds", enabled = false) {
+                        val displayBounds = WindowUtils.getDisplayBounds(rotation)
+                        this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
+                    }
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+                                    nonResizeableApp.defaultWindowName, letterBox)
+                    )
+                }
+                windowManagerTrace {
+                    end {
+                        showsAppWindow(nonResizeableApp.defaultWindowName)
+                        hidesAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testNonResizeableWhenAlreadyInSplitScreenSecondary() {
+        val testTag = "testNonResizeableWhenAlreadyInSplitScreenSecondary"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+                uiDevice.pressBack()
+                nonResizeableApp.launchViaIntent()
+            }
+            assertions {
+                layersTrace {
+                    dockedStackDividerIsInvisible()
+                    end("appsEndingBounds", enabled = false) {
+                        val displayBounds = WindowUtils.getDisplayBounds(rotation)
+                        this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
+                    }
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+                                    nonResizeableApp.defaultWindowName, letterBox)
+                    )
+                }
+                windowManagerTrace {
+                    end {
+                        showsAppWindow(nonResizeableApp.defaultWindowName)
+                        hidesAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_0)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt
new file mode 100644
index 0000000..573ffc6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.Flicker
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.exitSplitScreenFromBottom
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.repetitions
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenFromBottomTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitLegacySplitScreenFromBottomTest(
+    testName: String,
+    flickerSpec: Flicker
+) : FlickerTestRunner(testName, flickerSpec) {
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val instrumentation = InstrumentationRegistry.getInstrumentation()
+            val testApp = StandardAppHelper(instrumentation,
+                    "com.android.wm.shell.flicker.testapp", "SimpleApp")
+
+            // b/161435597 causes the test not to work on 90 degrees
+            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
+                    .buildTest { configuration ->
+                        withTestName {
+                            buildTestTag("exitSplitScreenFromBottom", testApp,
+                                    configuration)
+                        }
+                        repeat { configuration.repetitions }
+                        setup {
+                            test {
+                                device.wakeUpAndGoToHomeScreen()
+                            }
+                            eachRun {
+                                testApp.open()
+                                device.launchSplitScreen()
+                                device.waitForIdle()
+                                this.setRotation(configuration.endRotation)
+                            }
+                        }
+                        teardown {
+                            eachRun {
+                                testApp.exit()
+                            }
+                            test {
+                                if (device.isInSplitScreen()) {
+                                    device.exitSplitScreen()
+                                }
+                            }
+                        }
+                        transitions {
+                            device.exitSplitScreenFromBottom()
+                        }
+                    }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
new file mode 100644
index 0000000..c51c73a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.platform.test.annotations.Presubmit
+import android.util.Rational
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.layerBecomesInvisible
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.resizeSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test exit SplitScreen mode.
+ * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenTest`
+ */
+@Presubmit
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitLegacySplitScreenTest(
+    rotationName: String,
+    rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+    private val splitScreenSetup: FlickerBuilder
+        get() = FlickerBuilder(instrumentation).apply {
+            val testLaunchActivity = "launch_splitScreen_test_activity"
+            withTestName {
+                testLaunchActivity
+            }
+            setup {
+                eachRun {
+                    uiDevice.wakeUpAndGoToHomeScreen()
+                    uiDevice.openQuickStepAndClearRecentAppsFromOverview()
+                    secondaryApp.launchViaIntent()
+                    splitScreenApp.launchViaIntent()
+                    uiDevice.launchSplitScreen()
+                }
+            }
+            teardown {
+                eachRun {
+                    splitScreenApp.exit()
+                    secondaryApp.exit()
+                }
+            }
+            assertions {
+                windowManagerTrace {
+                    visibleWindowsShownMoreThanOneConsecutiveEntry()
+                }
+                layersTrace {
+                    visibleLayersShownMoreThanOneConsecutiveEntry(
+                            listOf(launcherPackageName))
+                }
+            }
+        }
+
+    @Test
+    fun testEnterSplitScreen_exitPrimarySplitScreenMode() {
+        val testTag = "testEnterSplitScreen_exitPrimarySplitScreenMode"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                uiDevice.exitSplitScreen()
+            }
+            assertions {
+                layersTrace {
+                    dockedStackDividerIsInvisible()
+                    layerBecomesInvisible(splitScreenApp.defaultWindowName)
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        hidesAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    @FlakyTest(bugId = 172811376)
+    fun testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen() {
+        val testTag = "testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen"
+        runWithFlicker(splitScreenSetup) {
+            withTestName { testTag }
+            repeat {
+                TEST_REPETITIONS
+            }
+            transitions {
+                splitScreenApp.reopenAppFromOverview()
+                uiDevice.resizeSplitScreen(startRatio)
+            }
+            assertions {
+                layersTrace {
+                    dockedStackDividerIsInvisible()
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    companion object {
+        private val startRatio = Rational(1, 3)
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_0)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
new file mode 100644
index 0000000..629c71f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.legacysplitscreen
+
+import android.platform.test.annotations.Presubmit
+import android.support.test.launcherhelper.LauncherStrategyFactory
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.Flicker
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.layerBecomesInvisible
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.repetitions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerBecomesInvisible
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:LegacySplitScreenToLauncherTest`
+ */
+@Presubmit
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class LegacySplitScreenToLauncherTest(
+    testName: String,
+    flickerSpec: Flicker
+) : FlickerTestRunner(testName, flickerSpec) {
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val instrumentation = InstrumentationRegistry.getInstrumentation()
+            val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+                    .launcherStrategy.supportedLauncherPackage
+            val testApp = StandardAppHelper(instrumentation,
+                "com.android.wm.shell.flicker.testapp", "SimpleApp")
+
+            // b/161435597 causes the test not to work on 90 degrees
+            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
+                .buildTest { configuration ->
+                    withTestName {
+                        buildTestTag("splitScreenToLauncher", testApp, configuration)
+                    }
+                    repeat { configuration.repetitions }
+                    setup {
+                        test {
+                            device.wakeUpAndGoToHomeScreen()
+                            device.openQuickStepAndClearRecentAppsFromOverview()
+                        }
+                        eachRun {
+                            testApp.open()
+                            this.setRotation(configuration.endRotation)
+                            device.launchSplitScreen()
+                            device.waitForIdle()
+                        }
+                    }
+                    teardown {
+                        eachRun {
+                            testApp.exit()
+                        }
+                        test {
+                            if (device.isInSplitScreen()) {
+                                device.exitSplitScreen()
+                            }
+                        }
+                    }
+                    transitions {
+                        device.exitSplitScreen()
+                    }
+                    assertions {
+                        windowManagerTrace {
+                            navBarWindowIsAlwaysVisible()
+                            statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry()
+                        }
+
+                        layersTrace {
+                            navBarLayerIsAlwaysVisible()
+                            statusBarLayerIsAlwaysVisible()
+                            noUncoveredRegions(configuration.endRotation)
+                            navBarLayerRotatesAndScales(configuration.endRotation)
+                            statusBarLayerRotatesScales(configuration.endRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(
+                                    listOf(launcherPackageName))
+
+                            // b/161435597 causes the test not to work on 90 degrees
+                            dockedStackDividerBecomesInvisible()
+
+                            layerBecomesInvisible(testApp.getPackage())
+                        }
+
+                        eventLog {
+                            focusDoesNotChange(bugId = 151179149)
+                        }
+                    }
+                }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
new file mode 100644
index 0000000..af03869
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
@@ -0,0 +1,140 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.platform.test.annotations.Presubmit
+import android.support.test.launcherhelper.LauncherStrategyFactory
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.Flicker
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.appWindowBecomesVisible
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.layerBecomesVisible
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.repetitions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:OpenAppToLegacySplitScreenTest`
+ */
+@Presubmit
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppToLegacySplitScreenTest(
+    testName: String,
+    flickerSpec: Flicker
+) : FlickerTestRunner(testName, flickerSpec) {
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val instrumentation = InstrumentationRegistry.getInstrumentation()
+            val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+                    .launcherStrategy.supportedLauncherPackage
+            val testApp = StandardAppHelper(instrumentation,
+                "com.android.wm.shell.flicker.testapp", "SimpleApp")
+
+            // b/161435597 causes the test not to work on 90 degrees
+            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
+                .buildTest { configuration ->
+                    withTestName {
+                        buildTestTag("appToSplitScreen", testApp, configuration)
+                    }
+                    repeat { configuration.repetitions }
+                    setup {
+                        test {
+                            device.wakeUpAndGoToHomeScreen()
+                            device.openQuickStepAndClearRecentAppsFromOverview()
+                        }
+                        eachRun {
+                            testApp.open()
+                            device.pressHome()
+                            this.setRotation(configuration.endRotation)
+                        }
+                    }
+                    teardown {
+                        eachRun {
+                            if (device.isInSplitScreen()) {
+                                device.exitSplitScreen()
+                            }
+                        }
+                        test {
+                            testApp.exit()
+                        }
+                    }
+                    transitions {
+                        device.launchSplitScreen()
+                    }
+                    assertions {
+                        windowManagerTrace {
+                            navBarWindowIsAlwaysVisible()
+                            statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+                            appWindowBecomesVisible(testApp.getPackage())
+                        }
+
+                        layersTrace {
+                            navBarLayerIsAlwaysVisible(bugId = 140855415)
+                            statusBarLayerIsAlwaysVisible()
+                            noUncoveredRegions(configuration.endRotation, enabled = false)
+                            navBarLayerRotatesAndScales(configuration.endRotation,
+                                bugId = 140855415)
+                            statusBarLayerRotatesScales(configuration.endRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(
+                                    listOf(launcherPackageName))
+
+                            dockedStackDividerBecomesVisible()
+                            layerBecomesVisible(testApp.getPackage())
+                        }
+
+                        eventLog {
+                            focusChanges(testApp.`package`,
+                                "recents_animation_input_consumer", "NexusLauncherActivity",
+                                bugId = 151179149)
+                        }
+                    }
+                }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
new file mode 100644
index 0000000..391cb2a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.legacysplitscreen
+
+import android.graphics.Region
+import android.util.Rational
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
+import com.android.server.wm.flicker.Flicker
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.resizeSplitScreen
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.repetitions
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test split screen resizing window transitions.
+ * To run this test: `atest WMShellFlickerTests:ResizeLegacySplitScreenTest`
+ *
+ * Currently it runs only in 0 degrees because of b/156100803
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 159096424)
+class ResizeLegacySplitScreenTest(
+    testName: String,
+    flickerSpec: Flicker
+) : FlickerTestRunner(testName, flickerSpec) {
+    companion object {
+        private const val sSimpleActivity = "SimpleActivity"
+        private const val sImeActivity = "ImeActivity"
+        private val startRatio = Rational(1, 3)
+        private val stopRatio = Rational(2, 3)
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val instrumentation = InstrumentationRegistry.getInstrumentation()
+            val testAppTop = StandardAppHelper(instrumentation,
+                "com.android.wm.shell.flicker.testapp", "SimpleApp")
+            val testAppBottom = ImeAppHelper(instrumentation)
+
+            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
+                .buildTest { configuration ->
+                    withTestName {
+                        val description = (startRatio.toString().replace("/", "-") + "_to_" +
+                            stopRatio.toString().replace("/", "-"))
+                        buildTestTag("resizeSplitScreen", testAppTop.launcherName,
+                            configuration.startRotation, configuration.endRotation,
+                            testAppBottom.launcherName, description)
+                    }
+                    repeat { configuration.repetitions }
+                    setup {
+                        eachRun {
+                            device.wakeUpAndGoToHomeScreen()
+                            this.setRotation(configuration.startRotation)
+                            this.launcherStrategy.clearRecentAppsFromOverview()
+                            testAppBottom.open()
+                            device.pressHome()
+                            testAppTop.open()
+                            device.waitForIdle()
+                            device.launchSplitScreen()
+                            val snapshot =
+                                device.findObject(By.res(device.launcherPackageName, "snapshot"))
+                            snapshot.click()
+                            testAppBottom.openIME(device)
+                            device.pressBack()
+                            device.resizeSplitScreen(startRatio)
+                        }
+                    }
+                    teardown {
+                        eachRun {
+                            if (device.isInSplitScreen()) {
+                                device.exitSplitScreen()
+                            }
+                            device.pressHome()
+                            testAppTop.exit()
+                            testAppBottom.exit()
+                        }
+                        test {
+                            if (device.isInSplitScreen()) {
+                                device.exitSplitScreen()
+                            }
+                        }
+                    }
+                    transitions {
+                        device.resizeSplitScreen(stopRatio)
+                    }
+                    assertions {
+                        windowManagerTrace {
+                            navBarWindowIsAlwaysVisible()
+                            statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+                            all("topAppWindowIsAlwaysVisible", bugId = 156223549) {
+                                this.showsAppWindow(sSimpleActivity)
+                            }
+
+                            all("bottomAppWindowIsAlwaysVisible", bugId = 156223549) {
+                                this.showsAppWindow(sImeActivity)
+                            }
+                        }
+
+                        layersTrace {
+                            navBarLayerIsAlwaysVisible()
+                            statusBarLayerIsAlwaysVisible()
+                            noUncoveredRegions(configuration.endRotation)
+                            navBarLayerRotatesAndScales(configuration.endRotation)
+                            statusBarLayerRotatesScales(configuration.endRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry()
+
+                            all("topAppLayerIsAlwaysVisible") {
+                                this.showsLayer(sSimpleActivity)
+                            }
+
+                            all("bottomAppLayerIsAlwaysVisible") {
+                                this.showsLayer(sImeActivity)
+                            }
+
+                            all("dividerLayerIsAlwaysVisible") {
+                                this.showsLayer(DOCKED_STACK_DIVIDER)
+                            }
+
+                            start("appsStartingBounds", enabled = false) {
+                                val displayBounds = WindowUtils.displayBounds
+                                val entry = this.trace.entries.firstOrNull()
+                                    ?: throw IllegalStateException("Trace is empty")
+                                val dividerBounds =
+                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
+
+                                val topAppBounds = Region(0, 0, dividerBounds.right,
+                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
+                                val bottomAppBounds = Region(0,
+                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+                                    displayBounds.right,
+                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
+                                this.hasVisibleRegion("SimpleActivity", topAppBounds)
+                                    .and()
+                                    .hasVisibleRegion("ImeActivity", bottomAppBounds)
+                            }
+
+                            end("appsEndingBounds", enabled = false) {
+                                val displayBounds = WindowUtils.displayBounds
+                                val entry = this.trace.entries.lastOrNull()
+                                    ?: throw IllegalStateException("Trace is empty")
+                                val dividerBounds =
+                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
+
+                                val topAppBounds = Region(0, 0, dividerBounds.right,
+                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
+                                val bottomAppBounds = Region(0,
+                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+                                    displayBounds.right,
+                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
+
+                                this.hasVisibleRegion(sSimpleActivity, topAppBounds)
+                                    .and()
+                                    .hasVisibleRegion(sImeActivity, bottomAppBounds)
+                            }
+                        }
+
+                        eventLog {
+                            focusDoesNotChange()
+                        }
+                    }
+                }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
new file mode 100644
index 0000000..923f2a4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
@@ -0,0 +1,148 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateOneLaunchedAppTest(
+    rotationName: String,
+    rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+    private val splitScreenRotationSetup: FlickerBuilder
+        get() = FlickerBuilder(instrumentation).apply {
+            val testSetupRotation = "testSetupRotation"
+            withTestName {
+                testSetupRotation
+            }
+            setup {
+                test {
+                    uiDevice.wakeUpAndGoToHomeScreen()
+                    uiDevice.openQuickStepAndClearRecentAppsFromOverview()
+                }
+            }
+            teardown {
+                eachRun {
+                    if (uiDevice.isInSplitScreen()) {
+                        uiDevice.exitSplitScreen()
+                    }
+                    setRotation(Surface.ROTATION_0)
+                    splitScreenApp.exit()
+                    secondaryApp.exit()
+                }
+            }
+        }
+
+    @Test
+    fun testRotateInSplitScreenMode() {
+        val testTag = "testEnterSplitScreen_launchToSide"
+        runWithFlicker(splitScreenRotationSetup) {
+            withTestName { testTag }
+            repeat {
+                SplitScreenHelper.TEST_REPETITIONS
+            }
+            transitions {
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+                setRotation(rotation)
+            }
+            assertions {
+                layersTrace {
+                    navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+                    statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+                    dockedStackDividerIsVisible()
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testRotateAndEnterSplitScreenMode() {
+        val testTag = "testRotateAndEnterSplitScreenMode"
+        runWithFlicker(splitScreenRotationSetup) {
+            withTestName { testTag }
+            repeat {
+                SplitScreenHelper.TEST_REPETITIONS
+            }
+            transitions {
+                splitScreenApp.launchViaIntent()
+                setRotation(rotation)
+                uiDevice.launchSplitScreen()
+            }
+            assertions {
+                layersTrace {
+                    navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+                    statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+                    dockedStackDividerIsVisible()
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
new file mode 100644
index 0000000..4578f68
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
@@ -0,0 +1,159 @@
+/*
+ * 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.flicker.legacysplitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateTwoLaunchedAppTest(
+    rotationName: String,
+    rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+    private val splitScreenRotationSetup: FlickerBuilder
+        get() = FlickerBuilder(instrumentation).apply {
+            val testSetupRotation = "testSetupRotation"
+            withTestName {
+                testSetupRotation
+            }
+            setup {
+                test {
+                    uiDevice.wakeUpAndGoToHomeScreen()
+                    uiDevice.openQuickStepAndClearRecentAppsFromOverview()
+                }
+            }
+            teardown {
+                eachRun {
+                    if (uiDevice.isInSplitScreen()) {
+                        uiDevice.exitSplitScreen()
+                    }
+                    setRotation(Surface.ROTATION_0)
+                    splitScreenApp.exit()
+                    secondaryApp.exit()
+                }
+            }
+        }
+
+    @Test
+    fun testRotateInSplitScreenMode() {
+        val testTag = "testRotateInSplitScreenMode"
+        runWithFlicker(splitScreenRotationSetup) {
+            withTestName { testTag }
+            repeat {
+                SplitScreenHelper.TEST_REPETITIONS
+            }
+            transitions {
+                secondaryApp.launchViaIntent()
+                splitScreenApp.launchViaIntent()
+                uiDevice.launchSplitScreen()
+                splitScreenApp.reopenAppFromOverview()
+                setRotation(rotation)
+            }
+            assertions {
+                layersTrace {
+                    navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+                    statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+                    dockedStackDividerIsVisible()
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                    dockedStackSecondaryBoundsIsVisible(
+                            rotation, secondaryApp.defaultWindowName, 169271943)
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                                .and().showsAppWindow(secondaryApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testRotateAndEnterSplitScreenMode() {
+        val testTag = "testRotateAndEnterSplitScreenMode"
+        runWithFlicker(splitScreenRotationSetup) {
+            withTestName { testTag }
+            repeat {
+                SplitScreenHelper.TEST_REPETITIONS
+            }
+            transitions {
+                secondaryApp.launchViaIntent()
+                splitScreenApp.launchViaIntent()
+                setRotation(rotation)
+                uiDevice.launchSplitScreen()
+                splitScreenApp.reopenAppFromOverview()
+            }
+            assertions {
+                layersTrace {
+                    navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+                    statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+                    dockedStackDividerIsVisible()
+                    dockedStackPrimaryBoundsIsVisible(
+                            rotation, splitScreenApp.defaultWindowName, 169271943)
+                    dockedStackSecondaryBoundsIsVisible(
+                            rotation, secondaryApp.defaultWindowName, 169271943)
+                }
+                windowManagerTrace {
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                    end {
+                        showsAppWindow(splitScreenApp.defaultWindowName)
+                                .and().showsAppWindow(secondaryApp.defaultWindowName)
+                    }
+                }
+            }
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
new file mode 100644
index 0000000..a536ec8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.legacysplitscreen
+
+import android.support.test.launcherhelper.LauncherStrategyFactory
+import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
+import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
+import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import com.android.wm.shell.flicker.testapp.Components
+
+abstract class SplitScreenTestBase(
+    rotationName: String,
+    rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+    protected val splitScreenApp = SplitScreenHelper(instrumentation,
+            TEST_APP_SPLITSCREEN_PRIMARY_LABEL,
+            Components.SplitScreenActivity())
+    protected val secondaryApp = SplitScreenHelper(instrumentation,
+            TEST_APP_SPLITSCREEN_SECONDARY_LABEL,
+            Components.SplitScreenSecondaryActivity())
+    protected val nonResizeableApp = SplitScreenHelper(instrumentation,
+            TEST_APP_NONRESIZEABLE_LABEL,
+            Components.NonResizeableActivity())
+    protected val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+            .launcherStrategy.supportedLauncherPackage
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 6b44ce6..866d654 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -25,8 +25,10 @@
 import com.android.server.wm.flicker.helpers.closePipWindow
 import com.android.server.wm.flicker.helpers.hasPipWindow
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import com.android.wm.shell.flicker.IME_WINDOW_NAME
 import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import com.android.wm.shell.flicker.testapp.Components
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -46,6 +48,8 @@
     rotation: Int
 ) : PipTestBase(rotationName, rotation) {
     private val keyboardApp = ImeAppHelper(instrumentation)
+    private val keyboardComponent = Components.ImeActivity().componentName
+    private val helper = WindowManagerStateHelper()
 
     private val keyboardScenario: FlickerBuilder
         get() = FlickerBuilder(instrumentation).apply {
@@ -64,6 +68,8 @@
                     // UiAutomator doesn't support to launch the multiple Activities in a task.
                     // So use launchActivity() for the Keyboard Activity.
                     keyboardApp.launchViaIntent()
+                    helper.waitForAppTransitionIdle()
+                    helper.waitForFullScreenApp(keyboardComponent)
                 }
             }
             teardown {
@@ -88,9 +94,11 @@
             transitions {
                 // open the soft keyboard
                 keyboardApp.openIME()
+                helper.waitImeWindowShown()
 
                 // then close it again
                 keyboardApp.closeIME()
+                helper.waitImeWindowGone()
             }
             assertions {
                 windowManagerTrace {
@@ -112,11 +120,13 @@
             transitions {
                 // open the soft keyboard
                 keyboardApp.openIME()
+                helper.waitImeWindowShown()
             }
             teardown {
                 eachRun {
                     // close the keyboard
                     keyboardApp.closeIME()
+                    helper.waitImeWindowGone()
                 }
             }
             assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
new file mode 100644
index 0000000..9eae179
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -0,0 +1,127 @@
+/*
+ * 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.flicker.pip
+
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.runFlicker
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import com.android.wm.shell.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip with split-screen.
+ * To run this test: `atest WMShellFlickerTests:PipLegacySplitScreenTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 161435597)
+class PipLegacySplitScreenTest(
+    rotationName: String,
+    rotation: Int
+) : AppTestBase(rotationName, rotation) {
+    private val pipApp = PipAppHelper(instrumentation)
+    private val imeApp = ImeAppHelper(instrumentation)
+    private val testApp = FixedAppHelper(instrumentation)
+
+    @Test
+    fun testShowsPipLaunchingToSplitScreen() {
+        runFlicker(instrumentation) {
+            withTestName { "testShowsPipLaunchingToSplitScreen" }
+            repeat { TEST_REPETITIONS }
+            setup {
+                test {
+                    removeAllTasksButHome()
+                    device.wakeUpAndGoToHomeScreen()
+                    pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true"))
+                    waitForAnimationComplete()
+                }
+            }
+            transitions {
+                testApp.launchViaIntent()
+                device.launchSplitScreen()
+                imeApp.launchViaIntent()
+                waitForAnimationComplete()
+            }
+            teardown {
+                eachRun {
+                    imeApp.exit()
+                    if (device.isInSplitScreen()) {
+                        device.exitSplitScreen()
+                    }
+                    testApp.exit()
+                }
+                test {
+                    removeAllTasksButHome()
+                }
+            }
+            assertions {
+                val displayBounds = WindowUtils.getDisplayBounds(rotation)
+                windowManagerTrace {
+                    all("PIP window must remain inside visible bounds") {
+                        coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+                    }
+                    end("Both app windows should be visible") {
+                        showsAppWindow(testApp.defaultWindowName)
+                        showsAppWindow(imeApp.defaultWindowName)
+                        noWindowsOverlap(testApp.defaultWindowName, imeApp.defaultWindowName)
+                    }
+                    navBarWindowIsAlwaysVisible()
+                    statusBarWindowIsAlwaysVisible()
+                }
+                layersTrace {
+                    all("PIP layer must remain inside visible bounds") {
+                        coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
+                    }
+                    end("Both app layers should be visible") {
+                        coversAtMostRegion(displayBounds, testApp.defaultWindowName)
+                        coversAtMostRegion(displayBounds, imeApp.defaultWindowName)
+                    }
+                    navBarLayerIsAlwaysVisible()
+                    statusBarLayerIsAlwaysVisible()
+                }
+            }
+        }
+    }
+
+    companion object {
+        const val TEST_REPETITIONS = 2
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<Array<Any>> {
+            val supportedRotations = intArrayOf(Surface.ROTATION_0)
+            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+        }
+    }
+}
\ No newline at end of file
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/PipSplitScreenTest.kt
deleted file mode 100644
index f79b21f..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.pip
-
-import android.view.Surface
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.runFlicker
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.helpers.ImeAppHelper
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.wm.shell.flicker.helpers.PipAppHelper
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test Pip with split-screen.
- * To run this test: `atest WMShellFlickerTests:PipSplitScreenTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 161435597)
-class PipSplitScreenTest(
-    rotationName: String,
-    rotation: Int
-) : AppTestBase(rotationName, rotation) {
-    private val pipApp = PipAppHelper(instrumentation)
-    private val imeApp = ImeAppHelper(instrumentation)
-    private val testApp = FixedAppHelper(instrumentation)
-
-    @Test
-    fun testShowsPipLaunchingToSplitScreen() {
-        runFlicker(instrumentation) {
-            withTestName { "testShowsPipLaunchingToSplitScreen" }
-            repeat { TEST_REPETITIONS }
-            setup {
-                test {
-                    removeAllTasksButHome()
-                    device.wakeUpAndGoToHomeScreen()
-                    pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true"))
-                    waitForAnimationComplete()
-                }
-            }
-            transitions {
-                testApp.launchViaIntent()
-                device.launchSplitScreen()
-                imeApp.launchViaIntent()
-                waitForAnimationComplete()
-            }
-            teardown {
-                eachRun {
-                    imeApp.exit()
-                    if (device.isInSplitScreen()) {
-                        device.exitSplitScreen()
-                    }
-                    testApp.exit()
-                }
-                test {
-                    removeAllTasksButHome()
-                }
-            }
-            assertions {
-                val displayBounds = WindowUtils.getDisplayBounds(rotation)
-                windowManagerTrace {
-                    all("PIP window must remain inside visible bounds") {
-                        coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
-                    }
-                    end("Both app windows should be visible") {
-                        showsAppWindow(testApp.defaultWindowName)
-                        showsAppWindow(imeApp.defaultWindowName)
-                        noWindowsOverlap(testApp.defaultWindowName, imeApp.defaultWindowName)
-                    }
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
-                }
-                layersTrace {
-                    all("PIP layer must remain inside visible bounds") {
-                        coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
-                    }
-                    end("Both app layers should be visible") {
-                        coversAtMostRegion(displayBounds, testApp.defaultWindowName)
-                        coversAtMostRegion(displayBounds, imeApp.defaultWindowName)
-                    }
-                    navBarLayerIsAlwaysVisible()
-                    statusBarLayerIsAlwaysVisible()
-                }
-            }
-        }
-    }
-
-    companion object {
-        const val TEST_REPETITIONS = 2
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val supportedRotations = intArrayOf(Surface.ROTATION_0)
-            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
index 70425a3..49094e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
@@ -42,7 +42,7 @@
         testApp.launchViaIntent()
 
         // Set up ratio and enter Pip
-        testApp.clickButton(radioButtonId)
+        testApp.clickObject(radioButtonId)
         testApp.clickEnterPipButton()
 
         val actualRatio: Float = testApp.ui?.visibleBounds?.ratio
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
index 4cb6447..66efb5a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
@@ -59,17 +59,24 @@
 
     @Test
     fun pipMenu_correctPosition() {
-        val pipMenu = enterPip_openMenu_assertShown()
-
-        // Make sure it's fullscreen
-        assertTrue("Pip menu should be shown fullscreen", pipMenu.isFullscreen(uiDevice))
+        enterPip_openMenu_assertShown()
 
         // Make sure the PiP task is positioned where it should be.
         val activityBounds: Rect = testApp.ui?.visibleBounds
-                ?: error("Could not retrieve PiP Activity bounds")
+                ?: error("Could not retrieve Pip Activity bounds")
         assertTrue("Pip Activity is positioned correctly while Pip menu is shown",
                 pipBoundsWhileInMenu == activityBounds)
 
+        // Make sure the Pip Menu Actions are positioned correctly.
+        uiDevice.findTvPipMenuControls()?.visibleBounds?.run {
+            assertTrue("Pip Menu Actions should be positioned below the Activity in Pip",
+                top >= activityBounds.bottom)
+            assertTrue("Pip Menu Actions should be positioned central horizontally",
+                centerX() == uiDevice.displayWidth / 2)
+            assertTrue("Pip Menu Actions should be fully shown on the screen",
+                left >= 0 && right <= uiDevice.displayWidth && bottom <= uiDevice.displayHeight)
+        } ?: error("Could not retrieve Pip Menu Actions bounds")
+
         testApp.closePipWindow()
     }
 
@@ -100,11 +107,11 @@
         enterPip_openMenu_assertShown()
 
         // PiP menu should contain the Close button
-        val closeButton = uiDevice.findTvPipMenuCloseButton()
+        uiDevice.findTvPipMenuCloseButton()
                 ?: fail("\"Close PIP\" button should be shown in Pip menu")
 
         // Clicking on the Close button should close the app
-        closeButton.click()
+        uiDevice.clickTvPipMenuCloseButton()
         assertTrue("\"Close PIP\" button should close the PiP", testApp.waitUntilClosed())
     }
 
@@ -113,12 +120,12 @@
         enterPip_openMenu_assertShown()
 
         // PiP menu should contain the Fullscreen button
-        val fullscreenButton = uiDevice.findTvPipMenuFullscreenButton()
+        uiDevice.findTvPipMenuFullscreenButton()
                 ?: fail("\"Full screen\" button should be shown in Pip menu")
 
         // Clicking on the fullscreen button should return app to the fullscreen mode.
         // Click, wait for the app to go fullscreen
-        fullscreenButton.click()
+        uiDevice.clickTvPipMenuFullscreenButton()
         assertTrue("\"Full screen\" button should open the app fullscreen",
                 wait { testApp.ui?.isFullscreen(uiDevice) ?: false })
 
@@ -136,12 +143,12 @@
         assertFullscreenAndCloseButtonsAreShown()
 
         // PiP menu should contain the Pause button
-        val pauseButton = uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
+        uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
                 ?: fail("\"Pause\" button should be shown in Pip menu if there is an active " +
                         "playing media session.")
 
         // When we pause media, the button should change from Pause to Play
-        pauseButton.click()
+        uiDevice.clickTvPipMenuElementWithDescription(pauseButtonDescription)
 
         assertFullscreenAndCloseButtonsAreShown()
         // PiP menu should contain the Play button now
@@ -161,27 +168,26 @@
         // PiP menu should contain "No-Op", "Off" and "Clear" buttons...
         uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_NO_OP)
                 ?: fail("\"No-Op\" button should be shown in Pip menu")
-        val offButton = uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
+        uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
                 ?: fail("\"Off\" button should be shown in Pip menu")
         uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
                 ?: fail("\"Clear\" button should be shown in Pip menu")
         // ... and should also contain the "Full screen" and "Close" buttons.
         assertFullscreenAndCloseButtonsAreShown()
 
-        offButton.click()
+        uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
         // Invoking the "Off" action should replace it with the "On" action/button and should
         // remove the "No-Op" action/button. "Clear" action/button should remain in the menu ...
         uiDevice.waitForTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_ON)
                 ?: fail("\"On\" button should be shown in Pip for a corresponding custom action")
         assertNull("\"No-Op\" button should not be shown in Pip menu",
                 uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_NO_OP))
-        val clearButton =
-                uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
+        uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
                         ?: fail("\"Clear\" button should be shown in Pip menu")
         // ... as well as the "Full screen" and "Close" buttons.
         assertFullscreenAndCloseButtonsAreShown()
 
-        clearButton.click()
+        uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
         // Invoking the "Clear" action should remove all the custom actions and their corresponding
         // buttons, ...
         uiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(TEST_APP_PIP_MENU_ACTION_ON)?.also {
@@ -211,9 +217,8 @@
                 ?: fail("\"No-Op\" button should be shown in Pip menu")
         uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
                 ?: fail("\"Off\" button should be shown in Pip menu")
-        val clearButton =
-                uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
-                        ?: fail("\"Clear\" button should be shown in Pip menu")
+        uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
+                ?: fail("\"Clear\" button should be shown in Pip menu")
         // ... should also contain the "Full screen" and "Close" buttons, ...
         assertFullscreenAndCloseButtonsAreShown()
         // ... but should not contain media buttons.
@@ -222,7 +227,7 @@
         assertNull("\"Pause\" button should not be shown in menu when there are custom actions",
                 uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription))
 
-        clearButton.click()
+        uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
         // Invoking the "Clear" action should remove all the custom actions, which should bring up
         // media buttons...
         uiDevice.waitForTvPipMenuElementWithDescription(pauseButtonDescription)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
index 0732794..587b551 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
@@ -18,6 +18,7 @@
 
 import android.view.KeyEvent
 import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
 import androidx.test.uiautomator.UiDevice
 import androidx.test.uiautomator.UiObject2
 import androidx.test.uiautomator.Until
@@ -25,11 +26,18 @@
 
 /** Id of the root view in the com.android.wm.shell.pip.tv.PipMenuActivity */
 private const val TV_PIP_MENU_ROOT_ID = "tv_pip_menu"
+private const val TV_PIP_MENU_CONTROLS_ID = "pip_controls"
 private const val TV_PIP_MENU_CLOSE_BUTTON_ID = "close_button"
 private const val TV_PIP_MENU_FULLSCREEN_BUTTON_ID = "full_button"
 
+private const val FOCUS_ATTEMPTS = 10
 private const val WAIT_TIME_MS = 3_000L
 
+private val TV_PIP_MENU_CLOSE_BUTTON_SELECTOR =
+        By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID)
+private val TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR =
+        By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID)
+
 private val tvPipMenuSelector = By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
 
 fun UiDevice.pressWindowKey() = pressKeyCode(KeyEvent.KEYCODE_WINDOW)
@@ -39,16 +47,35 @@
 
 fun UiDevice.waitForTvPipMenuToClose(): Boolean = wait(Until.gone(tvPipMenuSelector), WAIT_TIME_MS)
 
-fun UiDevice.findTvPipMenuCloseButton(): UiObject2? = findObject(
-        By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID))
+fun UiDevice.findTvPipMenuControls(): UiObject2? =
+        findObject(tvPipMenuSelector)
+                ?.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CONTROLS_ID))
 
-fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? = findObject(
-        By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID))
+fun UiDevice.findTvPipMenuCloseButton(): UiObject2? =
+        findObject(tvPipMenuSelector)?.findObject(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR)
 
-fun UiDevice.findTvPipMenuElementWithDescription(desc: String): UiObject2? {
-    val buttonSelector = By.desc(desc)
-    val menuWithButtonSelector = By.copy(tvPipMenuSelector).hasDescendant(buttonSelector)
-    return findObject(menuWithButtonSelector)?.findObject(buttonSelector)
+fun UiDevice.clickTvPipMenuCloseButton() {
+    focusOnObjectInTvPipMenu(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR) ||
+            error("Could not focus on the Close button")
+    pressDPadCenter()
+}
+
+fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? =
+        findObject(tvPipMenuSelector)?.findObject(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR)
+
+fun UiDevice.clickTvPipMenuFullscreenButton() {
+    focusOnObjectInTvPipMenu(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR) ||
+            error("Could not focus on the Fullscreen button")
+    pressDPadCenter()
+}
+
+fun UiDevice.findTvPipMenuElementWithDescription(desc: String): UiObject2? =
+        findObject(tvPipMenuSelector)?.findObject(By.desc(desc).pkg(SYSTEM_UI_PACKAGE_NAME))
+
+fun UiDevice.clickTvPipMenuElementWithDescription(desc: String) {
+    focusOnObjectInTvPipMenu(By.desc(desc).pkg(SYSTEM_UI_PACKAGE_NAME)) ||
+            error("Could not focus on the Pip menu object with \"$desc\" description")
+    pressDPadCenter()
 }
 
 fun UiDevice.waitForTvPipMenuElementWithDescription(desc: String): UiObject2? {
@@ -63,4 +90,33 @@
 
 fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean = visibleBounds.run {
     height() == uiDevice.displayHeight && width() == uiDevice.displayWidth
+}
+
+val UiObject2.isFocusedOrHasFocusedChild: Boolean
+    get() = isFocused || findObject(By.focused(true)) != null
+
+fun UiDevice.closeTvPipWindow() {
+    // Check if Pip menu is Open. If it's not, open it.
+    if (findObject(tvPipMenuSelector) == null) {
+        pressWindowKey()
+        waitForTvPipMenu() ?: error("Could not open Pip menu")
+    }
+
+    clickTvPipMenuCloseButton()
+    waitForTvPipMenuToClose()
+}
+
+private fun UiDevice.focusOnObjectInTvPipMenu(objectSelector: BySelector): Boolean {
+    repeat(FOCUS_ATTEMPTS) {
+        val menu = findObject(tvPipMenuSelector) ?: error("Pip Menu is now shown")
+        val objectToFocus = menu.findObject(objectSelector)
+                .apply { if (isFocusedOrHasFocusedChild) return true }
+                ?: error("The object we try to focus on is gone.")
+        val currentlyFocused = menu.findObject(By.focused(true))
+                ?: error("Pip menu does not contain a focused element")
+        if (objectToFocus.visibleCenter.x < currentlyFocused.visibleCenter.x)
+            pressDPadLeft() else pressDPadRight()
+        waitForIdle()
+    }
+    return false
 }
\ No newline at end of file
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/splitscreen/EnterSplitScreenTest.kt
deleted file mode 100644
index 5570a56..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import android.platform.test.annotations.Presubmit
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.dsl.runWithFlicker
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.dockedStackDividerIsVisible
-import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test SplitScreen launch.
- * To run this test: `atest WMShellFlickerTests:EnterSplitScreenTest`
- */
-@Presubmit
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterSplitScreenTest(
-    rotationName: String,
-    rotation: Int
-) : SplitScreenTestBase(rotationName, rotation) {
-    private val splitScreenSetup: FlickerBuilder
-        get() = FlickerBuilder(instrumentation).apply {
-            val testLaunchActivity = "launch_splitScreen_test_activity"
-            withTestName {
-                testLaunchActivity
-            }
-            setup {
-                eachRun {
-                    uiDevice.wakeUpAndGoToHomeScreen()
-                    splitScreenApp.open()
-                    uiDevice.pressHome()
-                }
-            }
-            teardown {
-                eachRun {
-                    splitScreenApp.exit()
-                    secondaryApp.exit()
-                }
-            }
-            assertions {
-                layersTrace {
-                    navBarLayerIsAlwaysVisible()
-                    statusBarLayerIsAlwaysVisible()
-                }
-                windowManagerTrace {
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
-                }
-            }
-        }
-
-    @Test
-    fun testEnterSplitScreen_dockActivity() {
-        val testTag = "testEnterSplitScreen_dockActivity"
-        runWithFlicker(splitScreenSetup) {
-            withTestName { testTag }
-            repeat {
-                TEST_REPETITIONS
-            }
-            transitions {
-                uiDevice.launchSplitScreen()
-            }
-            assertions {
-                layersTrace {
-                    dockedStackDividerIsVisible()
-                    end("appsEndingBounds", enabled = false) {
-                        val entry = this.trace.entries.firstOrNull()
-                                ?: throw IllegalStateException("Trace is empty")
-                        this.hasVisibleRegion(splitScreenApp.defaultWindowName,
-                                splitScreenApp.getPrimaryBounds(
-                                        entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
-                    }
-                }
-                windowManagerTrace {
-                    end {
-                        showsAppWindow(splitScreenApp.defaultWindowName)
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun testEnterSplitScreen_launchToSide() {
-        val testTag = "testEnterSplitScreen_launchToSide"
-        runWithFlicker(splitScreenSetup) {
-            withTestName { testTag }
-            repeat {
-                TEST_REPETITIONS
-            }
-            transitions {
-                secondaryApp.open()
-                uiDevice.pressHome()
-                splitScreenApp.open()
-                uiDevice.pressHome()
-                uiDevice.launchSplitScreen()
-                splitScreenApp.reopenAppFromOverview()
-            }
-            assertions {
-                layersTrace {
-                    dockedStackDividerIsVisible()
-                    end("appsEndingBounds", enabled = false) {
-                        val entry = this.trace.entries.firstOrNull()
-                                ?: throw IllegalStateException("Trace is empty")
-                        this.hasVisibleRegion(splitScreenApp.defaultWindowName,
-                                splitScreenApp.getPrimaryBounds(
-                                        entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
-                                .and()
-                                .hasVisibleRegion(secondaryApp.defaultWindowName,
-                                        splitScreenApp.getSecondaryBounds(
-                                        entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
-                    }
-                }
-                windowManagerTrace {
-                    end {
-                        showsAppWindow(splitScreenApp.defaultWindowName)
-                                .and().showsAppWindow(secondaryApp.defaultWindowName)
-                    }
-                }
-            }
-        }
-    }
-
-    companion object {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val supportedRotations = intArrayOf(Surface.ROTATION_0)
-            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
-        }
-    }
-}
\ No newline at end of file
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/splitscreen/ExitSplitScreenTest.kt
deleted file mode 100644
index 7c47d1f..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import android.platform.test.annotations.Presubmit
-import android.util.Rational
-import android.view.Surface
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.dsl.runWithFlicker
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.resizeSplitScreen
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
-import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test exit SplitScreen mode.
- * To run this test: `atest WMShellFlickerTests:ExitSplitScreenTest`
- */
-@Presubmit
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitSplitScreenTest(
-    rotationName: String,
-    rotation: Int
-) : SplitScreenTestBase(rotationName, rotation) {
-    private val splitScreenSetup: FlickerBuilder
-        get() = FlickerBuilder(instrumentation).apply {
-            val testLaunchActivity = "launch_splitScreen_test_activity"
-            withTestName {
-                testLaunchActivity
-            }
-            setup {
-                eachRun {
-                    uiDevice.wakeUpAndGoToHomeScreen()
-                    secondaryApp.open()
-                    uiDevice.pressHome()
-                    splitScreenApp.open()
-                    uiDevice.pressHome()
-                    uiDevice.launchSplitScreen()
-                }
-            }
-            teardown {
-                eachRun {
-                    splitScreenApp.exit()
-                    secondaryApp.exit()
-                }
-            }
-        }
-
-    @Test
-    fun testEnterSplitScreen_exitPrimarySplitScreenMode() {
-        val testTag = "testEnterSplitScreen_exitPrimarySplitScreenMode"
-        runWithFlicker(splitScreenSetup) {
-            withTestName { testTag }
-            repeat {
-                TEST_REPETITIONS
-            }
-            transitions {
-                uiDevice.exitSplitScreen()
-            }
-            assertions {
-                layersTrace {
-                    dockedStackDividerIsInvisible()
-                }
-                windowManagerTrace {
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
-                    end {
-                        hidesAppWindow(splitScreenApp.defaultWindowName)
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    @FlakyTest(bugId = 172811376)
-    fun testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen() {
-        val testTag = "testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen"
-        runWithFlicker(splitScreenSetup) {
-            withTestName { testTag }
-            repeat {
-                TEST_REPETITIONS
-            }
-            transitions {
-                splitScreenApp.reopenAppFromOverview()
-                uiDevice.resizeSplitScreen(startRatio)
-            }
-            assertions {
-                layersTrace {
-                    dockedStackDividerIsInvisible()
-                }
-                windowManagerTrace {
-                    navBarWindowIsAlwaysVisible()
-                    statusBarWindowIsAlwaysVisible()
-                    end {
-                        showsAppWindow(splitScreenApp.defaultWindowName)
-                    }
-                }
-            }
-        }
-    }
-
-    companion object {
-        private val startRatio = Rational(1, 3)
-
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val supportedRotations = intArrayOf(Surface.ROTATION_0)
-            return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
-        }
-    }
-}
\ No newline at end of file
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/splitscreen/OpenAppToSplitScreenTest.kt
deleted file mode 100644
index c85561d..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import android.platform.test.annotations.Presubmit
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerRotatesAndScales
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:OpenAppToSplitScreenTest`
- */
-@Presubmit
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppToSplitScreenTest(
-    testName: String,
-    flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
-    companion object {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = StandardAppHelper(instrumentation,
-                "com.android.wm.shell.flicker.testapp", "SimpleApp")
-
-            // b/161435597 causes the test not to work on 90 degrees
-            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
-                .buildTest { configuration ->
-                    withTestName {
-                        buildTestTag("appToSplitScreen", testApp, configuration)
-                    }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.open()
-                            this.setRotation(configuration.endRotation)
-                        }
-                    }
-                    teardown {
-                        eachRun {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                        }
-                        test {
-                            testApp.exit()
-                        }
-                    }
-                    transitions {
-                        device.launchSplitScreen()
-                    }
-                    assertions {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible()
-                            noUncoveredRegions(configuration.endRotation, enabled = false)
-                            navBarLayerRotatesAndScales(configuration.endRotation,
-                                bugId = 140855415)
-                            statusBarLayerRotatesScales(configuration.endRotation)
-
-                            all("dividerLayerBecomesVisible") {
-                                this.hidesLayer(DOCKED_STACK_DIVIDER)
-                                    .then()
-                                    .showsLayer(DOCKED_STACK_DIVIDER)
-                            }
-                        }
-
-                        eventLog {
-                            focusChanges(testApp.`package`,
-                                "recents_animation_input_consumer", "NexusLauncherActivity",
-                                bugId = 151179149)
-                        }
-                    }
-                }
-        }
-    }
-}
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/splitscreen/ResizeSplitScreenTest.kt
deleted file mode 100644
index 7c83846..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import android.graphics.Region
-import android.util.Rational
-import android.view.Surface
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.uiautomator.By
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.focusDoesNotChange
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.resizeSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerRotatesAndScales
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test split screen resizing window transitions.
- * To run this test: `atest WMShellFlickerTests:ResizeSplitScreenTest`
- *
- * Currently it runs only in 0 degrees because of b/156100803
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 159096424)
-class ResizeSplitScreenTest(
-    testName: String,
-    flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
-    companion object {
-        private const val sSimpleActivity = "SimpleActivity"
-        private const val sImeActivity = "ImeActivity"
-        private val startRatio = Rational(1, 3)
-        private val stopRatio = Rational(2, 3)
-
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testAppTop = StandardAppHelper(instrumentation,
-                "com.android.wm.shell.flicker.testapp", "SimpleApp")
-            val testAppBottom = ImeAppHelper(instrumentation)
-
-            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
-                .buildTest { configuration ->
-                    withTestName {
-                        val description = (startRatio.toString().replace("/", "-") + "_to_" +
-                            stopRatio.toString().replace("/", "-"))
-                        buildTestTag("resizeSplitScreen", testAppTop.launcherName,
-                            configuration.startRotation, configuration.endRotation,
-                            testAppBottom.launcherName, description)
-                    }
-                    repeat { configuration.repetitions }
-                    setup {
-                        eachRun {
-                            device.wakeUpAndGoToHomeScreen()
-                            this.setRotation(configuration.startRotation)
-                            this.launcherStrategy.clearRecentAppsFromOverview()
-                            testAppBottom.open()
-                            device.pressHome()
-                            testAppTop.open()
-                            device.waitForIdle()
-                            device.launchSplitScreen()
-                            val snapshot =
-                                device.findObject(By.res(device.launcherPackageName, "snapshot"))
-                            snapshot.click()
-                            testAppBottom.openIME(device)
-                            device.pressBack()
-                            device.resizeSplitScreen(startRatio)
-                        }
-                    }
-                    teardown {
-                        eachRun {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                            device.pressHome()
-                            testAppTop.exit()
-                            testAppBottom.exit()
-                        }
-                        test {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                        }
-                    }
-                    transitions {
-                        device.resizeSplitScreen(stopRatio)
-                    }
-                    assertions {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-
-                            all("topAppWindowIsAlwaysVisible", bugId = 156223549) {
-                                this.showsAppWindow(sSimpleActivity)
-                            }
-
-                            all("bottomAppWindowIsAlwaysVisible", bugId = 156223549) {
-                                this.showsAppWindow(sImeActivity)
-                            }
-                        }
-
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible()
-                            statusBarLayerIsAlwaysVisible()
-                            noUncoveredRegions(configuration.endRotation)
-                            navBarLayerRotatesAndScales(configuration.endRotation)
-                            statusBarLayerRotatesScales(configuration.endRotation)
-
-                            all("topAppLayerIsAlwaysVisible") {
-                                this.showsLayer(sSimpleActivity)
-                            }
-
-                            all("bottomAppLayerIsAlwaysVisible") {
-                                this.showsLayer(sImeActivity)
-                            }
-
-                            all("dividerLayerIsAlwaysVisible") {
-                                this.showsLayer(DOCKED_STACK_DIVIDER)
-                            }
-
-                            start("appsStartingBounds", enabled = false) {
-                                val displayBounds = WindowUtils.displayBounds
-                                val entry = this.trace.entries.firstOrNull()
-                                    ?: throw IllegalStateException("Trace is empty")
-                                val dividerBounds =
-                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
-
-                                val topAppBounds = Region(0, 0, dividerBounds.right,
-                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
-                                val bottomAppBounds = Region(0,
-                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
-                                    displayBounds.right,
-                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
-                                this.hasVisibleRegion("SimpleActivity", topAppBounds)
-                                    .and()
-                                    .hasVisibleRegion("ImeActivity", bottomAppBounds)
-                            }
-
-                            end("appsEndingBounds", enabled = false) {
-                                val displayBounds = WindowUtils.displayBounds
-                                val entry = this.trace.entries.lastOrNull()
-                                    ?: throw IllegalStateException("Trace is empty")
-                                val dividerBounds =
-                                    entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
-
-                                val topAppBounds = Region(0, 0, dividerBounds.right,
-                                    dividerBounds.top + WindowUtils.dockedStackDividerInset)
-                                val bottomAppBounds = Region(0,
-                                    dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
-                                    displayBounds.right,
-                                    displayBounds.bottom - WindowUtils.navigationBarHeight)
-
-                                this.hasVisibleRegion(sSimpleActivity, topAppBounds)
-                                    .and()
-                                    .hasVisibleRegion(sImeActivity, bottomAppBounds)
-                            }
-                        }
-
-                        eventLog {
-                            focusDoesNotChange()
-                        }
-                    }
-                }
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
deleted file mode 100644
index d2371bd..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateOneLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateOneLaunchedAppTest(
-    testName: String,
-    flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
-    companion object {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = StandardAppHelper(instrumentation,
-                    "com.android.wm.shell.flicker.testapp", "SimpleApp")
-
-            return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
-                    .buildTest { configuration ->
-                        withTestName {
-                            buildTestTag("splitScreenRotateOneApp", testApp, configuration)
-                        }
-                        repeat { configuration.repetitions }
-                        setup {
-                            test {
-                                device.wakeUpAndGoToHomeScreen()
-                                testApp.open()
-                                device.launchSplitScreen()
-                                device.waitForIdle()
-                            }
-                            eachRun {
-                                this.setRotation(configuration.startRotation)
-                            }
-                        }
-                        teardown {
-                            eachRun {
-                                setRotation(Surface.ROTATION_0)
-                            }
-                            test {
-                                testApp.exit()
-                                if (device.isInSplitScreen()) {
-                                    device.exitSplitScreen()
-                                }
-                            }
-                        }
-                        transitions {
-                            this.setRotation(configuration.endRotation)
-                        }
-                    }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
deleted file mode 100644
index 6734642..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateTwoLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateTwoLaunchedAppTest(
-    testName: String,
-    flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
-    companion object {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = StandardAppHelper(instrumentation,
-                    "com.android.wm.shell.flicker.testapp", "SimpleApp")
-            val secondaryApp = StandardAppHelper(instrumentation,
-                    "com.android.wm.shell.flicker.testapp",
-                    "SplitScreenSecondaryApp")
-
-            return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
-                    .buildTest { configuration ->
-                        withTestName {
-                            buildTestTag("splitScreenRotateTwoApps", testApp, configuration)
-                        }
-                        repeat { configuration.repetitions }
-                        setup {
-                            test {
-                                device.wakeUpAndGoToHomeScreen()
-                                testApp.open()
-                                device.pressHome()
-                                secondaryApp.open()
-                                device.pressHome()
-                                device.launchSplitScreen()
-                                device.reopenAppFromOverview()
-                                device.waitForIdle()
-                            }
-                            eachRun {
-                                this.setRotation(configuration.startRotation)
-                            }
-                        }
-                        teardown {
-                            eachRun {
-                                setRotation(Surface.ROTATION_0)
-                            }
-                            test {
-                                testApp.exit()
-                                secondaryApp.exit()
-                                if (device.isInSplitScreen()) {
-                                    device.exitSplitScreen()
-                                }
-                            }
-                        }
-                        transitions {
-                            this.setRotation(configuration.endRotation)
-                        }
-                    }
-        }
-    }
-}
\ No newline at end of file
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/splitscreen/SplitScreenTestBase.kt
deleted file mode 100644
index a3440df..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import com.android.wm.shell.flicker.NonRotationTestBase
-import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
-import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL
-import com.android.wm.shell.flicker.helpers.SplitScreenHelper
-import com.android.wm.shell.flicker.testapp.Components
-
-abstract class SplitScreenTestBase(
-    rotationName: String,
-    rotation: Int
-) : NonRotationTestBase(rotationName, rotation) {
-    protected val splitScreenApp = SplitScreenHelper(instrumentation,
-            TEST_APP_SPLITSCREEN_PRIMARY_LABEL,
-            Components.SplitScreenActivity())
-    protected val secondaryApp = SplitScreenHelper(instrumentation,
-            TEST_APP_SPLITSCREEN_SECONDARY_LABEL,
-            Components.SplitScreenSecondaryActivity())
-}
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/splitscreen/SplitScreenToLauncherTest.kt
deleted file mode 100644
index 00979fa..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import android.platform.test.annotations.Presubmit
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.focusDoesNotChange
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerRotatesAndScales
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenToLauncherTest`
- */
-@Presubmit
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SplitScreenToLauncherTest(
-    testName: String,
-    flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
-    companion object {
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): Collection<Array<Any>> {
-            val instrumentation = InstrumentationRegistry.getInstrumentation()
-            val testApp = StandardAppHelper(instrumentation,
-                "com.android.wm.shell.flicker.testapp", "SimpleApp")
-
-            // b/161435597 causes the test not to work on 90 degrees
-            return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
-                .buildTest { configuration ->
-                    withTestName {
-                        buildTestTag("splitScreenToLauncher", testApp, configuration)
-                    }
-                    repeat { configuration.repetitions }
-                    setup {
-                        test {
-                            device.wakeUpAndGoToHomeScreen()
-                        }
-                        eachRun {
-                            testApp.open()
-                            this.setRotation(configuration.endRotation)
-                            device.launchSplitScreen()
-                            device.waitForIdle()
-                        }
-                    }
-                    teardown {
-                        eachRun {
-                            testApp.exit()
-                        }
-                        test {
-                            if (device.isInSplitScreen()) {
-                                device.exitSplitScreen()
-                            }
-                        }
-                    }
-                    transitions {
-                        device.exitSplitScreen()
-                    }
-                    assertions {
-                        windowManagerTrace {
-                            navBarWindowIsAlwaysVisible()
-                            statusBarWindowIsAlwaysVisible()
-                        }
-
-                        layersTrace {
-                            navBarLayerIsAlwaysVisible()
-                            statusBarLayerIsAlwaysVisible()
-                            noUncoveredRegions(configuration.endRotation)
-                            navBarLayerRotatesAndScales(configuration.endRotation)
-                            statusBarLayerRotatesScales(configuration.endRotation)
-
-                            // b/161435597 causes the test not to work on 90 degrees
-                            all("dividerLayerBecomesInvisible") {
-                                this.showsLayer(DOCKED_STACK_DIVIDER)
-                                    .then()
-                                    .hidesLayer(DOCKED_STACK_DIVIDER)
-                            }
-
-                            all("appLayerBecomesInvisible") {
-                                this.showsLayer(testApp.getPackage())
-                                    .then()
-                                    .hidesLayer(testApp.getPackage())
-                            }
-                        }
-
-                        eventLog {
-                            focusDoesNotChange(bugId = 151179149)
-                        }
-                    }
-                }
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
index a583b72..28ed343 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -86,6 +86,17 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".NonResizeableActivity"
+                  android:resizeableActivity="false"
+                  android:taskAffinity="com.android.wm.shell.flicker.testapp.NonResizeableActivity"
+                  android:label="NonResizeableApp"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
         <activity android:name=".SimpleActivity"
                   android:taskAffinity="com.android.wm.shell.flicker.testapp.SimpleActivity"
                   android:label="SimpleApp"
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
new file mode 100644
index 0000000..45d5917
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="@android:color/holo_orange_light">
+
+    <TextView
+        android:id="@+id/NonResizeableTest"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:gravity="center_vertical|center_horizontal"
+        android:text="NonResizeableActivity"
+        android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+</LinearLayout>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
index e5d2f82..909b77c 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -21,6 +21,12 @@
     android:orientation="vertical"
     android:background="@android:color/holo_blue_bright">
 
+    <!-- All the buttons (and other clickable elements) should be arranged in a way so that it is
+         possible to "cycle" over all them by clicking on the D-Pad DOWN button. The way we do it
+         here is by arranging them this vertical LL and by relying on the nextFocusDown attribute
+         where things are arranged differently and to circle back up to the top once we reach the
+         bottom. -->
+
     <Button
         android:id="@+id/enter_pip"
         android:layout_width="wrap_content"
@@ -87,12 +93,14 @@
             android:id="@+id/media_session_start"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:nextFocusDown="@id/media_session_stop"
             android:text="Start"/>
 
         <Button
             android:id="@+id/media_session_stop"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:nextFocusDown="@id/enter_pip"
             android:text="Stop"/>
 
     </LinearLayout>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
index 8e9b4cb..f729ea5 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
@@ -38,6 +38,13 @@
         }
     }
 
+    public static class NonResizeableActivity extends ComponentsInfo {
+        @Override
+        public String getActivityName() {
+            return NonResizeableActivity.class.getSimpleName();
+        }
+    }
+
     public static class PipActivity extends ComponentsInfo {
         // Intent action that this activity dynamically registers to enter picture-in-picture
         public static final String ACTION_ENTER_PIP = PACKAGE_NAME + ".PipActivity.ENTER_PIP";
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java
new file mode 100644
index 0000000..24275e0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java
@@ -0,0 +1,29 @@
+/*
+ * 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.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class NonResizeableActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.activity_non_resizeable);
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index fdf4d31..862776e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -16,18 +16,14 @@
 
 package com.android.wm.shell;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX;
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -38,7 +34,6 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
-import android.graphics.Rect;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -47,7 +42,6 @@
 import android.window.ITaskOrganizerController;
 import android.window.TaskAppearedInfo;
 
-import androidx.annotation.Nullable;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
@@ -108,8 +102,7 @@
             doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList())
                     .when(mTaskOrganizerController).registerTaskOrganizer(any());
         } catch (RemoteException e) {}
-        mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mSyncTransactionQueue,
-                mTransactionPool, mTestExecutor, mTestExecutor, mContext));
+        mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mTestExecutor, mContext));
     }
 
     @Test
@@ -264,28 +257,6 @@
         assertTrue(mwListener.appeared.contains(task2));
     }
 
-    @Test
-    public void testTaskInfoToTaskListenerType_whenLetterboxBoundsPassed_returnsLetterboxType() {
-        RunningTaskInfo taskInfo = createTaskInfo(
-                /* taskId */ 1,
-                WINDOWING_MODE_FULLSCREEN,
-                /* letterboxActivityBounds */ new Rect(1, 1, 1, 1));
-
-        assertEquals(
-                ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo),
-                TASK_LISTENER_TYPE_LETTERBOX);
-    }
-
-    @Test
-    public void testTaskInfoToTaskListenerType_whenLetterboxBoundsIsNull_returnsFullscreenType() {
-        RunningTaskInfo taskInfo = createTaskInfo(
-                /* taskId */ 1, WINDOWING_MODE_FULLSCREEN, /* letterboxActivityBounds */ null);
-
-        assertEquals(
-                ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo),
-                TASK_LISTENER_TYPE_FULLSCREEN);
-    }
-
     private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
         taskInfo.taskId = taskId;
@@ -293,12 +264,4 @@
         return taskInfo;
     }
 
-    private static RunningTaskInfo createTaskInfo(
-                int taskId, int windowingMode, @Nullable Rect letterboxActivityBounds) {
-        RunningTaskInfo taskInfo = new RunningTaskInfo();
-        taskInfo.taskId = taskId;
-        taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
-        taskInfo.letterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds);
-        return taskInfo;
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index 34f772f..01b5204 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -96,8 +97,8 @@
             return null;
         }).when(mExecutor).execute(any());
 
+        when(mOrganizer.getExecutor()).thenReturn(mExecutor);
         mTaskView = new TaskView(mContext, mOrganizer);
-        mTaskView.setExecutor(mExecutor);
         mTaskView.setListener(mViewListener);
     }
 
@@ -111,7 +112,6 @@
     @Test
     public void testSetPendingListener_throwsException() {
         TaskView taskView = new TaskView(mContext, mOrganizer);
-        mTaskView.setExecutor(mExecutor);
         taskView.setListener(mViewListener);
         try {
             taskView.setListener(mViewListener);
@@ -215,4 +215,19 @@
 
         verify(mViewListener).onBackPressedOnTaskRoot(eq(mTaskInfo.taskId));
     }
+
+    @Test
+    public void testSetOnBackPressedOnTaskRoot() {
+        mTaskView.onTaskAppeared(mTaskInfo, mLeash);
+        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
+    }
+
+    @Test
+    public void testUnsetOnBackPressedOnTaskRoot() {
+        mTaskView.onTaskAppeared(mTaskInfo, mLeash);
+        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
+
+        mTaskView.onTaskVanished(mTaskInfo);
+        verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
index 8842872..495be41 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.window.TaskSnapshot;
 
 import androidx.test.filters.SmallTest;
 
@@ -153,7 +154,7 @@
 
     @Test
     public void testOnTaskSnapshotChanged() {
-        ActivityManager.TaskSnapshot snapshot = mock(ActivityManager.TaskSnapshot.class);
+        TaskSnapshot snapshot = mock(TaskSnapshot.class);
         mImpl.onTaskSnapshotChanged(123, snapshot);
         verify(mCallback).onTaskSnapshotChanged(eq(123), eq(snapshot));
         verify(mOtherCallback).onTaskSnapshotChanged(eq(123), eq(snapshot));
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 d87f4c6..cd46816 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
@@ -69,24 +69,28 @@
     }
 
     @Test
-    public void testUpdateDividePosition() {
-        mSplitLayout.updateDividePosition(anyInt());
+    public void testUpdateDivideBounds() {
+        mSplitLayout.updateDivideBounds(anyInt());
         verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
     }
 
     @Test
-    public void testSetSnapTarget() {
-        DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0,
-                DividerSnapAlgorithm.SnapTarget.FLAG_NONE);
-        mSplitLayout.setSnapTarget(snapTarget);
+    public void testSetDividePosition() {
+        mSplitLayout.setDividePosition(anyInt());
         verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class));
+    }
 
+    @Test
+    @UiThreadTest
+    public void testSnapToDismissTarget() {
         // verify it callbacks properly when the snap target indicates dismissing split.
-        snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
-        mSplitLayout.setSnapTarget(snapTarget);
+        DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
+                DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
+        mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
         verify(mLayoutChangeListener).onSnappedToDismiss(eq(false));
-        snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
-        mSplitLayout.setSnapTarget(snapTarget);
+        snapTarget = getSnapTarget(0 /* position */,
+                DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
+        mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
         verify(mLayoutChangeListener).onSnappedToDismiss(eq(true));
     }
 
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/letterbox/LetterboxConfigControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java
deleted file mode 100644
index 2923336..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.letterbox;
-
-import static org.junit.Assert.assertEquals;
-
-import android.view.Gravity;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.R;
-import com.android.wm.shell.ShellTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for {@link LetterboxConfigController}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class LetterboxConfigControllerTest extends ShellTestCase {
-
-    private LetterboxConfigController mLetterboxConfigController;
-
-    @Before
-    public void setUp() {
-        mLetterboxConfigController = new LetterboxConfigController(getContext());
-    }
-
-    @Test
-    public void testGetPortraitGravity_noOverrides_returnConfigValue() {
-        assertEquals(
-                mLetterboxConfigController.getPortraitGravity(),
-                getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity));
-    }
-
-    @Test
-    public void testGetLandscapeGravity_noOverrides_returnConfigValue() {
-        assertEquals(
-                mLetterboxConfigController.getLandscapeGravity(),
-                getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity));
-    }
-
-    @Test
-    public void testSetPortraitGravity_validValue_savesValue() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.BOTTOM);
-
-        mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.CENTER);
-
-        mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.TOP);
-    }
-
-    @Test
-    public void testSetLandscapeGravity_validValue_savesValue() {
-        mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.LEFT);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.CENTER);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.RIGHT);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testSetPortraitGravity_invalidValue_throwsException() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.RIGHT);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testSetLandscapeGravity_invalidValue_throwsException() {
-        mLetterboxConfigController.setLandscapeGravity(Gravity.TOP);
-    }
-
-    @Test
-    public void testResetPortraitGravity() {
-        int defaultGravity =
-                getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity);
-
-        mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
-        mLetterboxConfigController.resetPortraitGravity();
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
-
-        mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
-        mLetterboxConfigController.resetPortraitGravity();
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
-
-        mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-        mLetterboxConfigController.resetPortraitGravity();
-        assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
-    }
-
-    @Test
-    public void testResetLandscapeGravity() {
-        int defaultGravity =
-                getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
-        mLetterboxConfigController.resetLandscapeGravity();
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
-        mLetterboxConfigController.resetLandscapeGravity();
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
-        mLetterboxConfigController.resetLandscapeGravity();
-        assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
-    }
-
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java
deleted file mode 100644
index fc0e20b..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.letterbox;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.graphics.Insets;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.Gravity;
-import android.view.SurfaceControl;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.TransactionPool;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link LetterboxTaskListener}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class LetterboxTaskListenerTest extends ShellTestCase {
-
-    @Mock private SurfaceControl mLeash;
-    @Mock private SurfaceControl.Transaction mTransaction;
-    @Mock private WindowManager mWindowManager;
-    @Mock private WindowMetrics mWindowMetrics;
-    @Mock private WindowInsets mWindowInsets;
-    private LetterboxTaskListener mLetterboxTaskListener;
-    private LetterboxConfigController mLetterboxConfigController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mLetterboxConfigController = new LetterboxConfigController(getContext());
-        mLetterboxTaskListener = new LetterboxTaskListener(
-                new SyncTransactionQueue(
-                        new TransactionPool() {
-                            @Override
-                            public SurfaceControl.Transaction acquire() {
-                                return mTransaction;
-                            }
-
-                            @Override
-                            public void release(SurfaceControl.Transaction t) {
-                            }
-                        },
-                        new Handler(Looper.getMainLooper())),
-                mLetterboxConfigController,
-                mWindowManager);
-
-        when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getWindowInsets()).thenReturn(mWindowInsets);
-    }
-
-    @Test
-    public void testOnTaskInfoChanged_updatesPositionAndCrop() {
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                Insets.NONE);
-
-        mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 100),
-                        /* activityBounds */ new Rect(75, 0, 125, 75),
-                        /* taskBounds */ new Rect(50, 0, 125, 100)),
-                mLeash);
-
-        // Task doesn't need to repositioned
-        verifySetPosition(50, 0);
-        // Should return activity coordinates offset by task coordinates
-        verifySetWindowCrop(new Rect(25, 0, 75, 75));
-
-        mLetterboxTaskListener.onTaskInfoChanged(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 100),
-                        // Activity is offset by 25 to the left
-                        /* activityBounds */ new Rect(50, 0, 100, 75),
-                        /* taskBounds */ new Rect(50, 0, 125, 100)));
-
-        // Task needs to be repositioned by 25 to the left
-        verifySetPosition(75, 0);
-        // Should return activity coordinates offset by task coordinates
-        verifySetWindowCrop(new Rect(0, 0, 50, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_landscapeWithLeftGravity() {
-        mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 100),
-                        /* activityBounds */ new Rect(150, 0, 200, 75),
-                        /* taskBounds */ new Rect(125, 0, 200, 100)),
-                mLeash);
-
-        verifySetPosition(-15, 0);
-        // Should return activity coordinates offset by task coordinates minus unwanted right inset
-        verifySetWindowCrop(new Rect(25, 0, 65, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_landscapeWithCenterGravity() {
-        mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 100),
-                        /* activityBounds */ new Rect(150, 0, 200, 75),
-                        /* taskBounds */ new Rect(125, 0, 200, 100)),
-                mLeash);
-
-        verifySetPosition(55, 0);
-        // Should return activity coordinates offset by task coordinates minus unwanted right inset
-        verifySetWindowCrop(new Rect(25, 0, 65, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_landscapeWithRightGravity() {
-        mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 100),
-                        /* activityBounds */ new Rect(50, 0, 100, 75),
-                        /* taskBounds */ new Rect(25, 0, 100, 100)),
-                mLeash);
-
-        verifySetPosition(115, 0);
-        // Should return activity coordinates offset by task coordinates
-        verifySetWindowCrop(new Rect(25, 0, 75, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_portraitWithTopGravity() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 100, 150),
-                        /* activityBounds */ new Rect(0, 75, 50, 125),
-                        /* taskBounds */ new Rect(0, 50, 100, 125)),
-                mLeash);
-
-        verifySetPosition(20, -15);
-        // Should return activity coordinates offset by task coordinates minus unwanted left inset
-        verifySetWindowCrop(new Rect(10, 25, 50, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_portraitWithCenterGravity() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 100, 150),
-                        /* activityBounds */ new Rect(0, 75, 50, 125),
-                        /* taskBounds */ new Rect(0, 50, 100, 125)),
-                mLeash);
-
-        verifySetPosition(20, 20);
-        // Should return activity coordinates offset by task coordinates minus unwanted left inset
-        verifySetWindowCrop(new Rect(10, 25, 50, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_portraitWithBottomGravity() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 100, 150),
-                        /* activityBounds */ new Rect(0, 75, 50, 125),
-                        /* taskBounds */ new Rect(0, 50, 100, 125)),
-                mLeash);
-
-        verifySetPosition(20, 55);
-        // Should return activity coordinates offset by task coordinates minus unwanted left inset
-        verifySetWindowCrop(new Rect(10, 25, 50, 75));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_partlyOverlapsWithAllInsets() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds
-                Insets.of(/* left= */ 25, /* top= */ 25, /* right= */ 35, /* bottom= */ 15));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds
-                        /* parentBounds */ new Rect(0, 0, 200, 125),
-                        /* activityBounds */ new Rect(15, 0, 175, 120),
-                        /* taskBounds */ new Rect(0, 0, 100, 125)), // equal to parent bounds
-                mLeash);
-
-        // Activity fully covers parent bounds with insets so doesn't need to be moved.
-        verifySetPosition(0, 0);
-        // Should return activity coordinates offset by task coordinates minus all insets
-        // except top one (keep status bar decor visible).
-        verifySetWindowCrop(new Rect(25, 0, 165, 110));
-    }
-
-    @Test
-    public void testOnTaskInfoAppeared_parentShiftedLikeInOneHandedMode() {
-        mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
-        setWindowBoundsAndInsets(
-                /* windowBounds= */ new Rect(0, 0, 100, 150),
-                Insets.of(/* left= */ 0, /* top= */ 10, /* right= */ 0, /* bottom= */ 0));
-
-        mLetterboxTaskListener.onTaskAppeared(
-                createTaskInfo(
-                        /* taskId */ 1,
-                        /* maxBounds= */ new Rect(0, 0, 100, 150),
-                        /* parentBounds */ new Rect(0, 75, 100, 225),
-                        /* activityBounds */ new Rect(25, 75, 75, 125),
-                        /* taskBounds */ new Rect(0, 75, 100, 125)),
-                mLeash);
-
-        verifySetPosition(0, 0);
-        verifySetWindowCrop(new Rect(25, 0, 75, 50));
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testOnTaskAppeared_calledSecondTimeWithSameTaskId_throwsException() {
-        setWindowBoundsAndInsets(new Rect(),  Insets.NONE);
-        RunningTaskInfo taskInfo =
-                createTaskInfo(/* taskId */ 1, new Rect(),  new Rect(), new Rect(), new Rect());
-        mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash);
-        mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash);
-    }
-
-    private void setWindowBoundsAndInsets(Rect windowBounds, Insets insets) {
-        when(mWindowMetrics.getBounds()).thenReturn(windowBounds);
-        when(mWindowInsets.getInsets(anyInt())).thenReturn(insets);
-    }
-
-    private void verifySetPosition(int x, int y) {
-        verify(mTransaction).setPosition(eq(mLeash), eq((float) x), eq((float) y));
-    }
-
-    private void verifySetWindowCrop(final Rect crop) {
-        // Should return activty coordinates offset by task coordinates
-        verify(mTransaction).setWindowCrop(eq(mLeash), eq(crop));
-    }
-
-    private static RunningTaskInfo createTaskInfo(
-                int taskId,
-                final Rect maxBounds,
-                final Rect parentBounds,
-                final Rect activityBounds,
-                final Rect taskBounds) {
-        RunningTaskInfo taskInfo = new RunningTaskInfo();
-        taskInfo.taskId = taskId;
-        taskInfo.configuration.windowConfiguration.setMaxBounds(maxBounds);
-        taskInfo.parentBounds = parentBounds;
-        taskInfo.configuration.windowConfiguration.setBounds(taskBounds);
-        taskInfo.letterboxActivityBounds = Rect.copyOrNull(activityBounds);
-
-        return taskInfo;
-    }
-}
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/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 7f280cd..d30fa38 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -197,6 +197,11 @@
         }
 
         @Override
+        public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
+            return this;
+        }
+
+        @Override
         public void apply() {}
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index a65d832..ef99235 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -337,7 +337,8 @@
         reentryBounds.scale(1.25f);
         final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds);
 
-        mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
+        mPipBoundsState.saveReentryState(
+                new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction);
         final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
 
         assertEquals(reentryBounds.width(), destinationBounds.width());
@@ -351,7 +352,8 @@
         reentryBounds.offset(0, -100);
         final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds);
 
-        mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
+        mPipBoundsState.saveReentryState(
+                new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction);
 
         final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
index 4bcca06..dea24d3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -31,14 +31,13 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.util.function.TriConsumer;
 import com.android.wm.shell.ShellTestCase;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.function.BiConsumer;
-
 /**
  * Tests for {@link PipBoundsState}.
  */
@@ -47,7 +46,7 @@
 @SmallTest
 public class PipBoundsStateTest extends ShellTestCase {
 
-    private static final Rect DEFAULT_BOUNDS = new Rect(0, 0, 10, 10);
+    private static final Size DEFAULT_SIZE = new Size(10, 10);
     private static final float DEFAULT_SNAP_FRACTION = 1.0f;
 
     private PipBoundsState mPipBoundsState;
@@ -71,22 +70,22 @@
 
     @Test
     public void testSetReentryState() {
-        final Rect bounds = new Rect(0, 0, 100, 100);
+        final Size size = new Size(100, 100);
         final float snapFraction = 0.5f;
 
-        mPipBoundsState.saveReentryState(bounds, snapFraction);
+        mPipBoundsState.saveReentryState(size, snapFraction);
 
         final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
-        assertEquals(new Size(100, 100), state.getSize());
+        assertEquals(size, state.getSize());
         assertEquals(snapFraction, state.getSnapFraction(), 0.01);
     }
 
     @Test
     public void testClearReentryState() {
-        final Rect bounds = new Rect(0, 0, 100, 100);
+        final Size size = new Size(100, 100);
         final float snapFraction = 0.5f;
 
-        mPipBoundsState.saveReentryState(bounds, snapFraction);
+        mPipBoundsState.saveReentryState(size, snapFraction);
         mPipBoundsState.clearReentryState();
 
         assertNull(mPipBoundsState.getReentryState());
@@ -95,20 +94,20 @@
     @Test
     public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() {
         mPipBoundsState.setLastPipComponentName(mTestComponentName1);
-        mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+        mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION);
 
         mPipBoundsState.setLastPipComponentName(mTestComponentName1);
 
         final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
         assertNotNull(state);
-        assertEquals(new Size(DEFAULT_BOUNDS.width(), DEFAULT_BOUNDS.height()), state.getSize());
+        assertEquals(DEFAULT_SIZE, state.getSize());
         assertEquals(DEFAULT_SNAP_FRACTION, state.getSnapFraction(), 0.01);
     }
 
     @Test
     public void testSetLastPipComponentName_changed_clearReentryState() {
         mPipBoundsState.setLastPipComponentName(mTestComponentName1);
-        mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+        mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION);
 
         mPipBoundsState.setLastPipComponentName(mTestComponentName2);
 
@@ -117,23 +116,33 @@
 
     @Test
     public void testSetShelfVisibility_changed_callbackInvoked() {
-        final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
+        final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
         mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
 
         mPipBoundsState.setShelfVisibility(true, 100);
 
-        verify(callback).accept(true, 100);
+        verify(callback).accept(true, 100, true);
+    }
+
+    @Test
+    public void testSetShelfVisibility_changedWithoutUpdateMovBounds_callbackInvoked() {
+        final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
+        mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
+
+        mPipBoundsState.setShelfVisibility(true, 100, false);
+
+        verify(callback).accept(true, 100, false);
     }
 
     @Test
     public void testSetShelfVisibility_notChanged_callbackNotInvoked() {
-        final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
+        final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
         mPipBoundsState.setShelfVisibility(true, 100);
         mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
 
         mPipBoundsState.setShelfVisibility(true, 100);
 
-        verify(callback, never()).accept(true, 100);
+        verify(callback, never()).accept(true, 100, true);
     }
 
     @Test
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/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index 4687d2d..62ffac4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -30,10 +30,12 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.graphics.Rect;
 import android.os.RemoteException;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.util.Size;
 
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.WindowManagerShellWrapper;
@@ -135,4 +137,28 @@
 
         verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
     }
+
+    @Test
+    public void saveReentryState_noUserResize_doesNotSaveSize() {
+        final Rect bounds = new Rect(0, 0, 10, 10);
+        when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f);
+        when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(false);
+
+        mPipController.saveReentryState(bounds);
+
+        verify(mMockPipBoundsState).saveReentryState(null, 1.0f);
+    }
+
+    @Test
+    public void saveReentryState_userHasResized_savesSize() {
+        final Rect bounds = new Rect(0, 0, 10, 10);
+        final Rect resizedBounds = new Rect(0, 0, 30, 30);
+        when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f);
+        when(mMockPipTouchHandler.getUserResizeBounds()).thenReturn(resizedBounds);
+        when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(true);
+
+        mPipController.saveReentryState(bounds);
+
+        verify(mMockPipBoundsState).saveReentryState(new Size(30, 30), 1.0f);
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index f5628ab..07115c2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -41,11 +41,14 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
+import android.window.StartingWindowInfo;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.wm.shell.common.HandlerExecutor;
+import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
 
 import org.junit.Before;
@@ -70,8 +73,8 @@
     static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
         int mAddWindowForTask = 0;
 
-        TestStartingSurfaceDrawer(Context context) {
-            super(context);
+        TestStartingSurfaceDrawer(Context context, ShellExecutor executor) {
+            super(context, executor);
         }
 
         @Override
@@ -109,36 +112,38 @@
         doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
         doNothing().when(mMockWindowManager).addView(any(), any());
 
-        mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(context));
+        mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(context,
+                new HandlerExecutor(new Handler(Looper.getMainLooper()))));
     }
 
     @Test
     public void testAddSplashScreenSurface() {
         final int taskId = 1;
         final Handler mainLoop = new Handler(Looper.getMainLooper());
-        final ActivityManager.RunningTaskInfo taskInfo =
-                createTaskInfo(taskId, WINDOWING_MODE_FULLSCREEN);
-        mStartingSurfaceDrawer.addStartingWindow(taskInfo, mBinder);
+        final StartingWindowInfo windowInfo =
+                createWindowInfo(taskId, WINDOWING_MODE_FULLSCREEN);
+        mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
         waitHandlerIdle(mainLoop);
         verify(mStartingSurfaceDrawer).postAddWindow(eq(taskId), eq(mBinder), any(), any(), any());
         assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
 
-        mStartingSurfaceDrawer.removeStartingWindow(taskInfo);
+        mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId);
         waitHandlerIdle(mainLoop);
         verify(mStartingSurfaceDrawer).removeWindowSynced(eq(taskId));
         assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
     }
 
-    private ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
-        ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
+    private StartingWindowInfo createWindowInfo(int taskId, int windowingMode) {
+        StartingWindowInfo windowInfo = new StartingWindowInfo();
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
         info.packageName = "test";
         info.theme = android.R.style.Theme;
+        final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.topActivityInfo = info;
         taskInfo.taskId = taskId;
-        taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
-        return taskInfo;
+        windowInfo.taskInfo = taskInfo;
+        return windowInfo;
     }
 
     private static void waitHandlerIdle(Handler handler) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
new file mode 100644
index 0000000..94af329
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package unittest.src.com.android.wm.shell.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+
+import android.app.ActivityManager.TaskDescription;
+import android.content.ComponentName;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorSpace;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.view.InsetsState;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.window.TaskSnapshot;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.startingsurface.TaskSnapshotWindow;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link TaskSnapshotWindow}.
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaskSnapshotWindowTest {
+
+    private TaskSnapshotWindow mWindow;
+
+    private void setupSurface(int width, int height) {
+        setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, width, height));
+    }
+
+    private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+            int windowFlags, Rect taskBounds) {
+        // Previously when constructing TaskSnapshots for this test, scale was 1.0f, so to mimic
+        // this behavior set the taskSize to be the same as the taskBounds width and height. The
+        // taskBounds passed here are assumed to be the same task bounds as when the snapshot was
+        // taken. We assume there is no aspect ratio mismatch between the screenshot and the
+        // taskBounds
+        assertEquals(width, taskBounds.width());
+        assertEquals(height, taskBounds.height());
+        Point taskSize = new Point(taskBounds.width(), taskBounds.height());
+
+        final TaskSnapshot snapshot = createTaskSnapshot(width, height, taskSize, contentInsets);
+        mWindow = new TaskSnapshotWindow(new SurfaceControl(), snapshot, "Test",
+                createTaskDescription(Color.WHITE, Color.RED, Color.BLUE),
+                0 /* appearance */, windowFlags /* windowFlags */, 0 /* privateWindowFlags */,
+                taskBounds, ORIENTATION_PORTRAIT, ACTIVITY_TYPE_STANDARD, new InsetsState(),
+                null /* clearWindow */);
+    }
+
+    private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
+            Rect contentInsets) {
+        final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
+                1, HardwareBuffer.USAGE_CPU_READ_RARELY);
+        return new TaskSnapshot(
+                System.currentTimeMillis(),
+                new ComponentName("", ""), buffer,
+                ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+                Surface.ROTATION_0, taskSize, contentInsets, false,
+                true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
+                0 /* systemUiVisibility */, false /* isTranslucent */);
+    }
+
+    private static TaskDescription createTaskDescription(int background, int statusBar,
+            int navigationBar) {
+        final TaskDescription td = new TaskDescription();
+        td.setBackgroundColor(background);
+        td.setStatusBarColor(statusBar);
+        td.setNavigationBarColor(navigationBar);
+        return td;
+    }
+
+    @Test
+    public void fillEmptyBackground_fillHorizontally() {
+        setupSurface(200, 100);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(200);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
+        verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
+    }
+
+    @Test
+    public void fillEmptyBackground_fillVertically() {
+        setupSurface(100, 200);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(200);
+        mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
+        verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
+    }
+
+    @Test
+    public void fillEmptyBackground_fillBoth() {
+        setupSurface(200, 200);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(200);
+        when(mockCanvas.getHeight()).thenReturn(200);
+        mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
+        verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
+        verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
+    }
+
+    @Test
+    public void fillEmptyBackground_dontFill_sameSize() {
+        setupSurface(100, 100);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
+        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+    }
+
+    @Test
+    public void fillEmptyBackground_dontFill_bitmapLarger() {
+        setupSurface(100, 100);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
+        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop() {
+        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 100, 90), mWindow.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_taskNotOnTop() {
+        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 150));
+        assertEquals(new Rect(0, 10, 100, 90), mWindow.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_navBarLeft() {
+        setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(10, 0, 100, 100), mWindow.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_navBarRight() {
+        setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 90, 100), mWindow.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_waterfall() {
+        setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(5, 0, 95, 90), mWindow.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotFrame() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 0, 10);
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        assertEquals(new Rect(0, 0, 100, 80),
+                mWindow.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+    }
+
+    @Test
+    public void testCalculateSnapshotFrame_navBarLeft() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(10, 10, 0, 0);
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        assertEquals(new Rect(10, 0, 100, 90),
+                mWindow.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+    }
+
+    @Test
+    public void testCalculateSnapshotFrame_waterfall() {
+        setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
+        final Rect insets = new Rect(0, 10, 0, 10);
+        mWindow.setFrames(new Rect(5, 0, 95, 100), insets);
+        assertEquals(new Rect(0, 0, 90, 90),
+                mWindow.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
+    }
+
+    @Test
+    public void testDrawStatusBarBackground() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 10, 0);
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100));
+        verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+    }
+
+    @Test
+    public void testDrawStatusBarBackground_nullFrame() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 10, 0);
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawStatusBarBackground(mockCanvas, null);
+        verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+    }
+
+    @Test
+    public void testDrawStatusBarBackground_nope() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 10, 0);
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100));
+        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground() {
+        final Rect insets = new Rect(0, 10, 0, 10);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground_left() {
+        final Rect insets = new Rect(10, 10, 0, 0);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground_right() {
+        final Rect insets = new Rect(0, 10, 10, 0);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mWindow.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+    }
+}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index a545b3d..bec80a7 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -670,7 +670,7 @@
     }
 
     auto entry_flags = type_spec->GetFlagsForEntryIndex(entry_idx);
-    if (UNLIKELY(!entry_flags)) {
+    if (UNLIKELY(!entry_flags.has_value())) {
       return base::unexpected(entry_flags.error());
     }
     type_flags |= entry_flags.value();
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 4010e4e..bce70e2 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -897,12 +897,12 @@
             // Decode the UTF-16 length. This is not used if we're not
             // converting to UTF-16 from UTF-8.
             const base::expected<size_t, IOError> u16len = decodeLength(&str);
-            if (UNLIKELY(!u16len)) {
+            if (UNLIKELY(!u16len.has_value())) {
                 return base::unexpected(u16len.error());
             }
 
             const base::expected<size_t, IOError> u8len = decodeLength(&str);
-            if (UNLIKELY(!u8len)) {
+            if (UNLIKELY(!u8len.has_value())) {
                 return base::unexpected(u8len.error());
             }
 
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
index a34aa72..87fb2c0 100644
--- a/libs/androidfw/ResourceUtils.cpp
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -56,7 +56,8 @@
     .package_len = package_name.size(),
   };
 
-  if (base::expected<StringPiece, NullOrIOError> type_str = type_string_ref.string8()) {
+  if (base::expected<StringPiece, NullOrIOError> type_str = type_string_ref.string8();
+      type_str.ok()) {
     name.type = type_str->data();
     name.type_len = type_str->size();
   } else if (UNLIKELY(IsIOError(type_str))) {
@@ -64,7 +65,8 @@
   }
 
   if (name.type == nullptr) {
-    if (base::expected<StringPiece16, NullOrIOError> type16_str = type_string_ref.string16()) {
+    if (base::expected<StringPiece16, NullOrIOError> type16_str = type_string_ref.string16();
+        type16_str.ok()) {
       name.type16 = type16_str->data();
       name.type_len = type16_str->size();
     } else if (!type16_str.has_value()) {
@@ -72,7 +74,8 @@
     }
   }
 
-  if (base::expected<StringPiece, NullOrIOError> entry_str = entry_string_ref.string8()) {
+  if (base::expected<StringPiece, NullOrIOError> entry_str = entry_string_ref.string8();
+      entry_str.ok()) {
     name.entry = entry_str->data();
     name.entry_len = entry_str->size();
   } else if (UNLIKELY(IsIOError(entry_str))) {
@@ -80,7 +83,8 @@
   }
 
   if (name.entry == nullptr) {
-    if (base::expected<StringPiece16, NullOrIOError> entry16_str = entry_string_ref.string16()) {
+    if (base::expected<StringPiece16, NullOrIOError> entry16_str = entry_string_ref.string16();
+        entry16_str.ok()) {
       name.entry16 = entry16_str->data();
       name.entry_len = entry16_str->size();
     } else if (!entry16_str.has_value()) {
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 1ff1978..9d82f63 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -618,6 +618,7 @@
         "tests/unit/LayerUpdateQueueTests.cpp",
         "tests/unit/LinearAllocatorTests.cpp",
         "tests/unit/MatrixTests.cpp",
+        "tests/unit/OpBufferTests.cpp",
         "tests/unit/PathInterpolatorTests.cpp",
         "tests/unit/RenderNodeDrawableTests.cpp",
         "tests/unit/RenderNodeTests.cpp",
@@ -672,6 +673,7 @@
 
     srcs: [
         "tests/microbench/main.cpp",
+        "tests/microbench/CanvasOpBench.cpp",
         "tests/microbench/DisplayListCanvasBench.cpp",
         "tests/microbench/LinearAllocatorBench.cpp",
         "tests/microbench/PathParserBench.cpp",
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index dc63e5d..dd24763 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -16,14 +16,15 @@
 
 #pragma once
 
-#include "pipeline/skia/SkiaDisplayList.h"
-
 namespace android {
 namespace uirenderer {
 
 namespace VectorDrawable {
 class Tree;
 };
+namespace skiapipeline {
+class SkiaDisplayList;
+}
 typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
 
 /**
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 738246d..ee7d15a 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -159,7 +159,7 @@
         // GPU start time is approximated to the moment before swapBuffer is invoked.
         // We could add an EGLSyncKHR fence at the beginning of the frame, but that is an overhead.
         int64_t endTime = get(FrameInfoIndex::GpuCompleted);
-        return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : 0;
+        return endTime > 0 ? endTime - get(FrameInfoIndex::SwapBuffers) : -1;
     }
 
     inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 31e4555..74c70c8 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -380,7 +380,7 @@
     if (mDisplayList) {
         mDisplayList->updateChildren(
                 [&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); });
-        if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) {
+        if (!mDisplayList->reuseDisplayList(this)) {
             delete mDisplayList;
         }
     }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9a4ed81..acb74f4 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -669,7 +669,10 @@
     if (paint) {
         pnt = *paint;
     }
-    pnt.setShader(bitmap.makeImage()->makeShader());
+    SkSamplingOptions sampling(pnt.isFilterBitmap() ? SkFilterMode::kLinear
+                                                    : SkFilterMode::kNearest,
+                               SkMipmapMode::kNone);
+    pnt.setShader(bitmap.makeImage()->makeShader(sampling));
     auto v = builder.detach();
     apply_looper(&pnt, [&](const SkPaint& p) {
         mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
diff --git a/libs/hwui/canvas/CanvasFrontend.cpp b/libs/hwui/canvas/CanvasFrontend.cpp
index 2c839b0..8f261c83 100644
--- a/libs/hwui/canvas/CanvasFrontend.cpp
+++ b/libs/hwui/canvas/CanvasFrontend.cpp
@@ -21,7 +21,14 @@
 namespace android::uirenderer {
 
 CanvasStateHelper::CanvasStateHelper(int width, int height) {
+    resetState(width, height);
+}
+
+void CanvasStateHelper::resetState(int width, int height) {
     mInitialBounds = SkIRect::MakeWH(width, height);
+    mSaveStack.clear();
+    mClipStack.clear();
+    mTransformStack.clear();
     mSaveStack.emplace_back();
     mClipStack.emplace_back().setRect(mInitialBounds);
     mTransformStack.emplace_back();
diff --git a/libs/hwui/canvas/CanvasFrontend.h b/libs/hwui/canvas/CanvasFrontend.h
index 5fccccb..d749d2f 100644
--- a/libs/hwui/canvas/CanvasFrontend.h
+++ b/libs/hwui/canvas/CanvasFrontend.h
@@ -57,9 +57,7 @@
     }
 
     bool internalSave(SaveEntry saveEntry);
-    bool internalSave(SaveFlags::Flags flags) {
-        return internalSave(flagsToSaveEntry(flags));
-    }
+
     void internalSaveLayer(const SkCanvas::SaveLayerRec& layerRec) {
         internalSave({
             .clip = true,
@@ -90,6 +88,8 @@
         return mClipStack[mCurrentClipIndex];
     }
 
+    void resetState(int width, int height);
+
 public:
     int saveCount() const { return mSaveStack.size(); }
 
@@ -186,14 +186,26 @@
         submit(std::move(op));
     }
 
-    const CanvasOpReceiver& receiver() const { return mReceiver; }
+    const CanvasOpReceiver& receiver() const { return *mReceiver; }
+
+    CanvasOpReceiver finish() {
+        auto ret = std::move(mReceiver.value());
+        mReceiver.reset();
+        return std::move(ret);
+    }
+
+    template<class... Args>
+    void reset(int newWidth, int newHeight, Args&&... args) {
+        resetState(newWidth, newHeight);
+        mReceiver.emplace(std::forward<Args>(args)...);
+    }
 
 private:
-    CanvasOpReceiver mReceiver;
+    std::optional<CanvasOpReceiver> mReceiver;
 
     template <CanvasOpType T>
     void submit(CanvasOp<T>&& op) {
-        mReceiver.push_container(CanvasOpContainer(std::move(op), transform()));
+        mReceiver->push_container(CanvasOpContainer(std::move(op), transform()));
     }
 };
 
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index 242dbdb..62c26c7 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -310,7 +310,7 @@
 template<>
 struct CanvasOp<CanvasOpType::DrawImage> {
 
-    CanvasOp<CanvasOpType::DrawImageRect>(
+    CanvasOp(
         const sk_sp<Bitmap>& bitmap,
         float left,
         float top,
@@ -336,7 +336,7 @@
 template<>
 struct CanvasOp<CanvasOpType::DrawImageRect> {
 
-    CanvasOp<CanvasOpType::DrawImageRect>(
+    CanvasOp(
         const sk_sp<Bitmap>& bitmap,
         SkRect src,
         SkRect dst,
@@ -367,7 +367,7 @@
 template<>
 struct CanvasOp<CanvasOpType::DrawImageLattice> {
 
-    CanvasOp<CanvasOpType::DrawImageLattice>(
+    CanvasOp(
         const sk_sp<Bitmap>& bitmap,
         SkRect dst,
         SkCanvas::Lattice lattice,
diff --git a/libs/hwui/canvas/OpBuffer.h b/libs/hwui/canvas/OpBuffer.h
index 98e385f..1237d69 100644
--- a/libs/hwui/canvas/OpBuffer.h
+++ b/libs/hwui/canvas/OpBuffer.h
@@ -60,9 +60,8 @@
         return (size + (Alignment - 1)) & -Alignment;
     }
 
-    static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader));
-
 public:
+    static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader));
     using ItemHeader = OpBufferItemHeader<ItemTypes>;
 
     OpBuffer() = default;
@@ -145,7 +144,86 @@
 
     ItemHeader* last() const { return isEmpty() ? nullptr : itemAt(mBuffer->endOffset); }
 
+    class sentinal {
+    public:
+        explicit sentinal(const uint8_t* end) : end(end) {}
+    private:
+        const uint8_t* const end;
+    };
+
+    sentinal end() const {
+        return sentinal{end_ptr()};
+    }
+
+    template <ItemTypes T>
+    class filtered_iterator {
+    public:
+        explicit filtered_iterator(uint8_t* start, const uint8_t* end)
+                : mCurrent(start), mEnd(end) {
+            ItemHeader* header = reinterpret_cast<ItemHeader*>(mCurrent);
+            if (header->type != T) {
+                advance();
+            }
+        }
+
+        filtered_iterator& operator++() {
+            advance();
+            return *this;
+        }
+
+        // Although this iterator self-terminates, we need a placeholder to compare against
+        // to make for-each loops happy
+        bool operator!=(const sentinal& other) const {
+            return mCurrent != mEnd;
+        }
+
+        ItemContainer<T>& operator*() {
+            return *reinterpret_cast<ItemContainer<T>*>(mCurrent);
+        }
+    private:
+        void advance() {
+            ItemHeader* header = reinterpret_cast<ItemHeader*>(mCurrent);
+            do {
+                mCurrent += header->size;
+                header = reinterpret_cast<ItemHeader*>(mCurrent);
+            } while (mCurrent != mEnd && header->type != T);
+        }
+        uint8_t* mCurrent;
+        const uint8_t* const mEnd;
+    };
+
+    template <ItemTypes T>
+    class filtered_view {
+    public:
+        explicit filtered_view(uint8_t* start, const uint8_t* end) : mStart(start), mEnd(end) {}
+
+        filtered_iterator<T> begin() const {
+            return filtered_iterator<T>{mStart, mEnd};
+        }
+
+        sentinal end() const {
+            return sentinal{mEnd};
+        }
+    private:
+        uint8_t* mStart;
+        const uint8_t* const mEnd;
+    };
+
+    template <ItemTypes T>
+    filtered_view<T> filter() const {
+        return filtered_view<T>{start_ptr(), end_ptr()};
+    }
+
 private:
+
+    uint8_t* start_ptr() const {
+        return reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->startOffset;
+    }
+
+    const uint8_t* end_ptr() const {
+        return reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->used;
+    }
+
     template <typename F, std::size_t... I>
     void for_each(F&& f, std::index_sequence<I...>) const {
         // Validate we're not empty
@@ -160,8 +238,8 @@
         }...};
 
         // Do the actual iteration of each item
-        uint8_t* current = reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->startOffset;
-        uint8_t* end = reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->used;
+        uint8_t* current = start_ptr();
+        const uint8_t* end = end_ptr();
         while (current != end) {
             auto header = reinterpret_cast<ItemHeader*>(current);
             // `f` could be a destructor, so ensure all accesses to the OP happen prior to invoking
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 4d67166..11fa322 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -21,6 +21,7 @@
 #include <SaveFlags.h>
 
 #include <androidfw/ResourceTypes.h>
+#include "DisplayList.h"
 #include "Properties.h"
 #include "utils/Macros.h"
 
@@ -47,18 +48,6 @@
 class CanvasPropertyPrimitive;
 class DeferredLayerUpdater;
 class RenderNode;
-
-namespace skiapipeline {
-class SkiaDisplayList;
-}
-
-/**
- * Data structure that holds the list of commands used in display list stream
- */
-using DisplayList = skiapipeline::SkiaDisplayList;
-}
-
-namespace uirenderer {
 namespace VectorDrawable {
 class Tree;
 }
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index e75e9e7..05bae5c 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -137,6 +137,9 @@
     bool isDevKern() const { return mDevKern; }
     void setDevKern(bool d) { mDevKern = d; }
 
+    // Deprecated -- bitmapshaders will be taking this flag explicitly
+    bool isFilterBitmap() const { return this->getFilterQuality() != kNone_SkFilterQuality; }
+
     // The Java flags (Paint.java) no longer fit into the native apis directly.
     // These methods handle converting to and from them and the native representations
     // in android::Paint.
@@ -149,7 +152,7 @@
     // The only respected flags are : [ antialias, dither, filterBitmap ]
     static uint32_t GetSkPaintJavaFlags(const SkPaint&);
     static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
- 
+
 private:
     SkFont mFont;
     sk_sp<SkDrawLooper> mLooper;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 45795ff..aaec60b 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -61,7 +61,7 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
-        jint tileModeX, jint tileModeY) {
+        jint tileModeX, jint tileModeY, bool filter) {
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
     sk_sp<SkImage> image;
     if (bitmapHandle) {
@@ -74,8 +74,10 @@
         SkBitmap bitmap;
         image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
     }
+    SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
+                               SkMipmapMode::kNone);
     sk_sp<SkShader> shader = image->makeShader(
-            (SkTileMode)tileModeX, (SkTileMode)tileModeY);
+            (SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
     ThrowIAE_IfNull(env, shader.get());
 
     if (matrix) {
@@ -291,7 +293,7 @@
 };
 
 static const JNINativeMethod gBitmapShaderMethods[] = {
-    { "nativeCreate",      "(JJII)J",  (void*)BitmapShader_constructor },
+    { "nativeCreate",      "(JJIIZ)J",  (void*)BitmapShader_constructor },
 };
 
 static const JNINativeMethod gLinearGradientMethods[] = {
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index a2964d6..10c8077 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_VIEW
 #include "FontUtils.h"
 #include "GraphicsJNI.h"
 #include "fonts/Font.h"
@@ -25,8 +26,13 @@
 #include <minikin/FontCollection.h>
 #include <minikin/FontFamily.h>
 #include <minikin/SystemFonts.h>
+#include <utils/TraceUtils.h>
+
+#include <mutex>
+#include <unordered_map>
 
 using namespace android;
+using android::uirenderer::TraceUtils;
 
 static inline Typeface* toTypeface(jlong ptr) {
     return reinterpret_cast<Typeface*>(ptr);
@@ -149,6 +155,20 @@
                                            toTypeface(ptr)->fFontCollection);
 }
 
+static sk_sp<SkData> makeSkDataCached(const std::string& path) {
+    // We don't clear cache as Typeface objects created by Typeface_readTypefaces() will be stored
+    // in a static field and will not be garbage collected.
+    static std::unordered_map<std::string, sk_sp<SkData>> cache;
+    static std::mutex mutex;
+    ALOG_ASSERT(!path.empty());
+    std::lock_guard lock{mutex};
+    sk_sp<SkData>& entry = cache[path];
+    if (entry.get() == nullptr) {
+        entry = SkData::MakeFromFileName(path.c_str());
+    }
+    return entry;
+}
+
 static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia(
         minikin::BufferReader* reader) {
     std::string_view fontPath = reader->readString();
@@ -158,8 +178,9 @@
     std::tie(axesPtr, axesCount) = reader->readArray<minikin::FontVariation>();
     return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr<minikin::MinikinFont> {
         std::string path(fontPath.data(), fontPath.size());
-        sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str());
-        if (data == nullptr) {
+        ATRACE_FORMAT("Loading font %s", path.c_str());
+        sk_sp<SkData> data = makeSkDataCached(path);
+        if (data.get() == nullptr) {
             // This may happen if:
             // 1. When the process failed to open the file (e.g. invalid path or permission).
             // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
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/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index bfbdc5c..c6c9e9d 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -19,8 +19,6 @@
 #include <private/hwui/DrawGlInfo.h>
 #include "FunctorDrawable.h"
 #include "GrBackendSurface.h"
-#include "GrRenderTarget.h"
-#include "GrRenderTargetContext.h"
 #include "RenderNode.h"
 #include "SkAndroidFrameworkUtils.h"
 #include "SkClipStack.h"
@@ -40,19 +38,13 @@
 }
 
 static void GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
-    GrRenderTargetContext* renderTargetContext =
-            canvas->internal_private_accessTopLayerRenderTargetContext();
-    LOG_ALWAYS_FATAL_IF(!renderTargetContext, "Failed to retrieve GrRenderTargetContext");
-
-    GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
-    LOG_ALWAYS_FATAL_IF(!renderTarget, "accessRenderTarget failed");
-
+    GrBackendRenderTarget renderTarget = canvas->topLayerBackendRenderTarget();
     GrGLFramebufferInfo fboInfo;
-    LOG_ALWAYS_FATAL_IF(!renderTarget->getBackendRenderTarget().getGLFramebufferInfo(&fboInfo),
+    LOG_ALWAYS_FATAL_IF(!renderTarget.getGLFramebufferInfo(&fboInfo),
         "getGLFrameBufferInfo failed");
 
     *outFboID = fboInfo.fFBOID;
-    *outFboSize = SkISize::Make(renderTargetContext->width(), renderTargetContext->height());
+    *outFboSize = renderTarget.dimensions();
 }
 
 void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
@@ -75,7 +67,7 @@
     SkISize fboSize;
     GetFboDetails(canvas, &fboID, &fboSize);
 
-    SkIRect surfaceBounds = canvas->internal_private_getTopLayerBounds();
+    SkIRect surfaceBounds = canvas->topLayerBounds();
     SkIRect clipBounds = canvas->getDeviceClipBounds();
     SkM44 mat4(canvas->getLocalToDevice());
     SkRegion clipRegion;
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 158c349..c63f5d3 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -47,7 +47,7 @@
     }
 }
 
-bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
+bool SkiaDisplayList::reuseDisplayList(RenderNode* node) {
     reset();
     node->attachAvailableList(this);
     return true;
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index cdd00db..f2f19ba 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -98,7 +98,7 @@
      *
      * @return true if the displayList will be reused and therefore should not be deleted
      */
-    bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context);
+    bool reuseDisplayList(RenderNode* node);
 
     /**
      * ONLY to be called by RenderNode::syncDisplayList so that we can notify any
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index c4067af..03aeb55 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -44,15 +44,16 @@
                     skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
                 });
 
+        SkSamplingOptions sampling;
         Paint paint;
         sk_sp<SkImage> image = hwuiBitmap->makeImage();
         sk_sp<SkShader> repeatShader =
-                image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
+                image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, sampling);
         paint.setShader(std::move(repeatShader));
         canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
 
         sk_sp<SkShader> mirrorShader =
-                image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
+                image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror, sampling);
         paint.setShader(std::move(mirrorShader));
         canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
     }
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 5886ea3..564354f 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -74,6 +74,6 @@
 
     sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
         sk_sp<SkImage> image = bitmap.makeImage();
-        return image->makeShader();
+        return image->makeShader(SkSamplingOptions());
     }
 };
diff --git a/libs/hwui/tests/microbench/CanvasOpBench.cpp b/libs/hwui/tests/microbench/CanvasOpBench.cpp
new file mode 100644
index 0000000..ef5749e
--- /dev/null
+++ b/libs/hwui/tests/microbench/CanvasOpBench.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <benchmark/benchmark.h>
+
+#include "DisplayList.h"
+#include "hwui/Paint.h"
+#include "canvas/CanvasOpBuffer.h"
+#include "canvas/CanvasFrontend.h"
+#include "tests/common/TestUtils.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+void BM_CanvasOpBuffer_alloc(benchmark::State& benchState) {
+    while (benchState.KeepRunning()) {
+        auto displayList = new CanvasOpBuffer();
+        benchmark::DoNotOptimize(displayList);
+        delete displayList;
+    }
+}
+BENCHMARK(BM_CanvasOpBuffer_alloc);
+
+void BM_CanvasOpBuffer_record_saverestore(benchmark::State& benchState) {
+    CanvasFrontend<CanvasOpBuffer> canvas(100, 100);
+    while (benchState.KeepRunning()) {
+        canvas.reset(100, 100);
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.save(SaveFlags::MatrixClip);
+        benchmark::DoNotOptimize(&canvas);
+        canvas.restore();
+        canvas.restore();
+        canvas.finish();
+    }
+}
+BENCHMARK(BM_CanvasOpBuffer_record_saverestore);
+
+void BM_CanvasOpBuffer_record_saverestoreWithReuse(benchmark::State& benchState) {
+    CanvasFrontend<CanvasOpBuffer> canvas(100, 100);
+
+    while (benchState.KeepRunning()) {
+        canvas.reset(100, 100);
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.save(SaveFlags::MatrixClip);
+        benchmark::DoNotOptimize(&canvas);
+        canvas.restore();
+        canvas.restore();
+    }
+}
+BENCHMARK(BM_CanvasOpBuffer_record_saverestoreWithReuse);
+
+void BM_CanvasOpBuffer_record_simpleBitmapView(benchmark::State& benchState) {
+    CanvasFrontend<CanvasOpBuffer> canvas(100, 100);
+
+    Paint rectPaint;
+    sk_sp<Bitmap> iconBitmap(TestUtils::createBitmap(80, 80));
+
+    while (benchState.KeepRunning()) {
+        canvas.reset(100, 100);
+        {
+            canvas.save(SaveFlags::MatrixClip);
+            canvas.draw(CanvasOp<CanvasOpType::DrawRect> {
+                    .rect = SkRect::MakeWH(100, 100),
+                    .paint = rectPaint,
+            });
+            canvas.restore();
+        }
+        {
+            canvas.save(SaveFlags::MatrixClip);
+            canvas.translate(10, 10);
+            canvas.draw(CanvasOp<CanvasOpType::DrawImage> {
+                    iconBitmap,
+                    0,
+                    0,
+                    SkPaint{}
+            });
+            canvas.restore();
+        }
+        benchmark::DoNotOptimize(&canvas);
+        canvas.finish();
+    }
+}
+BENCHMARK(BM_CanvasOpBuffer_record_simpleBitmapView);
diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp
index 206dcd5..011939a 100644
--- a/libs/hwui/tests/microbench/RenderNodeBench.cpp
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -30,3 +30,29 @@
     }
 }
 BENCHMARK(BM_RenderNode_create);
+
+void BM_RenderNode_recordSimple(benchmark::State& state) {
+    sp<RenderNode> node = new RenderNode();
+    std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
+    delete canvas->finishRecording();
+
+    while (state.KeepRunning()) {
+        canvas->resetRecording(100, 100, node.get());
+        canvas->drawColor(0x00000000, SkBlendMode::kSrcOver);
+        node->setStagingDisplayList(canvas->finishRecording());
+    }
+}
+BENCHMARK(BM_RenderNode_recordSimple);
+
+void BM_RenderNode_recordSimpleWithReuse(benchmark::State& state) {
+    sp<RenderNode> node = new RenderNode();
+    std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
+    delete canvas->finishRecording();
+
+    while (state.KeepRunning()) {
+        canvas->resetRecording(100, 100, node.get());
+        canvas->drawColor(0x00000000, SkBlendMode::kSrcOver);
+        canvas->finishRecording()->reuseDisplayList(node.get());
+    }
+}
+BENCHMARK(BM_RenderNode_recordSimpleWithReuse);
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index 033a587..a09e742 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -36,50 +36,6 @@
 // We lazy
 using Op = CanvasOpType;
 
-enum MockTypes {
-    Lifecycle,
-    COUNT
-};
-
-template<MockTypes T>
-struct MockOp;
-
-template<MockTypes T>
-struct MockOpContainer {
-    OpBufferItemHeader<MockTypes> header;
-    MockOp<T> impl;
-};
-
-struct LifecycleTracker {
-    int ctor_count = 0;
-    int dtor_count = 0;
-
-    int alive() { return ctor_count - dtor_count; }
-};
-
-template<>
-struct MockOp<MockTypes::Lifecycle> {
-    MockOp() = delete;
-    void operator=(const MockOp&) = delete;
-
-    MockOp(LifecycleTracker* tracker) : tracker(tracker) {
-        tracker->ctor_count += 1;
-    }
-
-    MockOp(const MockOp& other) {
-        tracker = other.tracker;
-        tracker->ctor_count += 1;
-    }
-
-    ~MockOp() {
-        tracker->dtor_count += 1;
-    }
-
-    LifecycleTracker* tracker = nullptr;
-};
-
-using MockBuffer = OpBuffer<MockTypes, MockOpContainer>;
-
 class CanvasOpCountingReceiver {
 public:
     template <CanvasOpType T>
@@ -104,62 +60,6 @@
     return count;
 }
 
-TEST(CanvasOp, lifecycleCheck) {
-    LifecycleTracker tracker;
-    {
-        MockBuffer buffer;
-        buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
-            .impl = MockOp<MockTypes::Lifecycle>{&tracker}
-        });
-        EXPECT_EQ(tracker.alive(), 1);
-        buffer.clear();
-        EXPECT_EQ(tracker.alive(), 0);
-    }
-    EXPECT_EQ(tracker.alive(), 0);
-}
-
-TEST(CanvasOp, lifecycleCheckMove) {
-    LifecycleTracker tracker;
-    {
-        MockBuffer buffer;
-        buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
-            .impl = MockOp<MockTypes::Lifecycle>{&tracker}
-        });
-        EXPECT_EQ(tracker.alive(), 1);
-        {
-            MockBuffer other(std::move(buffer));
-            EXPECT_EQ(tracker.alive(), 1);
-            EXPECT_EQ(buffer.size(), 0);
-            EXPECT_GT(other.size(), 0);
-            EXPECT_EQ(1, countItems(other));
-            EXPECT_EQ(0, countItems(buffer));
-
-            other.push_container(MockOpContainer<MockTypes::Lifecycle> {
-                .impl = MockOp<MockTypes::Lifecycle>{&tracker}
-            });
-
-            EXPECT_EQ(2, countItems(other));
-            EXPECT_EQ(2, tracker.alive());
-
-            buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
-                .impl = MockOp<MockTypes::Lifecycle>{&tracker}
-            });
-            EXPECT_EQ(1, countItems(buffer));
-            EXPECT_EQ(3, tracker.alive());
-
-            buffer = std::move(other);
-            EXPECT_EQ(2, countItems(buffer));
-            EXPECT_EQ(2, tracker.alive());
-        }
-        EXPECT_EQ(2, countItems(buffer));
-        EXPECT_EQ(2, tracker.alive());
-        buffer.clear();
-        EXPECT_EQ(0, countItems(buffer));
-        EXPECT_EQ(0, tracker.alive());
-    }
-    EXPECT_EQ(tracker.alive(), 0);
-}
-
 TEST(CanvasOp, verifyConst) {
     CanvasOpBuffer buffer;
     buffer.push<Op::DrawColor>({
@@ -708,7 +608,3 @@
     EXPECT_EQ(1, receiver[Op::Save]);
     EXPECT_EQ(1, receiver[Op::Restore]);
 }
-
-TEST(CanvasOp, frontendTransform) {
-
-}
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/OpBufferTests.cpp b/libs/hwui/tests/unit/OpBufferTests.cpp
new file mode 100644
index 0000000..c0ae943
--- /dev/null
+++ b/libs/hwui/tests/unit/OpBufferTests.cpp
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <canvas/OpBuffer.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+enum MockTypes {
+    Lifecycle,
+    NoOp,
+    IntHolder,
+    COUNT
+};
+
+using Op = MockTypes;
+
+template<MockTypes T>
+struct MockOp;
+
+template<MockTypes T>
+struct MockOpContainer {
+    OpBufferItemHeader<MockTypes> header;
+    MockOp<T> impl;
+
+    MockOpContainer(MockOp<T>&& impl) : impl(std::move(impl)) {}
+};
+
+struct LifecycleTracker {
+    int ctor_count = 0;
+    int dtor_count = 0;
+
+    int alive() { return ctor_count - dtor_count; }
+};
+
+template<>
+struct MockOp<MockTypes::Lifecycle> {
+    MockOp() = delete;
+    void operator=(const MockOp&) = delete;
+
+    MockOp(LifecycleTracker* tracker) : tracker(tracker) {
+        tracker->ctor_count += 1;
+    }
+
+    MockOp(const MockOp& other) {
+        tracker = other.tracker;
+        tracker->ctor_count += 1;
+    }
+
+    ~MockOp() {
+        tracker->dtor_count += 1;
+    }
+
+    LifecycleTracker* tracker = nullptr;
+};
+
+template<>
+struct MockOp<MockTypes::NoOp> {};
+
+template<>
+struct MockOp<MockTypes::IntHolder> {
+    int value = -1;
+};
+
+struct MockBuffer : public OpBuffer<MockTypes, MockOpContainer> {
+    template <MockTypes T>
+    void push(MockOp<T>&& op) {
+        push_container(MockOpContainer<T>{std::move(op)});
+    }
+};
+
+template<typename T>
+static int countItems(const T& t) {
+    int count = 0;
+    t.for_each([&](auto i) {
+        count++;
+    });
+    return count;
+}
+
+TEST(OpBuffer, lifecycleCheck) {
+    LifecycleTracker tracker;
+    {
+        MockBuffer buffer;
+        buffer.push_container(MockOpContainer<Op::Lifecycle> {
+            MockOp<MockTypes::Lifecycle>{&tracker}
+        });
+        EXPECT_EQ(tracker.alive(), 1);
+        buffer.clear();
+        EXPECT_EQ(tracker.alive(), 0);
+    }
+    EXPECT_EQ(tracker.alive(), 0);
+}
+
+TEST(OpBuffer, lifecycleCheckMove) {
+    LifecycleTracker tracker;
+    {
+        MockBuffer buffer;
+        buffer.push_container(MockOpContainer<Op::Lifecycle> {
+            MockOp<MockTypes::Lifecycle>{&tracker}
+        });
+        EXPECT_EQ(tracker.alive(), 1);
+        {
+            MockBuffer other(std::move(buffer));
+            EXPECT_EQ(tracker.alive(), 1);
+            EXPECT_EQ(buffer.size(), 0);
+            EXPECT_GT(other.size(), 0);
+            EXPECT_EQ(1, countItems(other));
+            EXPECT_EQ(0, countItems(buffer));
+
+            other.push_container(MockOpContainer<MockTypes::Lifecycle> {
+                MockOp<MockTypes::Lifecycle>{&tracker}
+            });
+
+            EXPECT_EQ(2, countItems(other));
+            EXPECT_EQ(2, tracker.alive());
+
+            buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
+                MockOp<MockTypes::Lifecycle>{&tracker}
+            });
+            EXPECT_EQ(1, countItems(buffer));
+            EXPECT_EQ(3, tracker.alive());
+
+            buffer = std::move(other);
+            EXPECT_EQ(2, countItems(buffer));
+            EXPECT_EQ(2, tracker.alive());
+        }
+        EXPECT_EQ(2, countItems(buffer));
+        EXPECT_EQ(2, tracker.alive());
+        buffer.clear();
+        EXPECT_EQ(0, countItems(buffer));
+        EXPECT_EQ(0, tracker.alive());
+    }
+    EXPECT_EQ(tracker.alive(), 0);
+}
+
+TEST(OpBuffer, verifyConst) {
+    MockBuffer buffer;
+    buffer.push<Op::IntHolder>({42});
+    buffer.for_each([](auto op) {
+        static_assert(std::is_const_v<std::remove_reference_t<decltype(*op)>>,
+                "Expected container to be const");
+    });
+}
+
+TEST(OpBuffer, filterView) {
+    MockBuffer buffer;
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::IntHolder>({0});
+    buffer.push<Op::IntHolder>({1});
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::IntHolder>({2});
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::NoOp>({});
+    buffer.push<Op::NoOp>({});
+
+
+    int index = 0;
+    for (const auto& it : buffer.filter<Op::IntHolder>()) {
+        ASSERT_EQ(Op::IntHolder, it.header.type);
+        EXPECT_EQ(index, it.impl.value);
+        index++;
+    }
+    EXPECT_EQ(index, 3);
+
+    int count = 0;
+    for (const auto& it : buffer.filter<Op::NoOp>()) {
+        ASSERT_EQ(Op::NoOp, it.header.type);
+        count++;
+    }
+    EXPECT_EQ(count, 7);
+}
+
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 2d34b09..c63f008 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -84,7 +84,7 @@
 
     // attach a displayList for reuse
     SkiaDisplayList skiaDL;
-    ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
+    ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get()));
 
     // detach the list that you just attempted to reuse
     availableList = renderNode->detachAvailableList();
diff --git a/libs/incident/OWNERS b/libs/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/libs/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/libs/input/OWNERS b/libs/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/libs/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/libs/storage/OWNERS b/libs/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/libs/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/libs/usb/OWNERS b/libs/usb/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/libs/usb/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/location/OWNERS b/location/OWNERS
new file mode 100644
index 0000000..5ac6028
--- /dev/null
+++ b/location/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/location/java/android/location/GnssMeasurementRequest.aidl b/location/java/android/location/GnssMeasurementRequest.aidl
new file mode 100644
index 0000000..7e50728
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+parcelable GnssMeasurementRequest;
diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java
new file mode 100644
index 0000000..613f591
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementRequest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains extra parameters to pass in a GNSS measurement request.
+ */
+public final class GnssMeasurementRequest implements Parcelable {
+    private final boolean mFullTracking;
+
+    /**
+     * Creates a {@link GnssMeasurementRequest} with a full list of parameters.
+     */
+    private GnssMeasurementRequest(boolean fullTracking) {
+        mFullTracking = fullTracking;
+    }
+
+    /**
+     * Represents whether to enable full GNSS tracking.
+     *
+     * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+     * discontinuities are expected, and when supported, carrier phase should be continuous in
+     * good signal conditions. All non-blocklisted, healthy constellations, satellites and
+     * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+     * will consume more power in full tracking mode than in duty cycling mode. If false, GNSS
+     * chipset optimizes power via duty cycling, constellations and frequency limits, etc.
+     *
+     * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+     * including GNSS location.
+     */
+    public boolean isFullTracking() {
+        return mFullTracking;
+    }
+
+    @NonNull
+    public static final Creator<GnssMeasurementRequest> CREATOR =
+            new Creator<GnssMeasurementRequest>() {
+                @Override
+                @NonNull
+                public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) {
+                    return new GnssMeasurementRequest(parcel.readBoolean());
+                }
+
+                @Override
+                public GnssMeasurementRequest[] newArray(int i) {
+                    return new GnssMeasurementRequest[i];
+                }
+            };
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
+        parcel.writeBoolean(mFullTracking);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("GnssMeasurementRequest[");
+        if (mFullTracking) {
+            s.append("FullTracking");
+        }
+        s.append(']');
+        return s.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (!(obj instanceof GnssMeasurementRequest)) return false;
+
+        GnssMeasurementRequest other = (GnssMeasurementRequest) obj;
+        if (mFullTracking != other.mFullTracking) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return mFullTracking ? 1 : 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Builder for {@link GnssMeasurementRequest} */
+    public static final class Builder {
+        private boolean mFullTracking;
+
+        /**
+         * Constructs a {@link Builder} instance.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}.
+         */
+        public Builder(@NonNull GnssMeasurementRequest request) {
+            mFullTracking = request.isFullTracking();
+        }
+
+        /**
+         * Set the value of whether to enable full GNSS tracking, which is false by default.
+         *
+         * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+         * discontinuities are expected, and when supported, carrier phase should be continuous in
+         * good signal conditions. All non-blocklisted, healthy constellations, satellites and
+         * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+         * will consume more power in full tracking mode than in duty cycling mode. If false,
+         * GNSS chipset optimizes power via duty cycling, constellations and frequency limits, etc.
+         *
+         * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+         * including GNSS location.
+         *
+         * <p>Full tracking requests always override non-full tracking requests. If any full
+         * tracking request occurs, all listeners on the device will receive full tracking GNSS
+         * measurements.
+         */
+        @NonNull public Builder setFullTracking(boolean value) {
+            mFullTracking = value;
+            return this;
+        }
+
+        /** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */
+        @NonNull
+        public GnssMeasurementRequest build() {
+            return new GnssMeasurementRequest(mFullTracking);
+        }
+    }
+}
diff --git a/location/java/android/location/GnssRequest.java b/location/java/android/location/GnssRequest.java
index 5fc9161..9c9766f 100644
--- a/location/java/android/location/GnssRequest.java
+++ b/location/java/android/location/GnssRequest.java
@@ -45,11 +45,23 @@
      * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
      * is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
      * duty cycling, constellations and frequency limits, etc.
+     *
+     * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+     * including GNSS location.
      */
     public boolean isFullTracking() {
         return mFullTracking;
     }
 
+    /**
+     * Converts the {@link GnssRequest} into a {@link GnssMeasurementRequest}.
+     * @hide
+     */
+    @NonNull
+    public GnssMeasurementRequest toGnssMeasurementRequest() {
+        return new GnssMeasurementRequest.Builder().setFullTracking(isFullTracking()).build();
+    }
+
     @NonNull
     public static final Creator<GnssRequest> CREATOR =
             new Creator<GnssRequest>() {
@@ -131,6 +143,9 @@
          * is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
          * duty cycling, constellations and frequency limits, etc.
          *
+         * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+         * including GNSS location.
+         *
          * <p>Full tracking requests always override non-full tracking requests. If any full
          * tracking request occurs, all listeners on the device will receive full tracking GNSS
          * measurements.
diff --git a/location/java/android/location/GnssSignalQuality.java b/location/java/android/location/GnssSignalQuality.java
new file mode 100644
index 0000000..7945f3e
--- /dev/null
+++ b/location/java/android/location/GnssSignalQuality.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.server.location.ServerLocationProtoEnums;
+
+/**
+ * Gnss signal quality information.
+ *
+ * @hide
+ */
+public interface GnssSignalQuality {
+
+    int GNSS_SIGNAL_QUALITY_UNKNOWN =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
+
+    int GNSS_SIGNAL_QUALITY_POOR =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
+
+    int GNSS_SIGNAL_QUALITY_GOOD =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
+
+    int NUM_GNSS_SIGNAL_QUALITY_LEVELS = GNSS_SIGNAL_QUALITY_GOOD + 1;
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 92e2136..a666eb4 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -22,7 +22,7 @@
 import android.location.GeocoderParams;
 import android.location.Geofence;
 import android.location.GnssMeasurementCorrections;
-import android.location.GnssRequest;
+import android.location.GnssMeasurementRequest;
 import android.location.IGeocodeListener;
 import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
@@ -78,7 +78,7 @@
     void registerGnssStatusCallback(in IGnssStatusListener callback, String packageName, String attributionTag);
     void unregisterGnssStatusCallback(in IGnssStatusListener callback);
 
-    void addGnssMeasurementsListener(in GnssRequest request, in IGnssMeasurementsListener listener, String packageName, String attributionTag);
+    void addGnssMeasurementsListener(in GnssMeasurementRequest request, in IGnssMeasurementsListener listener, String packageName, String attributionTag);
     void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
     void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections);
 
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index b4392b1..a7e9a0d 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,6 +19,7 @@
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -1048,11 +1049,7 @@
      * <ul>
      * <li> satellites - the number of satellites used to derive the fix
      * </ul>
-     *
-     * @deprecated Do not use. For GNSS related information, prefer listening for GNSS status
-     *             information via {@link LocationManager}.
      */
-    @Deprecated
     public Bundle getExtras() {
         return mExtras;
     }
@@ -1062,11 +1059,8 @@
      *
      * <p>Note this stores a copy of the given extras, so any changes to extras after calling this
      * method won't be reflected in the location bundle.
-     *
-     * @deprecated Do not use.
      */
-    @Deprecated
-    public void setExtras(Bundle extras) {
+    public void setExtras(@Nullable Bundle extras) {
         mExtras = (extras == null) ? null : new Bundle(extras);
     }
 
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 7085a75..ecdba1f 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -159,21 +159,21 @@
     public static final long BLOCK_GPS_STATUS_USAGE = 144027538L;
 
     /**
-     * Name of the network location provider.
+     * Standard name of the network location provider.
      *
-     * <p>This provider determines location based on nearby of cell tower and WiFi access points.
-     * Results are retrieved by means of a network lookup.
+     * <p>If present, this provider determines location based on nearby of cell tower and WiFi
+     * access points. Operation of this provider may require a data connection.
      */
     public static final String NETWORK_PROVIDER = "network";
 
     /**
-     * Name of the GNSS location provider.
+     * Standard name of the GNSS location provider.
      *
-     * <p>This provider determines location using GNSS satellites. Depending on conditions, this
-     * provider may take a while to return a location fix. Requires the
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+     * <p>If present, this provider determines location using GNSS satellites. The responsiveness
+     * and accuracy of location fixes may depend on GNSS signal conditions.
      *
-     * <p>The extras Bundle for the GPS location provider can contain the following key/value pairs:
+     * <p>The extras Bundle for locations derived by this location provider may contain the
+     * following key/value pairs:
      * <ul>
      * <li> satellites - the number of satellites used to derive the fix
      * </ul>
@@ -181,29 +181,22 @@
     public static final String GPS_PROVIDER = "gps";
 
     /**
-     * A special location provider for receiving locations without actually initiating a location
-     * fix.
+     * A special location provider for receiving locations without actively initiating a location
+     * fix. This location provider is always present.
      *
      * <p>This provider can be used to passively receive location updates when other applications or
      * services request them without actually requesting the locations yourself. This provider will
-     * only return locations generated by other providers.  You can query the
-     * {@link Location#getProvider()} method to determine the actual provider that supplied the
-     * location update. Requires the {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
-     * permission, although there is no guarantee of fine locations.
+     * only return locations generated by other providers.
      */
     public static final String PASSIVE_PROVIDER = "passive";
 
     /**
-     * The fused location provider.
+     * Standard name of the fused location provider.
      *
-     * <p>This provider may combine inputs from several location sources to provide the
-     * best possible location fix. It is implicitly used for all API's that involve the
-     * {@link LocationRequest} object.
-     *
-     * @hide
+     * <p>If present, this provider may combine inputs from several other location providers to
+     * provide the best possible location fix. It is implicitly used for all requestLocationUpdates
+     * APIs that involve a {@link Criteria}.
      */
-    @SystemApi
-    @TestApi
     public static final String FUSED_PROVIDER = "fused";
 
     /**
@@ -918,6 +911,9 @@
     /**
      * Register for a single location update using a Criteria and a callback.
      *
+     * <p>Note: Since Android KitKat, Criteria requests will always result in using the
+     * {@link #FUSED_PROVIDER}.
+     *
      * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
      * on how to use this method.
      *
@@ -985,6 +981,9 @@
     /**
      * Register for a single location update using a Criteria and pending intent.
      *
+     * <p>Note: Since Android KitKat, Criteria requests will always result in using the
+     * {@link #FUSED_PROVIDER}.
+     *
      * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
      * on how to use this method.
      *
@@ -1113,6 +1112,9 @@
      * Register for location updates using a provider selected through the given Criteria, and a
      * callback on the specified {@link Looper}.
      *
+     * <p>Note: Since Android KitKat, Criteria requests will always result in using the
+     * {@link #FUSED_PROVIDER}.
+     *
      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
      * for more detail on how this method works.
      *
@@ -1124,7 +1126,12 @@
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if listener is null
      * @throws SecurityException if no suitable permission is present
+     *
+     * @deprecated Use
+     * {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} instead to
+     * explicitly select a provider.
      */
+    @Deprecated
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(long minTimeMs, float minDistanceM,
             @NonNull Criteria criteria, @NonNull LocationListener listener,
@@ -1138,6 +1145,9 @@
      * Register for location updates using a provider selected through the given Criteria, and a
      * callback on the specified {@link Executor}.
      *
+     * <p>Note: Since Android KitKat, Criteria requests will always result in using the
+     * {@link #FUSED_PROVIDER}.
+     *
      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
      * for more detail on how this method works.
      *
@@ -1151,7 +1161,12 @@
      * @throws IllegalArgumentException if executor is null
      * @throws IllegalArgumentException if listener is null
      * @throws SecurityException        if no suitable permission is present
+     *
+     * @deprecated Use
+     * {@link #requestLocationUpdates(String, long, float, Executor, LocationListener)} instead to
+     * explicitly select a provider.
      */
+    @Deprecated
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(
             long minTimeMs,
@@ -1199,6 +1214,9 @@
      * Register for location updates using a provider selected through the given Criteria, and
      * callbacks delivered via the provided {@link PendingIntent}.
      *
+     * <p>Note: Since Android KitKat, Criteria requests will always result in using the
+     * {@link #FUSED_PROVIDER}.
+     *
      * <p>See {@link #requestLocationUpdates(String, long, float, PendingIntent)} for more detail on
      * how this method works.
      *
@@ -1210,7 +1228,11 @@
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if pendingIntent is null
      * @throws SecurityException if no suitable permission is present
+     *
+     * @deprecated Use {@link #requestLocationUpdates(String, long, float, PendingIntent)} instead
+     * to explicitly select a provider.
      */
+    @Deprecated
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(long minTimeMs, float minDistanceM,
             @NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) {
@@ -1594,9 +1616,8 @@
     }
 
     /**
-     * Returns a list of the names of all known location providers. All providers are returned,
-     * including ones that are not permitted to be accessed by the calling activity or are currently
-     * disabled.
+     * Returns a list of the names of all available location providers. All providers are returned,
+     * including those that are currently disabled.
      *
      * @return list of provider names
      */
@@ -1609,8 +1630,8 @@
     }
 
     /**
-     * Returns a list of the names of location providers. Only providers that the caller has
-     * permission to access will be returned.
+     * Returns a list of the names of available location providers. If {@code enabledOnly} is false,
+     * this is functionally the same as {@link #getAllProviders()}.
      *
      * @param enabledOnly if true then only enabled providers are included
      * @return list of provider names
@@ -1624,8 +1645,7 @@
     }
 
     /**
-     * Returns a list of the names of providers that satisfy the given criteria. Only providers that
-     * the caller has permission to access will be returned.
+     * Returns a list of the names of available location providers that satisfy the given criteria.
      *
      * @param criteria the criteria that providers must match
      * @param enabledOnly if true then only enabled providers are included
@@ -2351,7 +2371,7 @@
             handler = new Handler();
         }
 
-        return registerGnssMeasurementsCallback(new GnssRequest.Builder().build(),
+        return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
                 new HandlerExecutor(handler), callback);
     }
 
@@ -2370,8 +2390,8 @@
     public boolean registerGnssMeasurementsCallback(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull GnssMeasurementsEvent.Callback callback) {
-        return registerGnssMeasurementsCallback(new GnssRequest.Builder().build(), executor,
-                callback);
+        return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
+                executor, callback);
     }
 
     /**
@@ -2388,14 +2408,42 @@
      * @throws IllegalArgumentException if callback is null
      * @throws SecurityException        if the ACCESS_FINE_LOCATION permission is not present
      * @hide
+     * @deprecated Use {@link #registerGnssMeasurementsCallback(GnssMeasurementRequest, Executor,
+     * GnssMeasurementsEvent.Callback)} instead.
      */
+    @Deprecated
     @SystemApi
-    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, LOCATION_HARDWARE})
+    @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssMeasurementsCallback(
             @NonNull GnssRequest request,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull GnssMeasurementsEvent.Callback callback) {
         Preconditions.checkArgument(request != null, "invalid null request");
+        getGnssMeasurementsTransportMultiplexer().addListener(request.toGnssMeasurementRequest(),
+                callback, executor);
+        return true;
+    }
+
+    /**
+     * Registers a GNSS measurement callback.
+     *
+     * @param request  extra parameters to pass to GNSS measurement provider. For example, if {@link
+     *                 GnssMeasurementRequest#isFullTracking()} is true, GNSS chipset switches off
+     *                 duty cycling.
+     * @param executor the executor that the callback runs on
+     * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
+     * @return {@code true} always if the callback was added successfully, {@code false} otherwise.
+     * @throws IllegalArgumentException if request is null
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if callback is null
+     * @throws SecurityException        if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssMeasurementsCallback(
+            @NonNull GnssMeasurementRequest request,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull GnssMeasurementsEvent.Callback callback) {
+        Preconditions.checkArgument(request != null, "invalid null request");
         getGnssMeasurementsTransportMultiplexer().addListener(request, callback, executor);
         return true;
     }
@@ -2887,14 +2935,14 @@
     }
 
     private class GnssMeasurementsTransportMultiplexer extends
-            ListenerTransportMultiplexer<GnssRequest, GnssMeasurementsEvent.Callback> {
+            ListenerTransportMultiplexer<GnssMeasurementRequest, GnssMeasurementsEvent.Callback> {
 
         private @Nullable IGnssMeasurementsListener mListenerTransport;
 
         GnssMeasurementsTransportMultiplexer() {}
 
         @Override
-        protected void registerWithServer(GnssRequest request) throws RemoteException {
+        protected void registerWithServer(GnssMeasurementRequest request) throws RemoteException {
             IGnssMeasurementsListener transport = mListenerTransport;
             if (transport == null) {
                 transport = new GnssMeasurementsListener();
@@ -2917,9 +2965,10 @@
         }
 
         @Override
-        protected GnssRequest mergeRequests(Collection<GnssRequest> requests) {
-            GnssRequest.Builder builder = new GnssRequest.Builder();
-            for (GnssRequest request : requests) {
+        protected GnssMeasurementRequest mergeRequests(
+                Collection<GnssMeasurementRequest> requests) {
+            GnssMeasurementRequest.Builder builder = new GnssMeasurementRequest.Builder();
+            for (GnssMeasurementRequest request : requests) {
                 if (request.isFullTracking()) {
                     builder.setFullTracking(true);
                     break;
diff --git a/location/java/android/location/OWNERS b/location/java/android/location/OWNERS
new file mode 100644
index 0000000..6032144
--- /dev/null
+++ b/location/java/android/location/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 880425
+
+sooniln@google.com
+wyattriley@google.com
+yuhany@google.com
+weiwa@google.com
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 0822cda..dd8a8c3 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -16,6 +16,11 @@
 
 package com.android.internal.location.gnssmetrics;
 
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD;
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_POOR;
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN;
+import static android.location.GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS;
+
 import android.app.StatsManager;
 import android.content.Context;
 import android.location.GnssStatus;
@@ -23,7 +28,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.connectivity.GpsBatteryStats;
-import android.server.location.ServerLocationProtoEnums;
 import android.text.format.DateUtils;
 import android.util.Base64;
 import android.util.Log;
@@ -50,17 +54,6 @@
 
     private static final String TAG = "GnssMetrics";
 
-    private static final int GPS_SIGNAL_QUALITY_UNKNOWN =
-            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
-
-    private static final int GPS_SIGNAL_QUALITY_POOR =
-            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
-
-    private static final int GPS_SIGNAL_QUALITY_GOOD =
-            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
-
-    public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
-
     /** Default time between location fixes (in millisecs) */
     private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
 
@@ -397,7 +390,7 @@
                     stats.getLoggingDurationMs() / ((double) DateUtils.MINUTE_IN_MILLIS)).append(
                     "\n");
             long[] t = stats.getTimeInGpsSignalQualityLevel();
-            if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+            if (t != null && t.length == NUM_GNSS_SIGNAL_QUALITY_LEVELS) {
                 s.append("  Amount of time (while on battery) Top 4 Avg CN0 > "
                         + GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ
                         + " dB-Hz (min): ").append(
@@ -512,7 +505,7 @@
           // so that
             // the first CNO report will trigger an update to BatteryStats
             mLastAverageCn0 = -100.0;
-            mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
+            mLastSignalLevel = GNSS_SIGNAL_QUALITY_UNKNOWN;
         }
 
         /**
@@ -584,9 +577,9 @@
          */
         private int getSignalLevel(double cn0) {
             if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
-                return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+                return GNSS_SIGNAL_QUALITY_GOOD;
             }
-            return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+            return GNSS_SIGNAL_QUALITY_POOR;
         }
     }
 
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/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 19354e0..bcc846b 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1235,53 +1235,59 @@
         return usageToString(mUsage);
     }
 
-    /** @hide */
-    public static String usageToString(int usage) {
+    /**
+     * Returns the string representation for the usage constant passed as parameter.
+     *
+     * @param usage one of the {@link AudioAttributes} usage constants
+     * @return string representing the {@link AudioAttributes} usage constant passed as a parameter
+     */
+    @NonNull
+    public static String usageToString(@AttributeSdkUsage int usage) {
         switch(usage) {
             case USAGE_UNKNOWN:
-                return new String("USAGE_UNKNOWN");
+                return "USAGE_UNKNOWN";
             case USAGE_MEDIA:
-                return new String("USAGE_MEDIA");
+                return "USAGE_MEDIA";
             case USAGE_VOICE_COMMUNICATION:
-                return new String("USAGE_VOICE_COMMUNICATION");
+                return "USAGE_VOICE_COMMUNICATION";
             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
-                return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
+                return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
             case USAGE_ALARM:
-                return new String("USAGE_ALARM");
+                return "USAGE_ALARM";
             case USAGE_NOTIFICATION:
-                return new String("USAGE_NOTIFICATION");
+                return "USAGE_NOTIFICATION";
             case USAGE_NOTIFICATION_RINGTONE:
-                return new String("USAGE_NOTIFICATION_RINGTONE");
+                return "USAGE_NOTIFICATION_RINGTONE";
             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-                return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
+                return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-                return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
+                return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-                return new String("USAGE_NOTIFICATION_COMMUNICATION_DELAYED");
+                return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
             case USAGE_NOTIFICATION_EVENT:
-                return new String("USAGE_NOTIFICATION_EVENT");
+                return "USAGE_NOTIFICATION_EVENT";
             case USAGE_ASSISTANCE_ACCESSIBILITY:
-                return new String("USAGE_ASSISTANCE_ACCESSIBILITY");
+                return "USAGE_ASSISTANCE_ACCESSIBILITY";
             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-                return new String("USAGE_ASSISTANCE_NAVIGATION_GUIDANCE");
+                return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
             case USAGE_ASSISTANCE_SONIFICATION:
-                return new String("USAGE_ASSISTANCE_SONIFICATION");
+                return "USAGE_ASSISTANCE_SONIFICATION";
             case USAGE_GAME:
-                return new String("USAGE_GAME");
+                return "USAGE_GAME";
             case USAGE_ASSISTANT:
-                return new String("USAGE_ASSISTANT");
+                return "USAGE_ASSISTANT";
             case USAGE_CALL_ASSISTANT:
-                return new String("USAGE_CALL_ASSISTANT");
+                return "USAGE_CALL_ASSISTANT";
             case USAGE_EMERGENCY:
-                return new String("USAGE_EMERGENCY");
+                return "USAGE_EMERGENCY";
             case USAGE_SAFETY:
-                return new String("USAGE_SAFETY");
+                return "USAGE_SAFETY";
             case USAGE_VEHICLE_STATUS:
-                return new String("USAGE_VEHICLE_STATUS");
+                return "USAGE_VEHICLE_STATUS";
             case USAGE_ANNOUNCEMENT:
-                return new String("USAGE_ANNOUNCEMENT");
+                return "USAGE_ANNOUNCEMENT";
             default:
-                return new String("unknown usage " + usage);
+                return "unknown usage " + usage;
         }
     }
 
diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java
index 6c8b500..7caac89 100644
--- a/media/java/android/media/AudioDeviceAttributes.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -120,7 +120,13 @@
         mAddress = address;
     }
 
-    /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
+    /**
+     * @hide
+     * Constructor from internal device type and address
+     * @param type the internal device type, as defined in {@link AudioSystem}
+     * @param address the address of the device, or an empty string for devices without one
+     */
+    public AudioDeviceAttributes(int nativeType, @NonNull String address) {
         mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
         mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
         mAddress = address;
@@ -191,10 +197,8 @@
     public String toString() {
         return new String("AudioDeviceAttributes:"
                 + " role:" + roleToString(mRole)
-                + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
-                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
-                        : AudioSystem.getInputDeviceName(
-                                AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)))
+                + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
+                        : AudioSystem.getInputDeviceName(mNativeType))
                 + " addr:" + mAddress);
     }
 
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index b67851a..2a3704d 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -23,6 +23,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 import java.util.TreeSet;
 
@@ -498,6 +499,13 @@
     }
 
     /**
+     * @return A list of {@link AudioProfile} supported by the audio devices.
+     */
+    public @NonNull List<AudioProfile> getAudioProfiles() {
+        return mPort.profiles();
+    }
+
+    /**
      * Returns an array of supported encapsulation modes for the device.
      *
      * The array can include any of the {@code AudioTrack} encapsulation modes,
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 0f79675..9c42bf7 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * The AudioDevicePort is a specialized type of AudioPort
@@ -57,6 +58,18 @@
         mEncapsulationMetadataTypes = encapsulationMetadataTypes;
     }
 
+    AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles,
+            AudioGain[] gains, int type, String address, int[] encapsulationModes,
+              @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes) {
+        super(handle,
+                AudioManager.isInputDevice(type) ? AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK,
+                deviceName, profiles, gains);
+        mType = type;
+        mAddress = address;
+        mEncapsulationModes = encapsulationModes;
+        mEncapsulationMetadataTypes = encapsulationMetadataTypes;
+    }
+
     /**
      * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
      */
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4578883..367b784 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2319,7 +2319,55 @@
         if (attributes == null) {
             throw new NullPointerException("Illegal null AudioAttributes");
         }
-        return AudioSystem.isOffloadSupported(format, attributes);
+        return AudioSystem.getOffloadSupport(format, attributes) != PLAYBACK_OFFLOAD_NOT_SUPPORTED;
+    }
+
+    /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
+        offload playback not supported */
+    public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = AudioSystem.OFFLOAD_NOT_SUPPORTED;
+    /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
+        offload playback supported */
+    public static final int PLAYBACK_OFFLOAD_SUPPORTED = AudioSystem.OFFLOAD_SUPPORTED;
+    /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
+        offload playback supported with gapless transitions */
+    public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED =
+            AudioSystem.OFFLOAD_GAPLESS_SUPPORTED;
+
+    /** @hide */
+    @IntDef(flag = false, prefix = "PLAYBACK_OFFLOAD_", value = {
+            PLAYBACK_OFFLOAD_NOT_SUPPORTED,
+            PLAYBACK_OFFLOAD_SUPPORTED,
+            PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED }
+    )
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioOffloadMode {}
+
+    /**
+     * Returns whether offloaded playback of an audio format is supported on the device or not and
+     * when supported whether gapless transitions are possible or not.
+     * <p>Offloaded playback is the feature where the decoding and playback of an audio stream
+     * is not competing with other software resources. In general, it is supported by dedicated
+     * hardware, such as audio DSPs.
+     * <p>Note that this query only provides information about the support of an audio format,
+     * it does not indicate whether the resources necessary for the offloaded playback are
+     * available at that instant.
+     * @param format the audio format (codec, sample rate, channels) being checked.
+     * @param attributes the {@link AudioAttributes} to be used for playback
+     * @return {@link #PLAYBACK_OFFLOAD_NOT_SUPPORTED} if offload playback if not supported,
+     *         {@link #PLAYBACK_OFFLOAD_SUPPORTED} if offload playback is supported or
+     *         {@link #PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} if gapless transitions are
+     *         also supported.
+     */
+    @AudioOffloadMode
+    public static int getPlaybackOffloadSupport(@NonNull AudioFormat format,
+            @NonNull AudioAttributes attributes) {
+        if (format == null) {
+            throw new NullPointerException("Illegal null AudioFormat");
+        }
+        if (attributes == null) {
+            throw new NullPointerException("Illegal null AudioAttributes");
+        }
+        return AudioSystem.getOffloadSupport(format, attributes);
     }
 
     //====================================================================
@@ -2881,7 +2929,12 @@
      * @return true if any music tracks are active.
      */
     public boolean isMusicActive() {
-        return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
+        final IAudioService service = getService();
+        try {
+            return service.isMusicActive(false /*remotely*/);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2892,7 +2945,12 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean isMusicActiveRemotely() {
-        return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0);
+        final IAudioService service = getService();
+        try {
+            return service.isMusicActive(true /*remotely*/);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -5055,7 +5113,12 @@
         case STREAM_NOTIFICATION:
         case STREAM_DTMF:
         case STREAM_ACCESSIBILITY:
-            return AudioSystem.getDevicesForStream(streamType);
+            final IAudioService service = getService();
+            try {
+                return service.getDevicesForStream(streamType);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         default:
             return 0;
         }
@@ -6120,6 +6183,29 @@
     }
 
     /**
+     * Returns an {@link AudioDeviceInfo} corresponding to the specified {@link AudioPort} ID.
+     * @param portId The audio port ID to look up for.
+     * @param flags A set of bitflags specifying the criteria to test.
+     * @see #GET_DEVICES_OUTPUTS
+     * @see #GET_DEVICES_INPUTS
+     * @see #GET_DEVICES_ALL
+     * @return An AudioDeviceInfo or null if no device with matching port ID is found.
+     * @hide
+     */
+    public static AudioDeviceInfo getDeviceForPortId(int portId, int flags) {
+        if (portId == 0) {
+            return null;
+        }
+        AudioDeviceInfo[] devices = getDevicesStatic(flags);
+        for (AudioDeviceInfo device : devices) {
+            if (device.getId() == portId) {
+                return device;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Registers an {@link AudioDeviceCallback} object to receive notifications of changes
      * to the set of connected audio devices.
      * @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect
@@ -6806,6 +6892,297 @@
         return hwSyncId;
     }
 
+    /**
+     * Selects the audio device that should be used for communication use cases, for instance voice
+     * or video calls. This method can be used by voice or video chat applications to select a
+     * different audio device than the one selected by default by the platform.
+     * <p>The device selection is expressed as an {@link AudioDeviceInfo}, of role sink
+     * ({@link AudioDeviceInfo#isSink()} is <code>true</code>) and of one of the following types:
+     * <ul>
+     *   <li> {@link AudioDeviceInfo#TYPE_BUILTIN_EARPIECE}
+     *   <li> {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}
+     *   <li> {@link AudioDeviceInfo#TYPE_WIRED_HEADSET}
+     *   <li> {@link AudioDeviceInfo#TYPE_BLUETOOTH_SCO}
+     *   <li> {@link AudioDeviceInfo#TYPE_USB_HEADSET}
+     *   <li> {@link AudioDeviceInfo#TYPE_BLE_HEADSET}
+     * </ul>
+     * The selection is active as long as the requesting application lives, until
+     * {@link #clearDeviceForCommunication} is called or until the device is disconnected.
+     * It is therefore important for applications to clear the request when a call ends or the
+     * application is paused.
+     * <p>In case of simultaneous requests by multiple applications the priority is given to the
+     * application currently controlling the audio mode (see {@link #setMode(int)}). This is the
+     * latest application having selected mode {@link #MODE_IN_COMMUNICATION} or mode
+     * {@link #MODE_IN_CALL}. Note that <code>MODE_IN_CALL</code> can only be selected by the main
+     * telephony application with permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE}.
+     * <p> If the requested devices is not currently available, the request will be rejected and
+     * the method will return false.
+     * <p>This API replaces the following deprecated APIs:
+     * <ul>
+     *   <li> {@link #startBluetoothSco()}
+     *   <li> {@link #stopBluetoothSco()}
+     *   <li> {@link #setSpeakerphoneOn(boolean)}
+     * </ul>
+     * <h4>Example</h4>
+     * <p>The example below shows how to enable and disable speakerphone mode.
+     * <pre class="prettyprint">
+     * // Get an AudioManager instance
+     * AudioManager audioManager = Context.getSystemService(AudioManager.class);
+     * try {
+     *     AudioDeviceInfo speakerDevice = null;
+     *     AudioDeviceInfo[] devices = audioManager.getDevices(GET_DEVICES_OUTPUTS);
+     *     for (AudioDeviceInfo device : devices) {
+     *         if (device.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
+     *             speakerDevice = device;
+     *             break;
+     *         }
+     *     }
+     *     if (speakerDevice != null) {
+     *         // Turn speakerphone ON.
+     *         boolean result = audioManager.setDeviceForCommunication(speakerDevice);
+     *         if (!result) {
+     *             // Handle error.
+     *         }
+     *         // Turn speakerphone OFF.
+     *         audioManager.clearDeviceForCommunication();
+     *     }
+     * } catch (IllegalArgumentException e) {
+     *     // Handle exception.
+     * }
+     * </pre>
+     * @param device the requested audio device.
+     * @return <code>true</code> if the request was accepted, <code>false</code> otherwise.
+     * @throws IllegalArgumentException If an invalid device is specified.
+     */
+    public boolean setDeviceForCommunication(@NonNull AudioDeviceInfo device) {
+        Objects.requireNonNull(device);
+        try {
+            if (device.getId() == 0) {
+                throw new IllegalArgumentException("In valid device: " + device);
+            }
+            return getService().setDeviceForCommunication(mICallBack, device.getId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Cancels previous communication device selection made with
+     * {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+     */
+    public void clearDeviceForCommunication() {
+        try {
+            getService().setDeviceForCommunication(mICallBack, 0);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns currently selected audio device for communication.
+     * <p>This API replaces the following deprecated APIs:
+     * <ul>
+     *   <li> {@link #isBluetoothScoOn()}
+     *   <li> {@link #isSpeakerphoneOn()}
+     * </ul>
+     * @return an {@link AudioDeviceInfo} indicating which audio device is
+     * currently selected or communication use cases or null if default selection
+     * is used.
+     */
+    @Nullable
+    public AudioDeviceInfo getDeviceForCommunication() {
+        try {
+            return getDeviceForPortId(
+                    getService().getDeviceForCommunication(), GET_DEVICES_OUTPUTS);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     * Returns an {@link AudioDeviceInfo} corresponding to a connected device of the type provided.
+     * The type must be a valid output type defined in <code>AudioDeviceInfo</code> class,
+     * for instance {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}.
+     * The method will return null if no device of the provided type is connected.
+     * If more than one device of the provided type is connected, an object corresponding to the
+     * first device encountered in the enumeration list will be returned.
+     * @param deviceType The device device for which an <code>AudioDeviceInfo</code>
+     * object is queried.
+     * @return An AudioDeviceInfo object or null if no device with the requested type is connected.
+     * @throws IllegalArgumentException If an invalid device type is specified.
+     */
+    @TestApi
+    @Nullable
+    public static AudioDeviceInfo getDeviceInfoFromType(
+            @AudioDeviceInfo.AudioDeviceTypeOut int deviceType) {
+        AudioDeviceInfo[] devices = getDevicesStatic(GET_DEVICES_OUTPUTS);
+        for (AudioDeviceInfo device : devices) {
+            if (device.getType() == deviceType) {
+                return device;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Listener registered by client to be notified upon communication audio device change.
+     * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+     */
+    public interface OnCommunicationDeviceChangedListener {
+        /**
+         * Callback method called upon communication audio device change.
+         * @param device the audio device selected for communication use cases
+         */
+        void onCommunicationDeviceChanged(@Nullable AudioDeviceInfo device);
+    }
+
+    /**
+     * Adds a listener for being notified of changes to the communication audio device.
+     * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+     * @param executor
+     * @param listener
+     */
+    public void addOnCommunicationDeviceChangedListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnCommunicationDeviceChangedListener listener) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(listener);
+        synchronized (mCommDevListenerLock) {
+            if (hasCommDevListener(listener)) {
+                throw new IllegalArgumentException(
+                        "attempt to call addOnCommunicationDeviceChangedListener() "
+                                + "on a previously registered listener");
+            }
+            // lazy initialization of the list of strategy-preferred device listener
+            if (mCommDevListeners == null) {
+                mCommDevListeners = new ArrayList<>();
+            }
+            final int oldCbCount = mCommDevListeners.size();
+            mCommDevListeners.add(new CommDevListenerInfo(listener, executor));
+            if (oldCbCount == 0 && mCommDevListeners.size() > 0) {
+                // register binder for callbacks
+                if (mCommDevDispatcherStub == null) {
+                    mCommDevDispatcherStub = new CommunicationDeviceDispatcherStub();
+                }
+                try {
+                    getService().registerCommunicationDeviceDispatcher(mCommDevDispatcherStub);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a previously added listener of changes to the communication audio device.
+     * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+     * @param listener
+     */
+    public void removeOnCommunicationDeviceChangedListener(
+            @NonNull OnCommunicationDeviceChangedListener listener) {
+        Objects.requireNonNull(listener);
+        synchronized (mCommDevListenerLock) {
+            if (!removeCommDevListener(listener)) {
+                throw new IllegalArgumentException(
+                        "attempt to call removeOnCommunicationDeviceChangedListener() "
+                                + "on an unregistered listener");
+            }
+            if (mCommDevListeners.size() == 0) {
+                // unregister binder for callbacks
+                try {
+                    getService().unregisterCommunicationDeviceDispatcher(
+                            mCommDevDispatcherStub);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                } finally {
+                    mCommDevDispatcherStub = null;
+                    mCommDevListeners = null;
+                }
+            }
+        }
+    }
+
+    private final Object mCommDevListenerLock = new Object();
+    /**
+     * List of listeners for preferred device for strategy and their associated Executor.
+     * List is lazy-initialized on first registration
+     */
+    @GuardedBy("mCommDevListenerLock")
+    private @Nullable ArrayList<CommDevListenerInfo> mCommDevListeners;
+
+    private static class CommDevListenerInfo {
+        final @NonNull OnCommunicationDeviceChangedListener mListener;
+        final @NonNull Executor mExecutor;
+
+        CommDevListenerInfo(OnCommunicationDeviceChangedListener listener, Executor exe) {
+            mListener = listener;
+            mExecutor = exe;
+        }
+    }
+
+    @GuardedBy("mCommDevListenerLock")
+    private CommunicationDeviceDispatcherStub mCommDevDispatcherStub;
+
+    private final class CommunicationDeviceDispatcherStub
+            extends ICommunicationDeviceDispatcher.Stub {
+
+        @Override
+        public void dispatchCommunicationDeviceChanged(int portId) {
+            // make a shallow copy of listeners so callback is not executed under lock
+            final ArrayList<CommDevListenerInfo> commDevListeners;
+            synchronized (mCommDevListenerLock) {
+                if (mCommDevListeners == null || mCommDevListeners.size() == 0) {
+                    return;
+                }
+                commDevListeners = (ArrayList<CommDevListenerInfo>) mCommDevListeners.clone();
+            }
+            AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS);
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                for (CommDevListenerInfo info : commDevListeners) {
+                    info.mExecutor.execute(() ->
+                            info.mListener.onCommunicationDeviceChanged(device));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @GuardedBy("mCommDevListenerLock")
+    private @Nullable CommDevListenerInfo getCommDevListenerInfo(
+            OnCommunicationDeviceChangedListener listener) {
+        if (mCommDevListeners == null) {
+            return null;
+        }
+        for (CommDevListenerInfo info : mCommDevListeners) {
+            if (info.mListener == listener) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    @GuardedBy("mCommDevListenerLock")
+    private boolean hasCommDevListener(OnCommunicationDeviceChangedListener listener) {
+        return getCommDevListenerInfo(listener) != null;
+    }
+
+    @GuardedBy("mCommDevListenerLock")
+    /**
+     * @return true if the listener was removed from the list
+     */
+    private boolean removeCommDevListener(OnCommunicationDeviceChangedListener listener) {
+        final CommDevListenerInfo infoToRemove = getCommDevListenerInfo(listener);
+        if (infoToRemove != null) {
+            mCommDevListeners.remove(infoToRemove);
+            return true;
+        }
+        return false;
+    }
+
     //---------------------------------------------------------
     // Inner classes
     //--------------------
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index 0e286b0..7f2249d 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -19,6 +19,8 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 
+import java.util.List;
+
 /**
  * The AudioMixPort is a specialized type of AudioPort
  * describing an audio mix or stream at an input or output stream of the audio
@@ -42,6 +44,12 @@
         mIoHandle = ioHandle;
     }
 
+    AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
+            List<AudioProfile> profiles, AudioGain[] gains) {
+        super(handle, role, deviceName, profiles, gains);
+        mIoHandle = ioHandle;
+    }
+
     /**
      * Build a specific configuration of this audio mix port for use by methods
      * like AudioManager.connectAudioPatch().
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index 515e9d0..b9f449c 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -21,6 +21,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Binder;
 import android.os.IBinder;
@@ -47,6 +48,8 @@
     public static final int PLAYER_PIID_INVALID = -1;
     /** @hide */
     public static final int PLAYER_UPID_INVALID = -1;
+    /** @hide */
+    public static final int PLAYER_DEVICEID_INVALID = 0;
 
     // information about the implementation
     /**
@@ -89,9 +92,8 @@
     /**
      * @hide
      * Player backed an AAudio player.
-     * Note this type is not in System API so it will not be returned in public API calls
      */
-    // TODO unhide for SystemApi, update getPlayerType()
+    @SystemApi
     public static final int PLAYER_TYPE_AAUDIO = 13;
 
     /**
@@ -159,6 +161,11 @@
      */
     @SystemApi
     public static final int PLAYER_STATE_STOPPED = 4;
+    /**
+     * @hide
+     * The state used to update device id, does not actually change the state of the player
+     */
+    public static final int PLAYER_UPDATE_DEVICE_ID = 5;
 
     /** @hide */
     @IntDef({
@@ -167,7 +174,8 @@
         PLAYER_STATE_IDLE,
         PLAYER_STATE_STARTED,
         PLAYER_STATE_PAUSED,
-        PLAYER_STATE_STOPPED
+        PLAYER_STATE_STOPPED,
+        PLAYER_UPDATE_DEVICE_ID
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PlayerState {}
@@ -185,6 +193,8 @@
     private int mPlayerState;
     private AudioAttributes mPlayerAttr; // never null
 
+    private int mDeviceId;
+
     /**
      * Never use without initializing parameters afterwards
      */
@@ -202,6 +212,7 @@
         mPlayerType = pic.mPlayerType;
         mClientUid = uid;
         mClientPid = pid;
+        mDeviceId = PLAYER_DEVICEID_INVALID;
         mPlayerState = PLAYER_STATE_IDLE;
         mPlayerAttr = pic.mAttributes;
         if ((sPlayerDeathMonitor != null) && (pic.mIPlayer != null)) {
@@ -242,6 +253,7 @@
                         in.mPlayerAttr.getAllowedCapturePolicy() == ALLOW_CAPTURE_BY_ALL
                         ? ALLOW_CAPTURE_BY_ALL : ALLOW_CAPTURE_BY_NONE)
                 .build();
+        anonymCopy.mDeviceId = in.mDeviceId;
         // anonymized data
         anonymCopy.mPlayerType = PLAYER_TYPE_UNKNOWN;
         anonymCopy.mClientUid = PLAYER_UPID_INVALID;
@@ -279,11 +291,27 @@
     }
 
     /**
+     * Returns information about the {@link AudioDeviceInfo} used for this playback.
+     * @return the audio playback device or null if the device is not available at the time of query
+     */
+    public @Nullable AudioDeviceInfo getAudioDevice() {
+        if (mDeviceId == PLAYER_DEVICEID_INVALID) {
+            return null;
+        }
+        // TODO(175802592): change this to AudioManager.getDeviceForPortId() when available
+        AudioDeviceInfo[] devices =
+                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
+        for (int i = 0; i < devices.length; i++) {
+            if (devices[i].getId() == mDeviceId) {
+                return devices[i];
+            }
+        }
+        return null;
+    }
+
+    /**
      * @hide
-     * Return the type of player linked to this configuration. The return value is one of
-     * {@link #PLAYER_TYPE_JAM_AUDIOTRACK}, {@link #PLAYER_TYPE_JAM_MEDIAPLAYER},
-     * {@link #PLAYER_TYPE_JAM_SOUNDPOOL}, {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE},
-     * {@link #PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD}, or {@link #PLAYER_TYPE_UNKNOWN}.
+     * Return the type of player linked to this configuration.
      * <br>Note that player types not exposed in the system API will be represented as
      * {@link #PLAYER_TYPE_UNKNOWN}.
      * @return the type of the player.
@@ -291,7 +319,6 @@
     @SystemApi
     public @PlayerType int getPlayerType() {
         switch (mPlayerType) {
-            case PLAYER_TYPE_AAUDIO:
             case PLAYER_TYPE_HW_SOURCE:
             case PLAYER_TYPE_EXTERNAL_PROXY:
                 return PLAYER_TYPE_UNKNOWN;
@@ -364,13 +391,29 @@
      * @hide
      * Handle a player state change
      * @param event
+     * @param deviceId active device id or {@Code PLAYER_DEVICEID_INVALID}
+     * <br>Note device id is valid for {@code PLAYER_UPDATE_DEVICE_ID} or
+     * <br>{@code PLAYER_STATE_STARTED} events, as the device id will be reset to none when
+     * <br>pausing or stopping playback. It will be set to active device when playback starts or
+     * <br>it will be changed when PLAYER_UPDATE_DEVICE_ID is sent. The latter can happen if the
+     * <br>device changes in the middle of playback.
      * @return true if the state changed, false otherwise
      */
-    public boolean handleStateEvent(int event) {
-        final boolean changed;
+    public boolean handleStateEvent(int event, int deviceId) {
+        boolean changed = false;
         synchronized (this) {
-            changed = (mPlayerState != event);
-            mPlayerState = event;
+
+            // Do not update if it is only device id update
+            if (event != PLAYER_UPDATE_DEVICE_ID) {
+                changed = (mPlayerState != event);
+                mPlayerState = event;
+            }
+
+            if (event == PLAYER_STATE_STARTED || event == PLAYER_UPDATE_DEVICE_ID) {
+                changed = changed || (mDeviceId != deviceId);
+                mDeviceId = deviceId;
+            }
+
             if (changed && (event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) {
                 mIPlayerShell.release();
                 mIPlayerShell = null;
@@ -441,7 +484,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mPlayerIId, mPlayerType, mClientUid, mClientPid);
+        return Objects.hash(mPlayerIId, mDeviceId, mPlayerType, mClientUid, mClientPid);
     }
 
     @Override
@@ -452,6 +495,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mPlayerIId);
+        dest.writeInt(mDeviceId);
         dest.writeInt(mPlayerType);
         dest.writeInt(mClientUid);
         dest.writeInt(mClientPid);
@@ -466,6 +510,7 @@
 
     private AudioPlaybackConfiguration(Parcel in) {
         mPlayerIId = in.readInt();
+        mDeviceId = in.readInt();
         mPlayerType = in.readInt();
         mClientUid = in.readInt();
         mClientPid = in.readInt();
@@ -483,6 +528,7 @@
         AudioPlaybackConfiguration that = (AudioPlaybackConfiguration) o;
 
         return ((mPlayerIId == that.mPlayerIId)
+                && (mDeviceId == that.mDeviceId)
                 && (mPlayerType == that.mPlayerType)
                 && (mClientUid == that.mClientUid)
                 && (mClientPid == that.mClientPid));
@@ -491,6 +537,7 @@
     @Override
     public String toString() {
         return "AudioPlaybackConfiguration piid:" + mPlayerIId
+                + " deviceId:" + mDeviceId
                 + " type:" + toLogFriendlyPlayerType(mPlayerType)
                 + " u/pid:" + mClientUid + "/" + mClientPid
                 + " state:" + toLogFriendlyPlayerState(mPlayerState)
@@ -576,6 +623,7 @@
             case PLAYER_STATE_STARTED: return "started";
             case PLAYER_STATE_PAUSED: return "paused";
             case PLAYER_STATE_STOPPED: return "stopped";
+            case PLAYER_UPDATE_DEVICE_ID: return "device";
             default:
                 return "unknown player state - FIXME";
         }
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index e6dc622..0302250 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -19,6 +19,13 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 /**
  * An audio port is a node of the audio framework or hardware that can be connected to or
  * disconnect from another audio node to create a specific audio routing configuration.
@@ -78,6 +85,7 @@
     private final int[] mChannelMasks;
     private final int[] mChannelIndexMasks;
     private final int[] mFormats;
+    private final List<AudioProfile> mProfiles;
     @UnsupportedAppUsage
     private final AudioGain[] mGains;
     @UnsupportedAppUsage
@@ -87,7 +95,6 @@
     AudioPort(AudioHandle handle, int role, String name,
             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains) {
-
         mHandle = handle;
         mRole = role;
         mName = name;
@@ -96,6 +103,39 @@
         mChannelIndexMasks = channelIndexMasks;
         mFormats = formats;
         mGains = gains;
+        mProfiles = new ArrayList<>();
+        if (mFormats != null) {
+            for (int format : mFormats) {
+                mProfiles.add(new AudioProfile(
+                        format, samplingRates, channelMasks, channelIndexMasks));
+            }
+        }
+    }
+
+    AudioPort(AudioHandle handle, int role, String name,
+            List<AudioProfile> profiles, AudioGain[] gains) {
+        mHandle = handle;
+        mRole = role;
+        mName = name;
+        mProfiles = profiles;
+        mGains = gains;
+        Set<Integer> formats = new HashSet<>();
+        Set<Integer> samplingRates = new HashSet<>();
+        Set<Integer> channelMasks = new HashSet<>();
+        Set<Integer> channelIndexMasks = new HashSet<>();
+        for (AudioProfile profile : profiles) {
+            formats.add(profile.getFormat());
+            samplingRates.addAll(Arrays.stream(profile.getSampleRates()).boxed()
+                    .collect(Collectors.toList()));
+            channelMasks.addAll(Arrays.stream(profile.getChannelMasks()).boxed()
+                    .collect(Collectors.toList()));
+            channelIndexMasks.addAll(Arrays.stream(profile.getChannelIndexMasks()).boxed()
+                    .collect(Collectors.toList()));
+        }
+        mSamplingRates = samplingRates.stream().mapToInt(Number::intValue).toArray();
+        mChannelMasks = channelMasks.stream().mapToInt(Number::intValue).toArray();
+        mChannelIndexMasks = channelIndexMasks.stream().mapToInt(Number::intValue).toArray();
+        mFormats = formats.stream().mapToInt(Number::intValue).toArray();
     }
 
     AudioHandle handle() {
@@ -163,6 +203,13 @@
     }
 
     /**
+     * Get the list of supported audio profiles
+     */
+    public List<AudioProfile> profiles() {
+        return mProfiles;
+    }
+
+    /**
      * Get the list of gain descriptors
      * Empty array if this port does not have gain control
      */
diff --git a/media/java/android/media/AudioProfile.java b/media/java/android/media/AudioProfile.java
new file mode 100644
index 0000000..4204166
--- /dev/null
+++ b/media/java/android/media/AudioProfile.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+
+/**
+ * AudioProfile is a class used by {@link AudioDeviceInfo} to list the audio formats, sampling rates
+ * and channel masks supported.
+ * Each AudioProfile is specific to an audio format and lists all sampling rates and channel masks
+ * supported for this format.
+ */
+public class AudioProfile {
+    private final int mFormat;
+    private final int[] mSamplingRates;
+    private final int[] mChannelMasks;
+    private final int[] mChannelIndexMasks;
+
+    AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks,
+                 @NonNull int[] channelIndexMasks) {
+        mFormat = format;
+        mSamplingRates = samplingRates;
+        mChannelMasks = channelMasks;
+        mChannelIndexMasks = channelIndexMasks;
+    }
+
+    /**
+     * @return the encoding format for this AudioProfile.
+     */
+    public @AudioFormat.Encoding int getFormat() {
+        return mFormat;
+    }
+
+    /**
+     * @return an array of channel position masks that are associated with the encoding format.
+     */
+    public @NonNull int[] getChannelMasks() {
+        return mChannelMasks;
+    }
+
+    /**
+     * @return an array of channel index masks that are associated with the encoding format.
+     */
+    public @NonNull int[] getChannelIndexMasks() {
+        return mChannelIndexMasks;
+    }
+
+    /**
+     * @return an array of sample rates that are associated with the encoding format.
+     */
+    public @NonNull int[] getSampleRates() {
+        return mSamplingRates;
+    }
+}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index bd27f6d..164b194 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1639,13 +1639,22 @@
      */
     public static native int setAllowedCapturePolicy(int uid, int flags);
 
-    static boolean isOffloadSupported(@NonNull AudioFormat format, @NonNull AudioAttributes attr) {
-        return native_is_offload_supported(format.getEncoding(), format.getSampleRate(),
+    /**
+     * @hide
+     * Compressed audio offload decoding modes supported by audio HAL implementation.
+     * Keep in sync with system/media/include/media/audio.h.
+     */
+    public static final int OFFLOAD_NOT_SUPPORTED = 0;
+    public static final int OFFLOAD_SUPPORTED = 1;
+    public static final int OFFLOAD_GAPLESS_SUPPORTED = 2;
+
+    static int getOffloadSupport(@NonNull AudioFormat format, @NonNull AudioAttributes attr) {
+        return native_get_offload_support(format.getEncoding(), format.getSampleRate(),
                 format.getChannelMask(), format.getChannelIndexMask(),
                 attr.getVolumeControlStream());
     }
 
-    private static native boolean native_is_offload_supported(int encoding, int sampleRate,
+    private static native int native_get_offload_support(int encoding, int sampleRate,
             int channelMask, int channelIndexMask, int streamType);
 
     /** @hide */
@@ -1721,7 +1730,7 @@
         int[] types = new int[devices.size()];
         String[] addresses = new String[devices.size()];
         for (int i = 0; i < devices.size(); ++i) {
-            types[i] = AudioDeviceInfo.convertDeviceTypeToInternalDevice(devices.get(i).getType());
+            types[i] = devices.get(i).getInternalType();
             addresses[i] = devices.get(i).getAddress();
         }
         return setDevicesRoleForStrategy(strategy, role, types, addresses);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index e8c6206..e9a18e9 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1256,7 +1256,8 @@
                     throw new UnsupportedOperationException(
                             "Offload and low latency modes are incompatible");
                 }
-                if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) {
+                if (AudioSystem.getOffloadSupport(mFormat, mAttributes)
+                        == AudioSystem.OFFLOAD_NOT_SUPPORTED) {
                     throw new UnsupportedOperationException(
                             "Cannot create AudioTrack, offload format / attributes not supported");
                 }
@@ -1823,6 +1824,7 @@
 
     @Override
     protected void finalize() {
+        tryToDisableNativeRoutingCallback();
         baseRelease();
         native_finalize();
     }
@@ -2716,9 +2718,15 @@
     }
 
     private void startImpl() {
+        synchronized (mRoutingChangeListeners) {
+            if (!mEnableSelfRoutingMonitor) {
+                testEnableNativeRoutingCallbacksLocked();
+                mEnableSelfRoutingMonitor = true;
+            }
+        }
         synchronized(mPlayStateLock) {
-            baseStart();
             native_start();
+            baseStart(native_getRoutedDeviceId());
             if (mPlayState == PLAYSTATE_PAUSED_STOPPING) {
                 mPlayState = PLAYSTATE_STOPPING;
             } else {
@@ -2756,6 +2764,7 @@
                 mPlayStateLock.notify();
             }
         }
+        tryToDisableNativeRoutingCallback();
     }
 
     /**
@@ -3495,12 +3504,21 @@
         return null;
     }
 
+    private void tryToDisableNativeRoutingCallback() {
+        synchronized (mRoutingChangeListeners) {
+            if (mEnableSelfRoutingMonitor) {
+                mEnableSelfRoutingMonitor = false;
+                testDisableNativeRoutingCallbacksLocked();
+            }
+        }
+    }
+
     /*
      * Call BEFORE adding a routing callback handler.
      */
     @GuardedBy("mRoutingChangeListeners")
     private void testEnableNativeRoutingCallbacksLocked() {
-        if (mRoutingChangeListeners.size() == 0) {
+        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
             native_enableDeviceCallback();
         }
     }
@@ -3510,7 +3528,7 @@
      */
     @GuardedBy("mRoutingChangeListeners")
     private void testDisableNativeRoutingCallbacksLocked() {
-        if (mRoutingChangeListeners.size() == 0) {
+        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
             native_disableDeviceCallback();
         }
     }
@@ -3527,6 +3545,9 @@
     private ArrayMap<AudioRouting.OnRoutingChangedListener,
             NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
 
+    @GuardedBy("mRoutingChangeListeners")
+    private boolean mEnableSelfRoutingMonitor;
+
    /**
     * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
     * changes on this AudioTrack.
@@ -3626,6 +3647,7 @@
      */
     private void broadcastRoutingChange() {
         AudioManager.resetAudioPortGeneration();
+        baseUpdateDeviceId(getRoutedDevice());
         synchronized (mRoutingChangeListeners) {
             for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
                 delegate.notifyClient();
diff --git a/media/java/android/media/HwAudioSource.java b/media/java/android/media/HwAudioSource.java
index 01a02f1..bbf632a 100644
--- a/media/java/android/media/HwAudioSource.java
+++ b/media/java/android/media/HwAudioSource.java
@@ -22,6 +22,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+
 /**
  * The HwAudioSource represents the audio playback directly from a source audio device.
  * It currently supports {@link HwAudioSource#start()} and {@link HwAudioSource#stop()} only
@@ -130,10 +132,32 @@
      */
     public void start() {
         Preconditions.checkState(!isPlaying(), "HwAudioSource is currently playing");
-        baseStart();
         mNativeHandle = AudioSystem.startAudioSource(
                 mAudioDeviceInfo.getPort().activeConfig(),
                 mAudioAttributes);
+        // FIXME: b/174876389 clean up device id reporting
+        baseStart(getDeviceId());
+    }
+
+    private int getDeviceId() {
+        ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
+        if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
+            return 0;
+        }
+
+        for (int i = 0; i < patches.size(); i++) {
+            AudioPatch patch = patches.get(i);
+            AudioPortConfig[] sources = patch.sources();
+            AudioPortConfig[] sinks = patch.sinks();
+            if ((sources != null) && (sources.length > 0)) {
+                for (int c = 0;  c < sources.length; c++) {
+                    if (sources[c].port().id() == mAudioDeviceInfo.getId()) {
+                        return sinks[c].port().id();
+                    }
+                }
+            }
+        }
+        return 0;
     }
 
     /**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5c012be..b6bb3a3 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -28,6 +28,7 @@
 import android.media.IAudioRoutesObserver;
 import android.media.IAudioServerStateDispatcher;
 import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
 import android.media.IPlaybackConfigDispatcher;
 import android.media.IRecordingConfigDispatcher;
 import android.media.IRingtonePlayer;
@@ -62,7 +63,7 @@
 
     oneway void playerAttributes(in int piid, in AudioAttributes attr);
 
-    oneway void playerEvent(in int piid, in int event);
+    oneway void playerEvent(in int piid, in int event, in int deviceId);
 
     oneway void releasePlayer(in int piid);
 
@@ -334,4 +335,17 @@
     oneway void setStreamVolumeForUid(int streamType, int direction, int flags,
             in String packageName, int uid, int pid, in UserHandle userHandle,
             int targetSdkVersion);
+
+    boolean isMusicActive(in boolean remotely);
+
+    int getDevicesForStream(in int streamType);
+
+    boolean setDeviceForCommunication(IBinder cb, int portId);
+
+    int getDeviceForCommunication();
+
+    void registerCommunicationDeviceDispatcher(ICommunicationDeviceDispatcher dispatcher);
+
+    oneway void unregisterCommunicationDeviceDispatcher(
+            ICommunicationDeviceDispatcher dispatcher);
 }
diff --git a/media/java/android/media/ICommunicationDeviceDispatcher.aidl b/media/java/android/media/ICommunicationDeviceDispatcher.aidl
new file mode 100644
index 0000000..429f934
--- /dev/null
+++ b/media/java/android/media/ICommunicationDeviceDispatcher.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * AIDL for AudioService to signal audio communication device updates.
+ *
+ * {@hide}
+ */
+oneway interface ICommunicationDeviceDispatcher {
+
+    void dispatchCommunicationDeviceChanged(int portId);
+
+}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 068f968..4b8a8ad 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -73,6 +73,8 @@
     void unregisterManager(IMediaRouter2Manager manager);
     void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
             in MediaRoute2Info route, int volume);
+    void startScan(IMediaRouter2Manager manager);
+    void stopScan(IMediaRouter2Manager manager);
 
     void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId,
             in RoutingSessionInfo oldSession, in @nullable MediaRoute2Info route);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index c2168f1..9657b25e 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -25,6 +25,7 @@
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
+import android.os.Process;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Pair;
@@ -188,13 +189,14 @@
 
     // COMMON CONSTANTS
     private static final Range<Integer> POSITIVE_INTEGERS =
-        Range.create(1, Integer.MAX_VALUE);
+            Range.create(1, Integer.MAX_VALUE);
     private static final Range<Long> POSITIVE_LONGS =
-        Range.create(1l, Long.MAX_VALUE);
+            Range.create(1L, Long.MAX_VALUE);
     private static final Range<Rational> POSITIVE_RATIONALS =
-        Range.create(new Rational(1, Integer.MAX_VALUE),
-                     new Rational(Integer.MAX_VALUE, 1));
-    private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
+            Range.create(new Rational(1, Integer.MAX_VALUE),
+                         new Rational(Integer.MAX_VALUE, 1));
+    private static final Range<Integer> SIZE_RANGE =
+            Process.is64Bit() ? Range.create(1, 32768) : Range.create(1, 4096);
     private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
     private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
     private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
@@ -1399,6 +1401,9 @@
 
         /**
          * Returns the range of supported video widths.
+         * <p class=note>
+         * 32-bit processes will not support resolutions larger than 4096x4096 due to
+         * the limited address space.
          */
         public Range<Integer> getSupportedWidths() {
             return mWidthRange;
@@ -1406,6 +1411,9 @@
 
         /**
          * Returns the range of supported video heights.
+         * <p class=note>
+         * 32-bit processes will not support resolutions larger than 4096x4096 due to
+         * the limited address space.
          */
         public Range<Integer> getSupportedHeights() {
             return mHeightRange;
@@ -1997,6 +2005,12 @@
          * Performance points assume a single active codec. For use cases where multiple
          * codecs are active, should use that highest pixel count, and add the frame rates of
          * each individual codec.
+         * <p class=note>
+         * 32-bit processes will not support resolutions larger than 4096x4096 due to
+         * the limited address space, but performance points will be presented as is.
+         * In other words, even though a component publishes a performance point for
+         * a resolution higher than 4096x4096, it does not mean that the resolution is supported
+         * for 32-bit processes.
          */
         @Nullable
         public List<PerformancePoint> getSupportedPerformancePoints() {
@@ -2164,6 +2178,12 @@
                 if (size == null || size.getWidth() * size.getHeight() <= 0) {
                     continue;
                 }
+                if (size.getWidth() > SIZE_RANGE.getUpper()
+                        || size.getHeight() > SIZE_RANGE.getUpper()) {
+                    size = new Size(
+                            Math.min(size.getWidth(), SIZE_RANGE.getUpper()),
+                            Math.min(size.getHeight(), SIZE_RANGE.getUpper()));
+                }
                 Range<Long> range = Utils.parseLongRange(map.get(key), null);
                 if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
                     continue;
@@ -2193,6 +2213,7 @@
                                (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) :
                        (a.getMaxFrameRate() != b.getMaxFrameRate()) ?
                                (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0));
+
             return Collections.unmodifiableList(ret);
         }
 
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index a17ff82..babc1d5 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -19,7 +19,7 @@
 import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.NetworkUtils;
+import android.net.InetAddresses;
 import android.os.IBinder;
 import android.os.StrictMode;
 import android.util.Log;
@@ -214,7 +214,7 @@
             if (host.equalsIgnoreCase("localhost")) {
                 return true;
             }
-            if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
+            if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) {
                 return true;
             }
         } catch (IllegalArgumentException iex) {
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 86d1d15..32a9168 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -1313,14 +1313,14 @@
     public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;
 
     /**
-     * If the media contains EXIF data, this key retrieves the offset value
+     * If the media contains EXIF data, this key retrieves the offset (in bytes)
      * of the data.
      */
     public static final int METADATA_KEY_EXIF_OFFSET = 33;
 
     /**
-     * If the media contains EXIF data, this key retrieves the length of the
-     * data.
+     * If the media contains EXIF data, this key retrieves the length (in bytes)
+     * of the data.
      */
     public static final int METADATA_KEY_EXIF_LENGTH = 34;
 
@@ -1371,5 +1371,21 @@
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40;
 
+    /**
+     * If the media contains XMP data, this key retrieves the offset (in bytes)
+     * of the data.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int METADATA_KEY_XMP_OFFSET = 41;
+
+    /**
+     * If the media contains XMP data, this key retrieves the length (in bytes)
+     * of the data.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int METADATA_KEY_XMP_LENGTH = 42;
+
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index f8311cd..ceac2c9 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1352,7 +1352,6 @@
     }
 
     private void startImpl() {
-        baseStart();
         stayAwake(true);
         _start();
     }
@@ -1378,7 +1377,6 @@
     public void stop() throws IllegalStateException {
         stayAwake(false);
         _stop();
-        baseStop();
     }
 
     private native void _stop() throws IllegalStateException;
@@ -1392,7 +1390,6 @@
     public void pause() throws IllegalStateException {
         stayAwake(false);
         _pause();
-        basePause();
     }
 
     private native void _pause() throws IllegalStateException;
@@ -1497,13 +1494,60 @@
         return null;
     }
 
+
+    /**
+     * Sends device list change notification to all listeners.
+     */
+    private void broadcastRoutingChange() {
+        AudioManager.resetAudioPortGeneration();
+        synchronized (mRoutingChangeListeners) {
+            // Prevent the case where an event is triggered by registering a routing change
+            // listener via the media player.
+            if (mEnableSelfRoutingMonitor) {
+                baseUpdateDeviceId(getRoutedDevice());
+            }
+            for (NativeRoutingEventHandlerDelegate delegate
+                    : mRoutingChangeListeners.values()) {
+                delegate.notifyClient();
+            }
+        }
+    }
+
     /*
-     * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
+     * Call BEFORE adding a routing callback handler.
      */
     @GuardedBy("mRoutingChangeListeners")
-    private void enableNativeRoutingCallbacksLocked(boolean enabled) {
-        if (mRoutingChangeListeners.size() == 0) {
-            native_enableDeviceCallback(enabled);
+    private void testEnableNativeRoutingCallbacksLocked() {
+        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
+            native_enableDeviceCallback(true);
+        }
+    }
+
+    private void tryToEnableNativeRoutingCallback() {
+        synchronized (mRoutingChangeListeners) {
+            if (!mEnableSelfRoutingMonitor) {
+                testEnableNativeRoutingCallbacksLocked();
+                mEnableSelfRoutingMonitor = true;
+            }
+        }
+    }
+
+    private void tryToDisableNativeRoutingCallback() {
+        synchronized (mRoutingChangeListeners) {
+            if (mEnableSelfRoutingMonitor) {
+                mEnableSelfRoutingMonitor = false;
+                testDisableNativeRoutingCallbacksLocked();
+            }
+        }
+    }
+
+    /*
+     * Call AFTER removing a routing callback handler.
+     */
+    @GuardedBy("mRoutingChangeListeners")
+    private void testDisableNativeRoutingCallbacksLocked() {
+        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
+            native_enableDeviceCallback(false);
         }
     }
 
@@ -1516,6 +1560,9 @@
     private ArrayMap<AudioRouting.OnRoutingChangedListener,
             NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
 
+    @GuardedBy("mRoutingChangeListeners")
+    private boolean mEnableSelfRoutingMonitor;
+
     /**
      * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
      * changes on this MediaPlayer.
@@ -1529,7 +1576,7 @@
             Handler handler) {
         synchronized (mRoutingChangeListeners) {
             if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
-                enableNativeRoutingCallbacksLocked(true);
+                testEnableNativeRoutingCallbacksLocked();
                 mRoutingChangeListeners.put(
                         listener, new NativeRoutingEventHandlerDelegate(this, listener,
                                 handler != null ? handler : mEventHandler));
@@ -1548,8 +1595,8 @@
         synchronized (mRoutingChangeListeners) {
             if (mRoutingChangeListeners.containsKey(listener)) {
                 mRoutingChangeListeners.remove(listener);
-                enableNativeRoutingCallbacksLocked(false);
             }
+            testDisableNativeRoutingCallbacksLocked();
         }
     }
 
@@ -3301,6 +3348,7 @@
 
     @Override
     protected void finalize() {
+        tryToDisableNativeRoutingCallback();
         baseRelease();
         native_finalize();
     }
@@ -3415,6 +3463,8 @@
 
             case MEDIA_STOPPED:
                 {
+                    tryToDisableNativeRoutingCallback();
+                    baseStop();
                     TimeProvider timeProvider = mTimeProvider;
                     if (timeProvider != null) {
                         timeProvider.onStopped();
@@ -3423,8 +3473,16 @@
                 break;
 
             case MEDIA_STARTED:
+                {
+                    baseStart(native_getRoutedDeviceId());
+                    tryToEnableNativeRoutingCallback();
+                }
+                // fall through
             case MEDIA_PAUSED:
                 {
+                    if (msg.what == MEDIA_PAUSED) {
+                        basePause();
+                    }
                     TimeProvider timeProvider = mTimeProvider;
                     if (timeProvider != null) {
                         timeProvider.onPaused(msg.what == MEDIA_PAUSED);
@@ -3590,14 +3648,8 @@
                 break;
 
             case MEDIA_AUDIO_ROUTING_CHANGED:
-                AudioManager.resetAudioPortGeneration();
-                synchronized (mRoutingChangeListeners) {
-                    for (NativeRoutingEventHandlerDelegate delegate
-                            : mRoutingChangeListeners.values()) {
-                        delegate.notifyClient();
-                    }
-                }
-                return;
+                    broadcastRoutingChange();
+                    return;
 
             case MEDIA_TIME_DISCONTINUITY:
                 final OnMediaTimeDiscontinuityListener mediaTimeListener;
@@ -3803,6 +3855,7 @@
         @Override
         public void onCompletion(MediaPlayer mp) {
             baseStop();
+            tryToDisableNativeRoutingCallback();
         }
     };
 
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 4940c76..36f7bed 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -43,6 +43,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayAddress;
@@ -54,6 +55,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -111,6 +113,8 @@
         IMediaRouterClient mClient;
         MediaRouterClientState mClientState;
 
+        Map<Integer, Integer> mStreamVolume = new ArrayMap<>();
+
         final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
             @Override
             public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
@@ -262,6 +266,17 @@
             mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
         }
 
+        int getStreamVolume(int streamType) {
+            if (!mStreamVolume.containsKey(streamType)) {
+                try {
+                    mStreamVolume.put(streamType, mAudioService.getStreamVolume(streamType));
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error getting local stream volume", e);
+                }
+            }
+            return mStreamVolume.get(streamType);
+        }
+
         boolean isBluetoothA2dpOn() {
             try {
                 return mBluetoothA2dpRoute != null && mAudioService.isBluetoothA2dpOn();
@@ -1976,13 +1991,7 @@
          */
         public int getVolume() {
             if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
-                int vol = 0;
-                try {
-                    vol = sStatic.mAudioService.getStreamVolume(mPlaybackStream);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Error getting local stream volume", e);
-                }
-                return vol;
+                return sStatic.getStreamVolume(mPlaybackStream);
             } else {
                 return mVolume;
             }
@@ -3139,11 +3148,12 @@
             if (intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                 final int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
                         -1);
+                final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
+                sStatic.mStreamVolume.put(streamType, newVolume);
                 if (streamType != AudioManager.STREAM_MUSIC) {
                     return;
                 }
 
-                final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
                 final int oldVolume = intent.getIntExtra(
                         AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
                 if (newVolume != oldVolume) {
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 4b09a5f..68237de 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -147,6 +147,36 @@
     }
 
     /**
+     * Starts scanning remote routes.
+     * @see #stopScan(String)
+     */
+    public void startScan() {
+        Client client = getOrCreateClient();
+        if (client != null) {
+            try {
+                mMediaRouterService.startScan(client);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+            }
+        }
+    }
+
+    /**
+     * Stops scanning remote routes to reduce resource consumption.
+     * @see #startScan(String)
+     */
+    public void stopScan() {
+        Client client = getOrCreateClient();
+        if (client != null) {
+            try {
+                mMediaRouterService.stopScan(client);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+            }
+        }
+    }
+
+    /**
      * Gets a {@link android.media.session.MediaController} associated with the
      * given routing session.
      * If there is no matching media session, {@code null} is returned.
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
new file mode 100644
index 0000000..cbc9ab7
--- /dev/null
+++ b/media/java/android/media/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 1344
+
+fgoldfain@google.com
+elaurent@google.com
+lajos@google.com
+olly@google.com
+andrewlewis@google.com
+sungsoo@google.com
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index da69c6c..58ae279 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -90,6 +90,8 @@
     private float mPanMultiplierR = 1.0f;
     @GuardedBy("mLock")
     private float mVolMultiplier = 1.0f;
+    @GuardedBy("mLock")
+    private int mDeviceId;
 
     /**
      * Constructor. Must be given audio attributes, as they are required for AppOps.
@@ -152,14 +154,35 @@
         }
     }
 
-    private void updateState(int state) {
+    void baseUpdateDeviceId(@Nullable AudioDeviceInfo deviceInfo) {
+        int deviceId = 0;
+        if (deviceInfo != null) {
+            deviceId = deviceInfo.getId();
+        }
+        int piid;
+        synchronized (mLock) {
+            piid = mPlayerIId;
+            mDeviceId = deviceId;
+        }
+        try {
+            getService().playerEvent(piid,
+                    AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID, deviceId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error talking to audio service, "
+                    + deviceId
+                    + " device id will not be tracked for piid=" + piid, e);
+        }
+    }
+
+    private void updateState(int state, int deviceId) {
         final int piid;
         synchronized (mLock) {
             mState = state;
             piid = mPlayerIId;
+            mDeviceId = deviceId;
         }
         try {
-            getService().playerEvent(piid, state);
+            getService().playerEvent(piid, state, deviceId);
         } catch (RemoteException e) {
             Log.e(TAG, "Error talking to audio service, "
                     + AudioPlaybackConfiguration.toLogFriendlyPlayerState(state)
@@ -167,9 +190,11 @@
         }
     }
 
-    void baseStart() {
-        if (DEBUG) { Log.v(TAG, "baseStart() piid=" + mPlayerIId); }
-        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
+    void baseStart(int deviceId) {
+        if (DEBUG) {
+            Log.v(TAG, "baseStart() piid=" + mPlayerIId + " deviceId=" + deviceId);
+        }
+        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED, deviceId);
         synchronized (mLock) {
             if (isRestricted_sync()) {
                 playerSetVolume(true/*muting*/,0, 0);
@@ -191,12 +216,12 @@
 
     void basePause() {
         if (DEBUG) { Log.v(TAG, "basePause() piid=" + mPlayerIId); }
-        updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED);
+        updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED, 0);
     }
 
     void baseStop() {
         if (DEBUG) { Log.v(TAG, "baseStop() piid=" + mPlayerIId); }
-        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED);
+        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED, 0);
     }
 
     void baseSetPan(float pan) {
diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java
index 68f2964..2f95247 100644
--- a/media/java/android/media/RouteDiscoveryPreference.java
+++ b/media/java/android/media/RouteDiscoveryPreference.java
@@ -153,6 +153,7 @@
             return false;
         }
         RouteDiscoveryPreference other = (RouteDiscoveryPreference) o;
+        //TODO: Make this order-free
         return Objects.equals(mPreferredFeatures, other.mPreferredFeatures)
                 && mShouldPerformActiveScan == other.mShouldPerformActiveScan;
     }
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 1bf2863..797caf3 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -149,7 +149,8 @@
         super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL);
 
         // do native setup
-        if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) {
+        if (native_setup(new WeakReference<SoundPool>(this),
+                maxStreams, attributes, getCurrentOpPackageName()) != 0) {
             throw new RuntimeException("Native setup failed");
         }
         mAttributes = attributes;
@@ -302,7 +303,8 @@
      */
     public final int play(int soundID, float leftVolume, float rightVolume,
             int priority, int loop, float rate) {
-        baseStart();
+        // FIXME: b/174876164 implement device id for soundpool
+        baseStart(0);
         return _play(soundID, leftVolume, rightVolume, priority, loop, rate);
     }
 
@@ -501,7 +503,7 @@
     private native final int _load(FileDescriptor fd, long offset, long length, int priority);
 
     private native final int native_setup(Object weakRef, int maxStreams,
-            Object/*AudioAttributes*/ attributes);
+            @NonNull Object/*AudioAttributes*/ attributes, @NonNull String opPackageName);
 
     private native final int _play(int soundID, float leftVolume, float rightVolume,
             int priority, int loop, float rate);
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 140e70d..6a695e6 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -16,9 +16,11 @@
 
 package android.media;
 
+import android.annotation.NonNull;
+import android.app.ActivityThread;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
-
+import android.text.TextUtils;
 
 
 /**
@@ -746,7 +748,7 @@
      *
      */
     public ToneGenerator(int streamType, int volume) {
-        native_setup(streamType, volume);
+        native_setup(streamType, volume, getCurrentOpPackageName());
     }
 
     /**
@@ -880,7 +882,8 @@
      */
     public native void release();
 
-    private native final void native_setup(int streamType, int volume);
+    private native void native_setup(
+            int streamType, int volume, @NonNull String opPackageName);
 
     private native final void native_finalize();
 
@@ -895,6 +898,10 @@
     @Override
     protected void finalize() { native_finalize(); }
 
+    private String getCurrentOpPackageName() {
+        return TextUtils.emptyIfNull(ActivityThread.currentOpPackageName());
+    }
+
     @SuppressWarnings("unused")
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private long mNativeContext; // accessed by native methods
diff --git a/media/java/android/media/audiofx/OWNERS b/media/java/android/media/audiofx/OWNERS
new file mode 100644
index 0000000..189fe0f
--- /dev/null
+++ b/media/java/android/media/audiofx/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+
+elaurent@google.com
diff --git a/media/java/android/media/audiopolicy/OWNERS b/media/java/android/media/audiopolicy/OWNERS
new file mode 100644
index 0000000..189fe0f
--- /dev/null
+++ b/media/java/android/media/audiopolicy/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+
+elaurent@google.com
diff --git a/media/java/android/media/browse/OWNERS b/media/java/android/media/browse/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/media/java/android/media/browse/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
+hdmoon@google.com
+insun@google.com
+jaewan@google.com
+jinpark@google.com
+klhyun@google.com
+gyumin@google.com
diff --git a/media/java/android/media/midi/OWNERS b/media/java/android/media/midi/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/java/android/media/midi/OWNERS
@@ -0,0 +1 @@
+elaurent@google.com
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 6af39f8..fd77b4e 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -180,7 +180,7 @@
      * be provided in priority order with the most important controller at index
      * 0.
      * <p>
-     * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL
+     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
      * permission be held by the calling app. You may also retrieve this list if
      * your app is an enabled notification listener using the
      * {@link NotificationListenerService} APIs, in which case you must pass the
@@ -196,14 +196,18 @@
     }
 
     /**
-     * Get active sessions for a specific user. To retrieve actions for a user
-     * other than your own you must hold the
-     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission
-     * in addition to any other requirements. If you are an enabled notification
-     * listener you may only get sessions for the users you are enabled for.
+     * Get active sessions for the given user.
+     * <p>
+     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+     * held by the calling app. You may also retrieve this list if your app is an enabled
+     * notification listener using the {@link NotificationListenerService} APIs, in which case you
+     * must pass the {@link ComponentName} of your enabled listener.
+     * <p>
+     * The calling application needs to hold the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+     * retrieve sessions for user ids that do not belong to current process.
      *
-     * @param notificationListener The enabled notification listener component.
-     *            May be null.
+     * @param notificationListener The enabled notification listener component. May be null.
      * @param userId The user id to fetch sessions for.
      * @return A list of controllers for ongoing sessions.
      * @hide
@@ -248,8 +252,9 @@
      * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
      * given user.
      * <p>
-     * If you want to get tokens for another user, you must hold the
-     * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL permission.
+     * The calling application needs to hold the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+     * retrieve session tokens for user ids that do not belong to current process.
      *
      * @param userId The user id to fetch sessions for.
      * @return A list of {@link Session2Token}
@@ -267,11 +272,12 @@
     }
 
     /**
-     * Add a listener to be notified when the list of active sessions changes. This requires the
-     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
-     * app. You may also retrieve this list if your app is an enabled notification listener using
-     * the {@link NotificationListenerService} APIs, in which case you must pass the
-     * {@link ComponentName} of your enabled listener.
+     * Add a listener to be notified when the list of active sessions changes.
+     * <p>
+     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+     * held by the calling app. You may also retrieve this list if your app is an enabled
+     * notificationlistener using the {@link NotificationListenerService} APIs, in which case you
+     * must pass the {@link ComponentName} of your enabled listener.
      *
      * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component. May be null.
@@ -283,12 +289,13 @@
     }
 
     /**
-     * Add a listener to be notified when the list of active sessions changes. This requires the
-     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
-     * app. You may also retrieve this list if your app is an enabled notification listener using
-     * the {@link NotificationListenerService} APIs, in which case you must pass the
-     * {@link ComponentName} of your enabled listener. Updates will be posted to the handler
-     * specified or to the caller's thread if the handler is null.
+     * Add a listener to be notified when the list of active sessions changes.
+     * <p>
+     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+     * held by the calling app. You may also retrieve this list if your app is an enabled
+     * notification listener using the {@link NotificationListenerService} APIs, in which case you
+     * must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
+     * handler specified or to the caller's thread if the handler is null.
      *
      * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component. May be null.
@@ -302,15 +309,17 @@
     }
 
     /**
-     * Add a listener to be notified when the list of active sessions changes for the given user.
-     * The calling app must have the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
-     * permission if it wants to call this method for a user that is not running the app.
+     * Add a listener to be notified when the list of active sessions changes.
      * <p>
      * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
      * held by the calling app. You may also retrieve this list if your app is an enabled
      * notification listener using the {@link NotificationListenerService} APIs, in which case you
      * must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
      * handler specified or to the caller's thread if the handler is null.
+     * <p>
+     * The calling application needs to hold the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+     * add listeners for user ids that do not belong to current process.
      *
      * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component. May be null.
@@ -407,6 +416,10 @@
      * Library</a> for consistent behavior across all devices.
      * <p>
      * Adds a listener to be notified when the {@link #getSession2Tokens()} changes.
+     * <p>
+     * The calling application needs to hold the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+     * add listeners for user ids that do not belong to current process.
      *
      * @param userId The userId to listen for changes on
      * @param listener The listener to add
@@ -705,8 +718,9 @@
     /**
      * Checks whether the remote user is a trusted app.
      * <p>
-     * An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
-     * permission or has an enabled notification listener.
+     * An app is trusted if the app holds the
+     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
+     * notification listener.
      *
      * @param userInfo The remote user info from either
      *            {@link MediaSession#getCurrentControllerInfo()} or
diff --git a/media/java/android/media/session/OWNERS b/media/java/android/media/session/OWNERS
new file mode 100644
index 0000000..916fc36
--- /dev/null
+++ b/media/java/android/media/session/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 137631
+
+hdmoon@google.com
+insun@google.com
+jaewan@google.com
+jinpark@google.com
+klhyun@google.com
+gyumin@google.com
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index b1a88ed..e7d30ebb 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -46,7 +46,8 @@
             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
-            ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI})
+            ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI,
+            ACTION_SET_PLAYBACK_SPEED})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Actions {}
 
@@ -176,6 +177,14 @@
      */
     public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
 
+    // Note: The value jumps from 1 << 17 to 1 << 22 for matching same value with AndroidX.
+    /**
+     * Indicates this session supports the set playback speed command.
+     *
+     * @see Builder#setActions(long)
+     */
+    public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22;
+
     /**
      * @hide
      */
@@ -428,6 +437,7 @@
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
+     * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li>
      * </ul>
      */
     @Actions
@@ -823,6 +833,7 @@
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
+         * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li>
          * </ul>
          *
          * @param actions The set of actions allowed.
diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/java/android/media/soundtrigger/OWNERS
@@ -0,0 +1 @@
+elaurent@google.com
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index a891154..8bccc9a 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -1,9 +1,6 @@
-amyjojo@google.com
 nchalko@google.com
-shubang@google.com
 quxiangfang@google.com
 
 # For android remote service
 per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS
 per-file ITvRemoteProvider.aidl = file:/media/lib/tvremote/OWNERS
-
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 d094c2c..dec0709 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -279,6 +279,7 @@
     @Nullable
     private FrontendInfo mFrontendInfo;
     private Integer mFrontendHandle;
+    private Boolean mIsSharedFrontend = false;
     private int mFrontendType = FrontendSettings.TYPE_UNDEFINED;
     private int mUserId;
     private Lnb mLnb;
@@ -441,8 +442,11 @@
      */
     public void shareFrontendFromTuner(@NonNull Tuner tuner) {
         mTunerResourceManager.shareFrontend(mClientId, tuner.mClientId);
-        mFrontendHandle = tuner.mFrontendHandle;
-        mFrontend = nativeOpenFrontendByHandle(mFrontendHandle);
+        synchronized (mIsSharedFrontend) {
+            mFrontendHandle = tuner.mFrontendHandle;
+            mFrontend = tuner.mFrontend;
+            mIsSharedFrontend = true;
+        }
     }
 
     /**
@@ -473,14 +477,19 @@
 
     private void releaseAll() {
         if (mFrontendHandle != null) {
-            int res = nativeCloseFrontend(mFrontendHandle);
-            if (res != Tuner.RESULT_SUCCESS) {
-                TunerUtils.throwExceptionForResult(res, "failed to close frontend");
+            synchronized (mIsSharedFrontend) {
+                if (!mIsSharedFrontend) {
+                    int res = nativeCloseFrontend(mFrontendHandle);
+                    if (res != Tuner.RESULT_SUCCESS) {
+                        TunerUtils.throwExceptionForResult(res, "failed to close frontend");
+                    }
+                }
+                mIsSharedFrontend = false;
             }
             mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
             FrameworkStatsLog
                     .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
-                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
+                    FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
             mFrontendHandle = null;
             mFrontend = null;
         }
@@ -546,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);
@@ -677,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
@@ -691,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.
@@ -740,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.
@@ -846,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
@@ -895,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.
@@ -917,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,
@@ -948,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.
      */
@@ -966,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) {
@@ -1283,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 98f8096..f68d554 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -341,13 +341,13 @@
         return mScanType;
     }
     /**
-     * Get if the client could handle the Diseqc Rx Message or not. Default value is false.
+     * Get if the client can handle the Diseqc Rx Message or not. Default value is false.
      *
-     * The setter {@link Builder#setCouldHandleDiseqcRxMessage(boolean)} is only supported with
-     * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker.getTunerVersion()} to check the
+     * The setter {@link Builder#setCanHandleDiseqcRxMessage(boolean)} is only supported with
+     * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker#getTunerVersion()} to check the
      * version.
      */
-    public boolean getCouldHandleDiseqcRxMessage() {
+    public boolean canHandleDiseqcRxMessage() {
         return mIsDiseqcRxMessage;
     }
 
@@ -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}.
@@ -409,18 +409,18 @@
         }
 
         /**
-         * Set true to indicate the client could handle the Diseqc Messages. Note that it's still
+         * Set true to indicate the client can handle the Diseqc Messages. Note that it's still
          * possible that the client won't receive the messages when HAL is not able to setup Rx
          * 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 setCouldHandleDiseqcRxMessage(boolean couldReceiveDiseqcMessage) {
+        public Builder setCanHandleDiseqcRxMessage(boolean canHandleDiseqcMessage) {
             if (TunerVersionChecker.checkHigherOrEqualVersionTo(
-                        TunerVersionChecker.TUNER_VERSION_1_1, "setCouldHandleDiseqcRxMessage")) {
-                mIsDiseqcRxMessage = couldReceiveDiseqcMessage;
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setCanHandleDiseqcRxMessage")) {
+                mIsDiseqcRxMessage = canHandleDiseqcMessage;
             }
             return this;
         }
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_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 948ebcd..6a622c5a 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -68,7 +68,7 @@
     mClass = (jclass)env->NewGlobalRef(clazz);
     mObject = env->NewWeakGlobalRef(thiz);
 
-    mImpl = new NuMediaExtractor;
+    mImpl = new NuMediaExtractor(NuMediaExtractor::EntryPoint::SDK);
 }
 
 JMediaExtractor::~JMediaExtractor() {
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 126897a..ddc51cd 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -464,11 +464,13 @@
                 || thumbPixels * 6 >= maxPixels) {
             frameMemory = retriever->getImageAtIndex(
                     index, colorFormat, false /*metaOnly*/, true /*thumbnail*/);
-            // TODO: Using unsecurePointer() has some associated security pitfalls
-            //       (see declaration for details).
-            //       Either document why it is safe in this case or address the
-            //       issue (e.g. by copying).
-            videoFrame = static_cast<VideoFrame *>(frameMemory->unsecurePointer());
+            if (frameMemory != 0) {
+                // TODO: Using unsecurePointer() has some associated security pitfalls
+                //       (see declaration for details).
+                //       Either document why it is safe in this case or address the
+                //       issue (e.g. by copying).
+                videoFrame = static_cast<VideoFrame *>(frameMemory->unsecurePointer());
+            }
 
             if (thumbPixels > maxPixels) {
                 int downscale = ceil(sqrt(thumbPixels / (float)maxPixels));
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 72dc32e..6fa94f1 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -337,8 +337,8 @@
 
 /////////////// MediaEvent ///////////////////////
 
-MediaEvent::MediaEvent(sp<Filter> filter, hidl_handle avHandle,
-        uint64_t dataId, uint64_t dataSize, jobject obj) : mFilter(filter),
+MediaEvent::MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle,
+        uint64_t dataId, uint64_t dataSize, jobject obj) : mFilterClient(filterClient),
         mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr),
         mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -359,12 +359,13 @@
     if (pC2Buffer != NULL) {
         pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
     }
+    mFilterClient = NULL;
 }
 
 void MediaEvent::finalize() {
-    if (mAvHandleRefCnt == 0) {
-        mFilter->mFilterSp->releaseAvHandle(
-                hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
+    if (mAvHandleRefCnt == 0 && mFilterClient != NULL) {
+        mFilterClient->releaseAvHandle(
+                mAvHandle, mDataIdRefCnt == 0 ? mDataId : 0);
         native_handle_close(mAvHandle);
     }
 }
@@ -382,21 +383,25 @@
     int numInts = 0;
     int memIndex;
     int dataSize;
+    SharedHandleInfo info = mFilterClient->getAvSharedHandleInfo();
+    native_handle_t* avSharedHandle = info.sharedHandle;
+    uint64_t avSharedMemSize = info.size;
+
     if (mAvHandle->numFds == 0) {
-        if (mFilter->mAvSharedHandle == NULL) {
+        if (avSharedHandle == NULL) {
             ALOGE("Shared AV memory handle is not initialized.");
             return NULL;
         }
-        if (mFilter->mAvSharedHandle->numFds == 0) {
+        if (avSharedHandle->numFds == 0) {
             ALOGE("Shared AV memory handle is empty.");
             return NULL;
         }
-        fd = mFilter->mAvSharedHandle->data[0];
-        dataSize = mFilter->mAvSharedMemSize;
-        numInts = mFilter->mAvSharedHandle->numInts;
+        fd = avSharedHandle->data[0];
+        dataSize = avSharedMemSize;
+        numInts = avSharedHandle->numInts;
         if (numInts > 0) {
             // If the first int in the shared native handle has value, use it as the index
-            memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+            memIndex = avSharedHandle->data[avSharedHandle->numFds];
         }
     } else {
         fd = mAvHandle->data[0];
@@ -407,11 +412,11 @@
             // event has value, use it as the index
             memIndex = mAvHandle->data[mAvHandle->numFds];
         } else {
-            if (mFilter->mAvSharedHandle != NULL) {
-                numInts = mFilter->mAvSharedHandle->numInts;
+            if (avSharedHandle != NULL) {
+                numInts = avSharedHandle->numInts;
                 if (numInts > 0) {
                     // If the first int in the shared native handle has value, use it as the index
-                    memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+                    memIndex = avSharedHandle->data[avSharedHandle->numFds];
                 }
             }
         }
@@ -462,9 +467,9 @@
     return mDataId;
 }
 
-/////////////// FilterCallback ///////////////////////
+/////////////// FilterClientCallbackImpl ///////////////////////
 
-jobjectArray FilterCallback::getSectionEvent(
+jobjectArray FilterClientCallbackImpl::getSectionEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent");
@@ -486,7 +491,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getMediaEvent(
+jobjectArray FilterClientCallbackImpl::getMediaEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
@@ -537,7 +542,7 @@
 
         if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
             sp<MediaEvent> mediaEventSp =
-                           new MediaEvent(mFilter, mediaEvent.avMemory,
+                           new MediaEvent(mFilterClient, mediaEvent.avMemory,
                                mediaEvent.avDataId, dataLength + offset, obj);
             mediaEventSp->mAvHandleRefCnt++;
             env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
@@ -549,7 +554,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getPesEvent(
+jobjectArray FilterClientCallbackImpl::getPesEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent");
@@ -570,7 +575,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getTsRecordEvent(
+jobjectArray FilterClientCallbackImpl::getTsRecordEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
                 const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -623,7 +628,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getMmtpRecordEvent(
+jobjectArray FilterClientCallbackImpl::getMmtpRecordEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
                 const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -665,7 +670,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getDownloadEvent(
+jobjectArray FilterClientCallbackImpl::getDownloadEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent");
@@ -689,7 +694,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getIpPayloadEvent(
+jobjectArray FilterClientCallbackImpl::getIpPayloadEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent");
@@ -705,7 +710,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getTemiEvent(
+jobjectArray FilterClientCallbackImpl::getTemiEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent");
@@ -728,7 +733,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getScramblingStatusEvent(
+jobjectArray FilterClientCallbackImpl::getScramblingStatusEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/ScramblingStatusEvent");
@@ -740,7 +745,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getIpCidChangeEvent(
+jobjectArray FilterClientCallbackImpl::getIpCidChangeEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpCidChangeEvent");
@@ -752,7 +757,7 @@
     return arr;
 }
 
-jobjectArray FilterCallback::getRestartEvent(
+jobjectArray FilterClientCallbackImpl::getRestartEvent(
         jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/RestartEvent");
@@ -764,9 +769,9 @@
     return arr;
 }
 
-Return<void> FilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
         const DemuxFilterEventExt& filterEventExt) {
-    ALOGD("FilterCallback::onFilterEvent_1_1");
+    ALOGD("FilterClientCallbackImpl::onFilterEvent_1_1");
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobjectArray array;
@@ -848,14 +853,13 @@
         }
     }
     env->CallVoidMethod(
-            mFilter->mFilterObj,
+            mFilterObj,
             gFields.onFilterEventID,
             array);
-    return Void();
 }
 
-Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
-    ALOGD("FilterCallback::onFilterEvent");
+void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
+    ALOGD("FilterClientCallbackImpl::onFilterEvent");
     std::vector<DemuxFilterEventExt::Event> emptyEventsExt;
     DemuxFilterEventExt emptyFilterEventExt {
             .events = emptyEventsExt,
@@ -863,49 +867,20 @@
     return onFilterEvent_1_1(filterEvent, emptyFilterEventExt);
 }
 
-Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
-    ALOGD("FilterCallback::onFilterStatus");
+void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
+    ALOGD("FilterClientCallbackImpl::onFilterStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
-            mFilter->mFilterObj,
+            mFilterObj,
             gFields.onFilterStatusID,
             (jint)status);
-    return Void();
 }
 
-void FilterCallback::setFilter(const sp<Filter> filter) {
-    ALOGD("FilterCallback::setFilter");
-    // JNI Object
-    mFilter = filter;
-}
-
-FilterCallback::~FilterCallback() {}
-
-/////////////// Filter ///////////////////////
-
-Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    mFilterObj = env->NewWeakGlobalRef(obj);
-}
-
-Filter::~Filter() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-
-    env->DeleteWeakGlobalRef(mFilterObj);
-    mFilterObj = NULL;
-    EventFlag::deleteEventFlag(&mFilterMQEventFlag);
-}
-
-int Filter::close() {
-    Result r = mFilterSp->close();
-    if (r == Result::SUCCESS) {
-        EventFlag::deleteEventFlag(&mFilterMQEventFlag);
-    }
-    return (int)r;
-}
-
-sp<IFilter> Filter::getIFilter() {
-    return mFilterSp;
+void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
+    ALOGD("FilterClientCallbackImpl::setFilter");
+    // Java Object
+    mFilterObj = filterObj;
+    mFilterClient = filterClient;
 }
 
 /////////////// TimeFilter ///////////////////////
@@ -927,22 +902,23 @@
     return mTimeFilterSp;
 }
 
-/////////////// FrontendCallback ///////////////////////
+/////////////// FrontendClientCallbackImpl ///////////////////////
 
-FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
+FrontendClientCallbackImpl::FrontendClientCallbackImpl(
+        jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
 
-Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
-    ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
+void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
+    ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
             mObject,
             gFields.onFrontendEventID,
             (jint)frontendEventType);
-    return Void();
 }
 
-Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) {
-    ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+void FrontendClientCallbackImpl::onScanMessage(
+        FrontendScanMessageType type, const FrontendScanMessage& message) {
+    ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
     switch(type) {
@@ -1050,13 +1026,15 @@
                         mObject,
                         env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
                         standard);
-            } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) {
+            } else if (std.getDiscriminator() ==
+                    FrontendScanMessage::Standard::hidl_discriminator::tStd) {
                 standard = (jint) std.tStd();
                 env->CallVoidMethod(
                         mObject,
                         env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
                         standard);
-            } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
+            } else if (std.getDiscriminator() ==
+                    FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
                 standard = (jint) std.sifStd();
                 env->CallVoidMethod(
                         mObject,
@@ -1081,17 +1059,17 @@
             }
             env->CallVoidMethod(
                     mObject,
-                    env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
+                    env->GetMethodID(clazz, "onAtsc3PlpInfos",
+                            "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
                     array);
             break;
         }
     }
-    return Void();
 }
 
-Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
         const FrontendScanMessageExt1_1& message) {
-    ALOGD("FrontendCallback::onScanMessageExt1_1, type=%d", type);
+    ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
     switch(type) {
@@ -1165,14 +1143,13 @@
         default:
             break;
     }
-    return Void();
 }
 
 /////////////// Tuner ///////////////////////
 
 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 +1158,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 +1179,17 @@
     env->DeleteWeakGlobalRef(mObject);
     env->DeleteGlobalRef(mClass);
     mTuner = NULL;
+    mFe = NULL;
+    mDemux = NULL;
+    mTunerClient = NULL;
+    mFeClient = NULL;
+    mDemuxClient = 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 +1197,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 +1207,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,16 +1226,18 @@
     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;
 }
 
-jobject JTuner::openFrontendById(int id) {
+jobject JTuner::openFrontendByHandle(int feHandle) {
     sp<IFrontend> fe;
     Result res;
+    uint32_t id = getResourceIdFromHandle(feHandle);
+
     mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
         fe = frontend;
         res = r;
@@ -1270,11 +1252,25 @@
     if (mDemux != NULL) {
         mDemux->setFrontendDataSource(mFeId);
     }
-    sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
-    fe->setCallback(feCb);
 
     jint jId = (jint) id;
 
+    // TODO: Handle reopening frontend with different handle
+    sp<FrontendClient> feClient = mTunerClient->openFrontend(feHandle);
+    if (feClient == NULL) {
+        ALOGE("Failed to open frontend");
+        return NULL;
+    }
+    mFeClient = feClient;
+
+    mFeId = mFeClient->getId();
+    jId = (jint) id;
+    if (mDemuxClient != NULL) {
+        mDemuxClient->setFrontendDataSource(mFeClient);
+    }
+    sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject, id);
+    mFeClient->setCallback(feClientCb);
+
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     // TODO: add more fields to frontend
     return env->NewObject(
@@ -1284,14 +1280,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 +1390,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 +1418,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()) {
@@ -1612,30 +1586,19 @@
 }
 
 int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) {
-    if (mFe == NULL) {
+    if (mFeClient == nullptr) {
         ALOGE("frontend is not initialized");
         return (int)Result::INVALID_STATE;
     }
-    Result result;
-    sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 =
-            ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
-    if (fe_1_1 == NULL) {
-        ALOGD("1.1 frontend is not found. Using 1.0 instead.");
-        result = mFe->tune(settings);
-        return (int)result;
-    }
-
-    result = fe_1_1->tune_1_1(settings, settingsExt1_1);
-    return (int)result;
+    return (int) mFeClient->tune(settings,settingsExt1_1);
 }
 
 int JTuner::stopTune() {
-    if (mFe == NULL) {
+    if (mFeClient == nullptr) {
         ALOGE("frontend is not initialized");
         return (int)Result::INVALID_STATE;
     }
-    Result result = mFe->stopTune();
-    return (int)result;
+    return (int) mFeClient->stopTune();
 }
 
 int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType,
@@ -1685,28 +1648,47 @@
 }
 
 Result JTuner::openDemux() {
-    if (mTuner == nullptr) {
+    if (mTuner == nullptr || mTunerClient == nullptr) {
         return Result::NOT_INITIALIZED;
     }
-    if (mDemux != nullptr) {
-        return Result::SUCCESS;
-    }
-    Result res;
-    uint32_t id;
-    sp<IDemux> demuxSp;
-    mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
-        demuxSp = demux;
-        id = demuxId;
-        res = r;
-        ALOGD("open demux, id = %d", demuxId);
-    });
-    if (res == Result::SUCCESS) {
-        mDemux = demuxSp;
-        mDemuxId = id;
-        if (mFe != NULL) {
-            mDemux->setFrontendDataSource(mFeId);
+
+    Result res = Result::SUCCESS;
+
+    if (mDemux == nullptr) {
+        uint32_t id;
+        sp<IDemux> demuxSp;
+        mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
+            demuxSp = demux;
+            id = demuxId;
+            res = r;
+            ALOGD("open demux, id = %d", demuxId);
+        });
+        if (res == Result::SUCCESS) {
+            mDemux = demuxSp;
+            mDemuxId = id;
+            if (mFe != NULL) {
+                mDemux->setFrontendDataSource(mFeId);
+            }
+        } else {
+            return res;
         }
     }
+
+    // TODO: replace demux opening with mTunerClient->openDemux(handle)
+    // when DemuxClient is fully ready
+    if (mDemuxClient == nullptr) {
+        sp<DemuxClient> demuxClient = new DemuxClient();
+        if (demuxClient == NULL) {
+            ALOGE("Failed to open demux");
+            return Result::UNKNOWN_ERROR;
+        }
+        mDemuxClient = demuxClient;
+        mDemuxClient->setHidlDemux(mDemux);
+        if (mFeClient != NULL) {
+            mDemuxClient->setFrontendDataSource(mFeClient);
+        }
+    }
+
     return res;
 }
 
@@ -1724,23 +1706,31 @@
             return (jint) res;
         }
     }
+
+    if (mFeClient != NULL) {
+        res = mFeClient->close();
+        if (res != Result::SUCCESS) {
+            return (jint) res;
+        }
+        mFeClient = NULL;
+    }
+    if (mDemuxClient != NULL) {
+        res = mDemuxClient->close();
+        if (res != Result::SUCCESS) {
+            return (jint) res;
+        }
+        mDemuxClient = NULL;
+    }
     return (jint) res;
 }
 
-jobject JTuner::getAvSyncHwId(sp<Filter> filter) {
-    if (mDemux == NULL) {
+jobject JTuner::getAvSyncHwId(sp<FilterClient> filterClient) {
+    if (mDemuxClient == NULL) {
         return NULL;
     }
 
-    uint32_t avSyncHwId;
-    Result res;
-    sp<IFilter> iFilterSp = filter->getIFilter();
-    mDemux->getAvSyncHwId(iFilterSp,
-            [&](Result r, uint32_t id) {
-                res = r;
-                avSyncHwId = id;
-            });
-    if (res == Result::SUCCESS) {
+    int avSyncHwId = mDemuxClient->getAvSyncHwId(filterClient);
+    if (avSyncHwId >= 0) {
         JNIEnv *env = AndroidRuntime::getJNIEnv();
         jclass integerClazz = env->FindClass("java/lang/Integer");
         jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
@@ -1750,17 +1740,11 @@
 }
 
 jobject JTuner::getAvSyncTime(jint id) {
-    if (mDemux == NULL) {
+    if (mDemuxClient == NULL) {
         return NULL;
     }
-    uint64_t time;
-    Result res;
-    mDemux->getAvSyncTime(static_cast<uint32_t>(id),
-            [&](Result r, uint64_t ts) {
-                res = r;
-                time = ts;
-            });
-    if (res == Result::SUCCESS) {
+    long time = mDemuxClient->getAvSyncTime((int)id);
+    if (time >= 0) {
         JNIEnv *env = AndroidRuntime::getJNIEnv();
         jclass longClazz = env->FindClass("java/lang/Long");
         jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
@@ -1770,13 +1754,13 @@
 }
 
 int JTuner::connectCiCam(jint id) {
-    if (mDemux == NULL) {
+    if (mDemuxClient == NULL) {
         Result r = openDemux();
         if (r != Result::SUCCESS) {
             return (int) r;
         }
     }
-    Result r = mDemux->connectCiCam(static_cast<uint32_t>(id));
+    Result r = mDemuxClient->connectCiCam((int)id);
     return (int) r;
 }
 
@@ -1802,13 +1786,13 @@
 }
 
 int JTuner::disconnectCiCam() {
-    if (mDemux == NULL) {
+    if (mDemuxClient == NULL) {
         Result r = openDemux();
         if (r != Result::SUCCESS) {
             return (int) r;
         }
     }
-    Result r = mDemux->disconnectCiCam();
+    Result r = mDemuxClient->disconnectCiCam();
     return (int) r;
 }
 
@@ -1855,34 +1839,25 @@
 }
 
 jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
-    if (mDemux == NULL) {
+    if (mDemux == NULL || mDemuxClient == NULL) {
         if (openDemux() != Result::SUCCESS) {
             return NULL;
         }
     }
 
-    sp<IFilter> iFilterSp;
-    sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
-    sp<FilterCallback> callback = new FilterCallback();
-    Result res;
-    mDemux->openFilter(type, bufferSize, callback,
-            [&](Result r, const sp<IFilter>& filter) {
-                iFilterSp = filter;
-                res = r;
-            });
-    if (res != Result::SUCCESS || iFilterSp == NULL) {
+    sp<FilterClient> filterClient;
+    sp<FilterClientCallbackImpl> callback = new FilterClientCallbackImpl();
+    filterClient = mDemuxClient->openFilter(type, bufferSize, callback);
+    if (filterClient == NULL) {
         ALOGD("Failed to open filter, type = %d", type.mainType);
         return NULL;
     }
     uint64_t fId;
-    iFilterSp->getId([&](Result, uint32_t filterId) {
-        fId = filterId;
-    });
-    iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
-    if (iFilterSp_1_1 != NULL) {
-        iFilterSp_1_1->getId64Bit([&](Result, uint64_t filterId64Bit) {
-            fId = filterId64Bit;
-        });
+    Result res = filterClient->getId64Bit(fId);
+    if (res != Result::SUCCESS) {
+        uint32_t id;
+        filterClient->getId(id);
+        fId = static_cast<uint64_t>(id);
     }
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1892,35 +1867,9 @@
                     gFields.filterInitID,
                     (jlong) fId);
 
-    sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
-    filterSp->incStrong(filterObj);
-    env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
-    filterSp->mIsMediaFilter = false;
-    filterSp->mAvSharedHandle = NULL;
-    callback->setFilter(filterSp);
-
-    if (type.mainType == DemuxFilterMainType::MMTP) {
-        if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
-                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
-            filterSp->mIsMediaFilter = true;
-        }
-    }
-
-    if (type.mainType == DemuxFilterMainType::TS) {
-        if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
-                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
-            filterSp->mIsMediaFilter = true;
-        }
-    }
-
-    if (iFilterSp_1_1 != NULL && filterSp->mIsMediaFilter) {
-        iFilterSp_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
-            if (r == Result::SUCCESS) {
-                filterSp->mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
-                filterSp->mAvSharedMemSize = avMemSize;
-            }
-        });
-    }
+    filterClient->incStrong(filterObj);
+    env->SetLongField(filterObj, gFields.filterContext, (jlong)filterClient.get());
+    callback->setFilter(env->NewWeakGlobalRef(filterObj), filterClient);
 
     return filterObj;
 }
@@ -2639,6 +2588,15 @@
     if (r == Result::SUCCESS) {
         mFe = NULL;
         mFe_1_1 = NULL;
+    } else {
+        return (jint) r;
+    }
+
+    if (mFeClient != NULL) {
+        r = mFeClient->close();
+    }
+    if (r == Result::SUCCESS) {
+        mFeClient = NULL;
     }
     return (jint) r;
 }
@@ -2650,10 +2608,18 @@
     }
     if (r == Result::SUCCESS) {
         mDemux = NULL;
+    } else {
+        return (jint) r;
+    }
+
+    if (mDemuxClient != NULL) {
+        r = mDemuxClient->close();
+    }
+    if (r == Result::SUCCESS) {
+        mDemuxClient = NULL;
     }
     return (jint) r;
 }
-
 }  // namespace android
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -3294,8 +3260,8 @@
     return settingsExt1_1;
 }
 
-static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
-    return (Filter *)env->GetLongField(filter, gFields.filterContext);
+static sp<FilterClient> getFilterClient(JNIEnv *env, jobject filter) {
+    return (FilterClient *)env->GetLongField(filter, gFields.filterContext);
 }
 
 static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) {
@@ -3406,7 +3372,7 @@
 
 static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
     sp<JTuner> tuner = new JTuner(env, thiz);
-    setTuner(env,thiz, tuner);
+    setTuner(env, thiz, tuner);
 }
 
 static jint android_media_tv_Tuner_native_get_tuner_version(JNIEnv *env, jobject thiz) {
@@ -3422,15 +3388,7 @@
 static jobject android_media_tv_Tuner_open_frontend_by_handle(
         JNIEnv *env, jobject thiz, jint handle) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    uint32_t id = getResourceIdFromHandle(handle);
-    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);
+    return tuner->openFrontendByHandle(handle);
 }
 
 static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
@@ -3476,13 +3434,13 @@
 
 static jobject android_media_tv_Tuner_get_av_sync_hw_id(
         JNIEnv *env, jobject thiz, jobject filter) {
-    sp<Filter> filterSp = getFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed to get sync ID. Filter not found");
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to get sync ID. Filter client not found");
         return NULL;
     }
     sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->getAvSyncHwId(filterSp);
+    return tuner->getAvSyncHwId(filterClient);
 }
 
 static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) {
@@ -3943,26 +3901,13 @@
 }
 
 static Result configureIpFilterContextId(
-        JNIEnv *env, sp<IFilter> iFilterSp, jobject ipFilterConfigObj) {
+        JNIEnv *env, sp<FilterClient> filterClient, jobject ipFilterConfigObj) {
     jclass clazz = env->FindClass(
             "android/media/tv/tuner/filter/IpFilterConfiguration");
     uint32_t cid = env->GetIntField(ipFilterConfigObj, env->GetFieldID(
             clazz, "mIpFilterContextId", "I"));
-    Result res = Result::SUCCESS;
-    if (cid != static_cast<uint32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID)) {
-        sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
-        iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
 
-        if (iFilterSp_1_1 != NULL) {
-            res = iFilterSp_1_1->configureIpCid(cid);
-            if (res != Result::SUCCESS) {
-                return res;
-            }
-        } else {
-            ALOGW("configureIpCid is not supported with the current HAL implementation.");
-        }
-    }
-    return res;
+    return filterClient->configureIpFilterContextId(cid);
 }
 
 static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
@@ -4005,21 +3950,20 @@
 static jint android_media_tv_Tuner_configure_filter(
         JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
     ALOGD("configure filter type=%d, subtype=%d", type, subtype);
-    sp<Filter> filterSp = getFilter(env, filter);
-    sp<IFilter> iFilterSp = filterSp->getIFilter();
-    if (iFilterSp == NULL) {
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
         ALOGD("Failed to configure filter: filter not found");
         return (jint) Result::NOT_INITIALIZED;
     }
     DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
-    Result res = iFilterSp->configure(filterSettings);
+    Result res = filterClient->configure(filterSettings);
 
     if (res != Result::SUCCESS) {
         return (jint) res;
     }
 
     if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) {
-        res = configureIpFilterContextId(env, iFilterSp, settings);
+        res = configureIpFilterContextId(env, filterClient, settings);
         if (res != Result::SUCCESS) {
             return (jint) res;
         }
@@ -4027,49 +3971,19 @@
 
     AvStreamType streamType;
     if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) {
-        sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
-        iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
-        if (iFilterSp_1_1 != NULL) {
-            res = iFilterSp_1_1->configureAvStreamType(streamType);
-        } else {
-            ALOGW("configureAvStreamType is not supported with the current HAL implementation.");
-        }
-        if (res != Result::SUCCESS) {
-            return (jint) res;
-        }
+        res = filterClient->configureAvStreamType(streamType);
     }
-
-    MQDescriptorSync<uint8_t> filterMQDesc;
-    Result getQueueDescResult = Result::UNKNOWN_ERROR;
-    if (filterSp->mFilterMQ == NULL) {
-        iFilterSp->getQueueDesc(
-                [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
-                    filterMQDesc = desc;
-                    getQueueDescResult = r;
-                    ALOGD("getFilterQueueDesc");
-                });
-        if (getQueueDescResult == Result::SUCCESS) {
-            filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
-            EventFlag::createEventFlag(
-                    filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
-        }
-    }
-    return (jint) getQueueDescResult;
+    return (jint) res;
 }
 
 static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to get filter ID: filter not found");
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to get filter ID: filter client not found");
         return (int) Result::NOT_INITIALIZED;
     }
-    Result res;
     uint32_t id;
-    iFilterSp->getId(
-            [&](Result r, uint32_t filterId) {
-                res = r;
-                id = filterId;
-            });
+    Result res = filterClient->getId(id);
     if (res != Result::SUCCESS) {
         return (jint) Constant::INVALID_FILTER_ID;
     }
@@ -4077,30 +3991,13 @@
 }
 
 static jlong android_media_tv_Tuner_get_filter_64bit_id(JNIEnv* env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to get filter ID: filter not found");
-        return static_cast<jlong>(
-                ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to get filter ID 64 bit: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-
-    sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
-    iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
-    Result res;
     uint64_t id;
-
-    if (iFilterSp_1_1 != NULL) {
-        iFilterSp_1_1->getId64Bit(
-            [&](Result r, uint64_t filterId64Bit) {
-                res = r;
-                id = filterId64Bit;
-        });
-    } else {
-        ALOGW("getId64Bit is not supported with the current HAL implementation.");
-        return static_cast<jlong>(
-                ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
-    }
-
+    Result res = filterClient->getId64Bit(id);
     return (res == Result::SUCCESS) ?
             static_cast<jlong>(id) : static_cast<jlong>(
                     ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
@@ -4108,96 +4005,96 @@
 
 static jint android_media_tv_Tuner_configure_monitor_event(
         JNIEnv* env, jobject filter, int monitorEventType) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to configure scrambling event: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to configure scrambling event: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-
-    sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
-    iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
-    Result res;
-
-    if (iFilterSp_1_1 != NULL) {
-        res = iFilterSp_1_1->configureMonitorEvent(monitorEventType);
-    } else {
-        ALOGW("configureScramblingEvent is not supported with the current HAL implementation.");
-        return (jint) Result::INVALID_STATE;
-    }
-
+    Result res = filterClient->configureMonitorEvent(monitorEventType);
     return (jint) res;
 }
 
 static jint android_media_tv_Tuner_set_filter_data_source(
         JNIEnv* env, jobject filter, jobject srcFilter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to set filter data source: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to set filter data source: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-    Result r;
+    Result res;
     if (srcFilter == NULL) {
-        r = iFilterSp->setDataSource(NULL);
+        res = filterClient->setDataSource(NULL);
     } else {
-        sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
-        if (iFilterSp == NULL) {
+        sp<FilterClient> srcClient = getFilterClient(env, srcFilter);
+        if (srcClient == NULL) {
             ALOGD("Failed to set filter data source: src filter not found");
             return (jint) Result::INVALID_ARGUMENT;
         }
-        r = iFilterSp->setDataSource(srcSp);
+        res = filterClient->setDataSource(srcClient);
     }
-    return (jint) r;
+    return (jint) res;
 }
 
 static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to start filter: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to start filter: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-    Result r = iFilterSp->start();
-    return (jint) r;
+    return (jint) filterClient->start();
 }
 
 static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to stop filter: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to stop filter: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-    Result r = iFilterSp->stop();
-    return (jint) r;
+    return (jint) filterClient->stop();
 }
 
 static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to flush filter: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        ALOGD("Failed to flush filter: filter client not found");
+        return (int) Result::NOT_INITIALIZED;
     }
-    Result r = iFilterSp->flush();
-    return (jint) r;
+    return (jint) filterClient->flush();
 }
 
 static jint android_media_tv_Tuner_read_filter_fmq(
         JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
-    sp<Filter> filterSp = getFilter(env, filter);
-    if (filterSp == NULL) {
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
-                "Failed to read filter FMQ: filter not found");
+                "Failed to read filter FMQ: filter client not found");
         return 0;
     }
-    return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size);
+
+    jboolean isCopy;
+    jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
+    ALOGD("copyData, isCopy=%d", isCopy);
+    if (dst == nullptr) {
+        jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
+        return 0;
+    }
+    int realReadSize = filterClient->read(reinterpret_cast<uint8_t*>(dst) + offset, size);
+    env->ReleaseByteArrayElements(buffer, dst, 0);
+    if (realReadSize < 0) {
+        return (jint) Result::UNKNOWN_ERROR;
+    }
+    return (jint) Result::SUCCESS;
 }
 
 static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (iFilterSp == NULL) {
-        ALOGD("Failed to close filter: filter not found");
-        return (jint) Result::NOT_INITIALIZED;
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                "Failed to close filter: filter client not found");
+        return 0;
     }
-    Result r = iFilterSp->close();
-    return (jint) r;
+
+    return (jint) filterClient->close();
 }
 
 static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
@@ -4305,7 +4202,8 @@
     if (descramblerSp == NULL) {
         return (jint) Result::NOT_INITIALIZED;
     }
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+    // TODO: use filter client once descramblerClient is ready
+    sp<IFilter> iFilterSp = getFilterClient(env, filter)->getHalFilter();
     Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
     return (jint) result;
 }
@@ -4316,7 +4214,8 @@
     if (descramblerSp == NULL) {
         return (jint) Result::NOT_INITIALIZED;
     }
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+    // TODO: use filter client once descramblerClient is ready
+    sp<IFilter> iFilterSp = getFilterClient(env, filter)->getHalFilter();
     Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
     return (jint) result;
 }
@@ -4388,12 +4287,13 @@
     if (dvrSp == NULL) {
         return (jint) Result::NOT_INITIALIZED;
     }
-    sp<Filter> filterSp = getFilter(env, filter);
-    if (filterSp == NULL) {
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
         return (jint) Result::INVALID_ARGUMENT;
     }
     sp<IDvr> iDvrSp = dvrSp->getIDvr();
-    sp<IFilter> iFilterSp = filterSp->getIFilter();
+    // TODO: use filter client once dvrClient is ready
+    sp<IFilter> iFilterSp = filterClient->getHalFilter();
     Result result = iDvrSp->attachFilter(iFilterSp);
     return (jint) result;
 }
@@ -4403,12 +4303,13 @@
     if (dvrSp == NULL) {
         return (jint) Result::NOT_INITIALIZED;
     }
-    sp<Filter> filterSp = getFilter(env, filter);
-    if (filterSp == NULL) {
+    sp<FilterClient> filterClient = getFilterClient(env, filter);
+    if (filterClient == NULL) {
         return (jint) Result::INVALID_ARGUMENT;
     }
     sp<IDvr> iDvrSp = dvrSp->getIDvr();
-    sp<IFilter> iFilterSp = filterSp->getIFilter();
+    // TODO: use filter client once dvrClient is ready
+    sp<IFilter> iFilterSp = filterClient->getHalFilter();
     Result result = iDvrSp->detachFilter(iFilterSp);
     return (jint) result;
 }
@@ -4746,8 +4647,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..4149228 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -34,6 +34,12 @@
 #include <utils/Mutex.h>
 #include <utils/RefBase.h>
 
+#include "tuner/DemuxClient.h"
+#include "tuner/FilterClient.h"
+#include "tuner/FilterClientCallback.h"
+#include "tuner/FrontendClient.h"
+#include "tuner/FrontendClientCallback.h"
+#include "tuner/TunerClient.h"
 #include "jni.h"
 
 using ::android::hardware::EventFlag;
@@ -76,7 +82,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>;
 
@@ -95,6 +100,7 @@
     Lnb(sp<ILnb> sp, jobject obj);
     ~Lnb();
     sp<ILnb> getILnb();
+    // TODO: remove after migrate to client lib
     sp<ILnb> mLnbSp;
     jweak mLnbObj;
 };
@@ -115,6 +121,7 @@
     jint close();
     MQ& getDvrMQ();
     sp<IDvr> getIDvr();
+    // TODO: remove after migrate to client lib
     sp<IDvr> mDvrSp;
     jweak mDvrObj;
     std::unique_ptr<MQ> mDvrMQ;
@@ -123,29 +130,15 @@
     int mFd;
 };
 
-struct Filter : public RefBase {
-    Filter(sp<IFilter> sp, jobject obj);
-    ~Filter();
-    int close();
-    sp<IFilter> getIFilter();
-    sp<IFilter> mFilterSp;
-    std::unique_ptr<MQ> mFilterMQ;
-    EventFlag* mFilterMQEventFlag;
-    jweak mFilterObj;
-    native_handle_t* mAvSharedHandle;
-    uint64_t mAvSharedMemSize;
-    bool mIsMediaFilter;
-};
-
 struct MediaEvent : public RefBase {
-    MediaEvent(sp<Filter> filter, hidl_handle avHandle, uint64_t dataId,
+    MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle, uint64_t dataId,
         uint64_t dataSize, jobject obj);
     ~MediaEvent();
     jobject getLinearBlock();
     uint64_t getAudioHandle();
     void finalize();
 
-    sp<Filter> mFilter;
+    sp<FilterClient> mFilterClient;
     native_handle_t* mAvHandle;
     uint64_t mDataId;
     uint64_t mDataSize;
@@ -159,16 +152,16 @@
     std::weak_ptr<C2Buffer> mC2Buffer;
 };
 
-struct FilterCallback : public IFilterCallback {
-    ~FilterCallback();
-    virtual Return<void> onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+struct FilterClientCallbackImpl : public FilterClientCallback {
+    virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
             const DemuxFilterEventExt& filterEventExt);
-    virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
-    virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+    virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
+    virtual void onFilterStatus(const DemuxFilterStatus status);
 
-    void setFilter(const sp<Filter> filter);
+    void setFilter(jweak filterObj, sp<FilterClient> filterClient);
 private:
-    sp<Filter> mFilter;
+    jweak mFilterObj;
+    sp<FilterClient> mFilterClient;
     jobjectArray getSectionEvent(
             jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
     jobjectArray getMediaEvent(
@@ -195,13 +188,13 @@
             jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt);
 };
 
-struct FrontendCallback : public IFrontendCallback {
-    FrontendCallback(jweak tunerObj, FrontendId id);
+struct FrontendClientCallbackImpl : public FrontendClientCallback {
+    FrontendClientCallbackImpl(jweak tunerObj, FrontendId id);
 
-    virtual Return<void> onEvent(FrontendEventType frontendEventType);
-    virtual Return<void> onScanMessage(
+    virtual void onEvent(FrontendEventType frontendEventType);
+    virtual void onScanMessage(
             FrontendScanMessageType type, const FrontendScanMessage& message);
-    virtual Return<void> onScanMessageExt1_1(
+    virtual void onScanMessageExt1_1(
             FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
 
     jweak mObject;
@@ -212,22 +205,24 @@
     TimeFilter(sp<ITimeFilter> sp, jweak obj);
     ~TimeFilter();
     sp<ITimeFilter> getITimeFilter();
+    // TODO: remove after migrate to client lib
     sp<ITimeFilter> mTimeFilterSp;
     jweak mTimeFilterObj;
 };
 
 struct JTuner : public RefBase {
     JTuner(JNIEnv *env, jobject thiz);
+    // TODO: modify after migrate to client lib
     sp<ITuner> getTunerService();
     int getTunerVersion();
-    jobject getAvSyncHwId(sp<Filter> filter);
+    jobject getAvSyncHwId(sp<FilterClient> filter);
     jobject getAvSyncTime(jint id);
     int connectCiCam(jint id);
     int linkCiCam(jint id);
     int disconnectCiCam();
     int unlinkCiCam(jint id);
     jobject getFrontendIds();
-    jobject openFrontendById(int id);
+    jobject openFrontendByHandle(int feHandle);
     jint closeFrontendById(int id);
     jobject getFrontendInfo(int id);
     int tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
@@ -257,18 +252,22 @@
 private:
     jclass mClass;
     jweak mObject;
+    // TODO: remove after migrate to client lib
     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;
+    // TODO: remove after migrate to client lib
     sp<IFrontend> mFe;
+    // TODO: remove after migrate to client lib
     sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1;
+    sp<FrontendClient> mFeClient;
     int mFeId;
     hidl_vec<LnbId> mLnbIds;
+    // TODO: remove after migrate to client lib
     sp<ILnb> mLnb;
+    // TODO: remove after migrate to client lib
     sp<IDemux> mDemux;
+    sp<DemuxClient> mDemuxClient;
     uint32_t mDemuxId;
     static jobject getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
     static jobject getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
@@ -282,6 +281,9 @@
     static jobject getDtmbFrontendCaps(JNIEnv *env, int id);
 
     bool isV1_1ExtendedStatusType(jint type);
+    static uint32_t getResourceIdFromHandle(jint handle) {
+        return (handle & 0x00ff0000) >> 16;
+    }
 };
 
 class C2DataIdInfo : public C2Param {
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index ac44843..253b4e3 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -84,8 +84,9 @@
 
 } // namespace
 
-SoundPool::SoundPool(int32_t maxStreams, const audio_attributes_t* attributes)
-    : mStreamManager(maxStreams, kStreamManagerThreads, attributes)
+SoundPool::SoundPool(
+        int32_t maxStreams, const audio_attributes_t* attributes, const std::string& opPackageName)
+    : mStreamManager(maxStreams, kStreamManagerThreads, attributes, opPackageName)
 {
     ALOGV("%s(maxStreams=%d, attr={ content_type=%d, usage=%d, flags=0x%x, tags=%s })",
             __func__, maxStreams,
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index d5b16ef..ffb1c99 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -19,6 +19,8 @@
 #include "SoundManager.h"
 #include "StreamManager.h"
 
+#include <string>
+
 namespace android {
 
 /**
@@ -29,7 +31,8 @@
  */
 class SoundPool {
 public:
-    SoundPool(int32_t maxStreams, const audio_attributes_t* attributes);
+    SoundPool(int32_t maxStreams, const audio_attributes_t* attributes,
+            const std::string& opPackageName = {});
     ~SoundPool();
 
     // SoundPool Java API support
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index e7042d0..73e319a 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -332,7 +332,9 @@
                     0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
                     AudioTrack::TRANSFER_DEFAULT,
                     nullptr /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/,
-                    mStreamManager->getAttributes());
+                    mStreamManager->getAttributes(),
+                    false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/,
+                    mStreamManager->getOpPackageName());
             // Set caller name so it can be logged in destructor.
             // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
             newTrack->setCallerName("soundpool");
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 5b6494d..502ee00 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -98,9 +98,11 @@
 #pragma clang diagnostic ignored "-Wthread-safety-analysis"
 
 StreamManager::StreamManager(
-        int32_t streams, size_t threads, const audio_attributes_t* attributes)
+        int32_t streams, size_t threads, const audio_attributes_t* attributes,
+        std::string opPackageName)
     : StreamMap(streams)
     , mAttributes(*attributes)
+    , mOpPackageName(std::move(opPackageName))
 {
     ALOGV("%s(%d, %zu, ...)", __func__, streams, threads);
     forEach([this](Stream *stream) {
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index 59ae2f9..81ac69e 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -24,6 +24,7 @@
 #include <map>
 #include <memory>
 #include <mutex>
+#include <string>
 #include <unordered_set>
 #include <vector>
 
@@ -386,7 +387,8 @@
 public:
     // Note: the SoundPool pointer is only used for stream initialization.
     // It is not stored in StreamManager.
-    StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes);
+    StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes,
+            std::string opPackageName);
     ~StreamManager();
 
     // Returns positive streamID on success, 0 on failure.  This is locked.
@@ -400,6 +402,8 @@
 
     const audio_attributes_t* getAttributes() const { return &mAttributes; }
 
+    const std::string& getOpPackageName() const { return mOpPackageName; }
+
     // Moves the stream to the restart queue (called upon BUFFER_END of the static track)
     // this is locked internally.
     // If activeStreamIDToMatch is nonzero, it will only move to the restart queue
@@ -473,6 +477,8 @@
     // The paired stream may be active or restarting.
     // No particular order.
     std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock);
+
+    const std::string           mOpPackageName;
 };
 
 } // namespace android::soundpool
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 26725f8..357cc63 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -22,6 +22,7 @@
 #include <utils/Log.h>
 #include <jni.h>
 #include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include <android_runtime/AndroidRuntime.h>
 #include "SoundPool.h"
 
@@ -181,7 +182,7 @@
 
 static jint
 android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
-        jint maxChannels, jobject jaa)
+        jint maxChannels, jobject jaa, jstring opPackageName)
 {
     if (jaa == nullptr) {
         ALOGE("Error creating SoundPool: invalid audio attributes");
@@ -203,7 +204,8 @@
     paa->flags = (audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
 
     ALOGV("android_media_SoundPool_native_setup");
-    auto *ap = new SoundPool(maxChannels, paa);
+    ScopedUtfChars opPackageNameStr(env, opPackageName);
+    auto *ap = new SoundPool(maxChannels, paa, opPackageNameStr.c_str());
     if (ap == nullptr) {
         return -1;
     }
@@ -298,7 +300,7 @@
         (void *)android_media_SoundPool_setRate
     },
     {   "native_setup",
-        "(Ljava/lang/Object;ILjava/lang/Object;)I",
+        "(Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I",
         (void*)android_media_SoundPool_native_setup
     },
     {   "native_release",
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
new file mode 100644
index 0000000..b237a24
--- /dev/null
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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(type);
+            filterClient->setHidlFilter(hidlFilter);
+            return filterClient;
+        }
+    }
+
+    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() {
+    // TODO: 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..0aab5fe
--- /dev/null
+++ b/media/jni/tuner/FilterClient.cpp
@@ -0,0 +1,319 @@
+/*
+ * 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;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+
+namespace android {
+
+/////////////// FilterClient ///////////////////////
+
+// TODO: pending aidl interface
+// TODO: add filter callback
+FilterClient::FilterClient(DemuxFilterType type) {
+    //mTunerFilter = tunerFilter;
+    mAvSharedHandle = NULL;
+    checkIsMediaFilter(type);
+}
+
+FilterClient::~FilterClient() {
+    //mTunerFilter = NULL;
+    mFilter = NULL;
+    mFilter_1_1 = NULL;
+    mAvSharedHandle = NULL;
+    mAvSharedMemSize = 0;
+}
+
+// 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);
+    handleAvShareMemory();
+}
+
+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;
+}
+
+SharedHandleInfo FilterClient::getAvSharedHandleInfo() {
+    SharedHandleInfo info{
+        .sharedHandle = NULL,
+        .size = 0,
+    };
+
+    // TODO: pending aidl interface
+
+    if (mFilter_1_1 != NULL) {
+        info.sharedHandle = mAvSharedHandle;
+        info.size = mAvSharedMemSize;
+    }
+
+    return info;
+}
+
+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) {
+        Result res = mFilter->close();
+        if (res == Result::SUCCESS) {
+            mFilter = NULL;
+        }
+        return res;
+    }
+
+    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;
+}
+
+void FilterClient::checkIsMediaFilter(DemuxFilterType type) {
+    if (type.mainType == DemuxFilterMainType::MMTP) {
+        if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+            mIsMediaFilter = true;
+        }
+    }
+
+    if (type.mainType == DemuxFilterMainType::TS) {
+        if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+            mIsMediaFilter = true;
+        }
+    }
+}
+
+void FilterClient::handleAvShareMemory() {
+    if (mFilter_1_1 != NULL && mIsMediaFilter) {
+        mFilter_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+            if (r == Result::SUCCESS) {
+                mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
+                mAvSharedMemSize = avMemSize;
+            }
+        });
+    }
+}
+}  // namespace android
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
new file mode 100644
index 0000000..976b2f5
--- /dev/null
+++ b/media/jni/tuner/FilterClient.h
@@ -0,0 +1,212 @@
+/*
+ * 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::DemuxFilterType;
+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 {
+
+struct SharedHandleInfo {
+    native_handle_t* sharedHandle;
+    uint64_t size;
+};
+
+// 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(DemuxFilterType type);
+    ~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);
+
+    /**
+     * Get the a/v shared memory handle information
+     */
+    SharedHandleInfo getAvSharedHandleInfo();
+
+    /**
+     * 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);
+    void checkIsMediaFilter(DemuxFilterType type);
+    void handleAvShareMemory();
+
+    /**
+     * 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;
+
+    native_handle_t* mAvSharedHandle;
+    uint64_t mAvSharedMemSize;
+    bool mIsMediaFilter;
+};
+}  // 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/mca/effect/java/android/media/effect/OWNERS b/media/mca/effect/java/android/media/effect/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/mca/effect/java/android/media/effect/OWNERS
@@ -0,0 +1 @@
+elaurent@google.com
diff --git a/media/mca/effect/java/android/media/effect/effects/OWNERS b/media/mca/effect/java/android/media/effect/effects/OWNERS
new file mode 100644
index 0000000..6a351d3
--- /dev/null
+++ b/media/mca/effect/java/android/media/effect/effects/OWNERS
@@ -0,0 +1 @@
+elaurent@google.com
diff --git a/media/mca/filterfw/java/android/filterfw/OWNERS b/media/mca/filterfw/java/android/filterfw/OWNERS
new file mode 100644
index 0000000..5d351ef
--- /dev/null
+++ b/media/mca/filterfw/java/android/filterfw/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 50018
+
+elaurent@google.com
diff --git a/media/mca/filterfw/java/android/filterfw/samples/OWNERS b/media/mca/filterfw/java/android/filterfw/samples/OWNERS
new file mode 100644
index 0000000..5d351ef
--- /dev/null
+++ b/media/mca/filterfw/java/android/filterfw/samples/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 50018
+
+elaurent@google.com
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 35c4d42..923377c 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -131,7 +131,7 @@
     MidiDeviceInfo deviceInfo;
     Status txResult = device->server->getDeviceInfo(&deviceInfo);
     if (!txResult.isOk()) {
-        ALOGE("AMIDI_getDeviceInfo transaction error: %d", txResult.transactionError());
+        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
         return AMEDIA_ERROR_UNKNOWN;
     }
 
@@ -253,7 +253,7 @@
             ? device->server->openOutputPort(portToken, portNumber, &ufd)
             : device->server->openInputPort(portToken, portNumber, &ufd);
     if (!txResult.isOk()) {
-        ALOGE("AMIDI_openPort transaction error: %d", txResult.transactionError());
+        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
         return AMEDIA_ERROR_UNKNOWN;
     }
 
@@ -282,7 +282,7 @@
 
     Status txResult = port->device->server->closePort(port->binderToken);
     if (!txResult.isOk()) {
-        ALOGE("Transaction error closing MIDI port:%d", txResult.transactionError());
+        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
     }
 
     delete port;
diff --git a/media/tests/MediaTranscodingTest/Android.bp b/media/tests/MediaTranscodingTest/Android.bp
deleted file mode 100644
index bd687a1..0000000
--- a/media/tests/MediaTranscodingTest/Android.bp
+++ /dev/null
@@ -1,16 +0,0 @@
-android_test {
-    name: "mediatranscodingtest",
-    srcs: ["**/*.java"],
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    static_libs: [
-        "androidx.test.ext.junit",
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-        "androidx.test.rules",
-        "testng"
-    ],
-    platform_apis: true,
-}
diff --git a/media/tests/MediaTranscodingTest/AndroidManifest.xml b/media/tests/MediaTranscodingTest/AndroidManifest.xml
deleted file mode 100644
index 07674da..0000000
--- a/media/tests/MediaTranscodingTest/AndroidManifest.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-     package="com.android.mediatranscodingtest">
-
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <uses-permission android:name="android.permission.WAKE_LOCK"/>
-
-    <application android:label="@string/app_name">
-        <uses-library android:name="android.test.runner"/>
-        <activity android:label="@string/app_name"
-             android:name="MediaTranscodingTest"
-             android:screenOrientation="landscape"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
-            </intent-filter>
-        </activity>
-    </application>
-
-    <instrumentation android:name=".MediaTranscodingTestRunner"
-         android:targetPackage="com.android.mediatranscodingtest"
-         android:label="MediaTranscoding tests InstrumentationRunner">
-    </instrumentation>
-</manifest>
diff --git a/media/tests/MediaTranscodingTest/AndroidTest.xml b/media/tests/MediaTranscodingTest/AndroidTest.xml
deleted file mode 100644
index c2167e8..0000000
--- a/media/tests/MediaTranscodingTest/AndroidTest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs MediaTranscoding Tests">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="mediatranscodingtest.apk" />
-    </target_preparer>
-
-    <option name="test-tag" value="MediaTranscodingTest" />
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.mediatranscodingtest" />
-        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
-        <option name="hidden-api-checks" value="false"/>
-    </test>
-</configuration>
diff --git a/media/tests/MediaTranscodingTest/Readme.txt b/media/tests/MediaTranscodingTest/Readme.txt
deleted file mode 100644
index e3b835b..0000000
--- a/media/tests/MediaTranscodingTest/Readme.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-MediaTranscodingTest/
-    Uses instrumentation and so can be run with runtest.
-    It assumes /sdcard/media_api/ has been populated.
-
-contents/media_api/
-    Push to /sdcard/media_api/ for use with MediaTranscodingTest:
-    adb shell mkdir /sdcard/media_api
-    adb push contents/media_api/ /sdcard/media_api/
diff --git a/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml b/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml
deleted file mode 100644
index 9b2fa3b..0000000
--- a/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HEVC" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml b/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml
deleted file mode 100644
index 5ef5e51..0000000
--- a/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format />
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml b/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml
deleted file mode 100644
index e50c212..0000000
--- a/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml b/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml
deleted file mode 100644
index 3bff61e..0000000
--- a/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HDR10" supported="false"/>
-    <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml b/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml
deleted file mode 100644
index 5cf66b0..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HDR10" supported="true"/>
-    <format android:name="HDR10Plus" supported="true"/>
-    <format android:name="Dolby-Vision" supported="true"/>
-    <format android:name="HLG" supported="true"/>
-    <format android:name="SlowMotion" supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml b/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml
deleted file mode 100644
index 309aa1d..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HDR10" supported="true"/>
-    <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml b/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml
deleted file mode 100644
index 29454fc..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml b/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml
deleted file mode 100644
index 62de6cd..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="yes"/>
-    <format android:name="HDR10" supported="false"/>
-    <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml b/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml
deleted file mode 100644
index 5db42e5..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capability xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HDR10" supported="true"/>
-    <format android:name="SlowMotion" supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml b/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml
deleted file mode 100644
index e924c48..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HDR10" supported="true"/>
-    <format android:name="SlowMotion" supported="true"/>
-</MediaCapability>
diff --git a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh b/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
deleted file mode 100644
index c8fb3a6..0000000
--- a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Run tests in this directory.
-#
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
-    echo "Android build environment not set"
-    exit -1
-fi
-
-# ensure we have mm
-. $ANDROID_BUILD_TOP/build/envsetup.sh
-
-mm
-
-echo "[==========] waiting for device"
-adb root && adb wait-for-device remount
-
-echo "[==========] set to use real transcoder"
-adb shell setprop debug.transcoding.simulated_transcoder false;
-adb shell kill -9 `pid media.transcoding`
-
-echo "[==========] build test apk"
-mmm -j16 .
-adb install -r -g ${OUT}/testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
-# Push the files into app's cache directory/
-FILES=$ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets/*
-for file in $FILES
-do
-adb push --sync $file /data/user/0/com.android.mediatranscodingtest/cache/
-done
-
-echo "[==========] running MediaTranscodeManagerTest"
-adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
-
-echo "[==========] running MediaTranscodeManagerDiedTest"
-adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
-
diff --git a/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png b/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png
deleted file mode 100644
index a02138e..0000000
--- a/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png b/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png
deleted file mode 100644
index 64e3601..0000000
--- a/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/layout/surface_view.xml b/media/tests/MediaTranscodingTest/res/layout/surface_view.xml
deleted file mode 100644
index 3b49db0..0000000
--- a/media/tests/MediaTranscodingTest/res/layout/surface_view.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:orientation="vertical">
-
-  <FrameLayout
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-  <SurfaceView
-     android:id="@+id/surface_view"
-     android:layout_width="match_parent"
-     android:layout_height="match_parent"
-     android:layout_centerInParent="true"
-     />
-
-  </FrameLayout>
-
-</LinearLayout>
diff --git a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4 b/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4
deleted file mode 100644
index 2033a3f..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4 b/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4
deleted file mode 100644
index 7ac0024..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4 b/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4
deleted file mode 100644
index ef7e1b7..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/values/strings.xml b/media/tests/MediaTranscodingTest/res/values/strings.xml
deleted file mode 100644
index 0e1f8eb..0000000
--- a/media/tests/MediaTranscodingTest/res/values/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-	<!-- Test application name [CHAR LIMIT=32] -->
-    <string name="app_name">MediaTranscodingTest</string>
-</resources>
diff --git a/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml b/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml
deleted file mode 100644
index 3bff61e..0000000
--- a/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    <format android:name="HEVC" supported="true"/>
-    <format android:name="HDR10" supported="false"/>
-    <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java
deleted file mode 100644
index 74552a5..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-/*
- * Test for ApplicationMediaCapabilities in the media framework.
- *
- * To run this test suite:
-     make frameworks/base/media/tests/MediaTranscodingTest
-     make mediatranscodingtest
-
-     adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
-     adb shell am instrument -e class \
-     com.android.mediatranscodingtest.ApplicationMediaCapabilitiesTest \
-     -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.Context;
-import android.content.res.XmlResourceParser;
-import android.media.ApplicationMediaCapabilities;
-import android.media.MediaFeature;
-import android.media.MediaFormat;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-import android.util.Xml;
-
-import org.junit.Test;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-
-public class ApplicationMediaCapabilitiesTest extends
-        ActivityInstrumentationTestCase2<MediaTranscodingTest> {
-    private static final String TAG = "MediaCapabilityTest";
-
-    private Context mContext;
-
-    public ApplicationMediaCapabilitiesTest() {
-        super("com.android.MediaCapabilityTest", MediaTranscodingTest.class);
-    }
-
-    public void setUp() throws Exception {
-        Log.d(TAG, "setUp");
-        super.setUp();
-
-        mContext = getInstrumentation().getContext();
-    }
-
-
-    @Test
-    public void testSetSupportHevc() throws Exception {
-        ApplicationMediaCapabilities capability =
-                new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC).build();
-        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-
-        ApplicationMediaCapabilities capability2 =
-                new ApplicationMediaCapabilities.Builder().build();
-        assertFalse(capability2.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-    }
-
-    @Test
-    public void testSetSupportHdr() throws Exception {
-        ApplicationMediaCapabilities capability =
-                new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
-                        MediaFeature.HdrType.HDR10_PLUS).addSupportedVideoMimeType(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC).build();
-        assertEquals(true, capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
-    }
-
-    @Test
-    public void testSetSupportSlowMotion() throws Exception {
-        ApplicationMediaCapabilities capability =
-                new ApplicationMediaCapabilities.Builder().setSlowMotionSupported(true).build();
-        assertTrue(capability.isSlowMotionSupported());
-    }
-
-    @Test
-    public void testBuilder() throws Exception {
-        ApplicationMediaCapabilities capability =
-                new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC).addSupportedHdrType(
-                        MediaFeature.HdrType.HDR10_PLUS).setSlowMotionSupported(true).build();
-        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
-        assertTrue(capability.isSlowMotionSupported());
-    }
-
-    @Test
-    public void testSupportHdrWithoutSupportHevc() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            ApplicationMediaCapabilities capability =
-                    new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
-                            MediaFeature.HdrType.HDR10_PLUS).build();
-        });
-    }
-
-    //   Test read the application's xml from res/xml folder using the XmlResourceParser.
-    //    <format android:name="HEVC" supported="true"/>
-    //    <format android:name="HDR10" supported="false"/>
-    //    <format android:name="SlowMotion" supported="false"/>
-    @Test
-    public void testReadMediaCapabilitiesXml() throws Exception {
-        XmlResourceParser parser = mContext.getResources().getXml(R.xml.mediacapabilities);
-        ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                parser);
-        assertFalse(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
-        assertFalse(capability.isSlowMotionSupported());
-        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-    }
-
-    //   Test read the application's xml from res/xml folder using the XmlResourceParser.
-    //    <format android:name="HEVC" supported="true"/>
-    //    <format android:name="HDR10" supported="true"/>
-    //    <format android:name="HDR10Plus" supported="true"/>
-    //    <format android:name="Dolby-Vision" supported="true"/>
-    //    <format android:name="HLG" supported="true"/>
-    //    <format android:name="SlowMotion" supported="true"/>
-    @Test
-    public void testReadMediaCapabilitiesXmlWithSupportAllHdr() throws Exception {
-        InputStream xmlIs = mContext.getAssets().open("SupportAllHdr.xml");
-        final XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-
-        ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                parser);
-        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
-        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
-        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.DOLBY_VISION));
-        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HLG));
-        assertTrue(capability.isSlowMotionSupported());
-        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-    }
-
-    //   Test read the xml from res/assets folder using the InputStream.
-    //    <format android:name="HEVC" supported="true"/>
-    //    <format android:name="HDR10" supported="false"/>
-    //    <format android:name="SlowMotion" supported="false"/>
-    @Test
-    public void testReadFromCorrectXmlWithInputStreamInAssets() throws Exception {
-        InputStream xmlIs = mContext.getAssets().open("MediaCapabilities.xml");
-        final XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-
-        ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                parser);
-        assertFalse(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
-        assertFalse(capability.isSlowMotionSupported());
-        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-    }
-
-    // Test parsing invalid xml with wrong tag expect UnsupportedOperationException
-    // MediaCapability does not match MediaCapabilities at the end which will lead to
-    // exception with "Ill-formatted xml file"
-    // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
-    //    <format android:name="HEVC" supported="true"/>
-    //    <format android:name="HDR10" supported="true"/>
-    //    <format android:name="SlowMotion" supported="true"/>
-    // </MediaCapabilities>
-    @Test
-    public void testReadFromWrongMediaCapabilityXml() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("WrongMediaCapabilityTag.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test invalid xml with wrong tag expect UnsupportedOperationException
-    // MediaCapability is wrong tag.
-    // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
-    //    <format android:name="HEVC" supported="true"/>
-    //    <format android:name="HDR10" supported="true"/>
-    //    <format android:name="SlowMotion" supported="true"/>
-    // </MediaCapability>
-    @Test
-    public void testReadFromWrongMediaCapabilityXml2() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("WrongMediaCapabilityTag2.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test invalid attribute value of "support" with true->yes expect UnsupportedOperationException
-    // <MediaCapabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    //    <format android:name="HEVC" supported="yes"/>
-    //    <format android:name="HDR10" supported="false"/>
-    //    <format android:name="SlowMotion" supported="false"/>
-    // </MediaCapabilities>
-    @Test
-    public void testReadFromXmlWithWrongBoolean() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("WrongBooleanValue.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test parsing capabilities that support HDR10 but not support HEVC.
-    // Expect UnsupportedOperationException
-    // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
-    //    <format android:name="HDR10" supported="true"/>
-    //    <format android:name="SlowMotion" supported="false"/>
-    // </MediaCapabilities>
-    @Test
-    public void testReadXmlSupportHdrWithoutSupportHevc() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("SupportHdrWithoutHevc.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test parsing capabilities that has conflicted supported value.
-    // Expect UnsupportedOperationException
-    // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    //     <format android:name="HEVC" supported="true"/>
-    //     <format android:name="HEVC" supported="false"/>
-    // </media-capabilities>
-    @Test
-    public void testReadXmlConflictSupportedValue() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("ConflictSupportedValue.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test parsing capabilities that has empty format.
-    // Expect UnsupportedOperationException
-    // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    //     <format/>
-    // </media-capabilities>
-    @Test
-    public void testReadXmlWithEmptyFormat() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("EmptyFormat.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test parsing capabilities that has empty format.
-    // Expect UnsupportedOperationException
-    // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    //     <format android:name="HEVC"/>
-    // </media-capabilities>
-    @Test
-    public void testReadXmlFormatWithoutSupported() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("FormatWithoutSupported.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-
-    // Test parsing capabilities that has supported without the format name.
-    // Expect UnsupportedOperationException
-    // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-    //     <format supported="true"/>
-    // </media-capabilities>
-    @Test
-    public void testReadXmlSupportedWithoutFormat() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            InputStream xmlIs = mContext.getAssets().open("SupportedWithoutFormat.xml");
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-            ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
-                    parser);
-        });
-    }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
deleted file mode 100644
index 52f2787..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
-    /*
-     * Source test files.
-     */
-    public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
-        "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
-    };
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
deleted file mode 100644
index 7c9842b..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.MediaTranscodingException;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.ParcelFileDescriptor;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/*
- * Service died tests for MediaTranscodeManager in the media framework.
- *
- * To run this test suite:
-     make frameworks/base/media/tests/MediaTranscodingTest
-     make mediatranscodingtest
-
-     adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
-     adb shell am instrument -e class \
-     com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest \
-     -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodeManagerDiedTest
-        extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
-    private static final String TAG = "MediaTranscodeManagerDiedTest";
-    /** The time to wait for the transcode operation to complete before failing the test. */
-    private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
-
-    /** Maximum number of retry to connect to the service. */
-    private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
-    /** Interval between trying to reconnect to the service. */
-    private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
-    private Context mContext;
-    private MediaTranscodeManager mMediaTranscodeManager = null;
-    private Uri mSourceHEVCVideoUri = null;
-    private Uri mSourceAVCVideoUri = null;
-    private Uri mDestinationUri = null;
-
-    // Setting for transcoding to H.264.
-    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
-    private static final int BIT_RATE = 20000000;            // 20Mbps
-    private static final int WIDTH = 1920;
-    private static final int HEIGHT = 1080;
-
-    public MediaTranscodeManagerDiedTest() {
-        super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class);
-    }
-
-    // Copy the resource to cache.
-    private Uri resourceToUri(Context context, int resId, String name) throws IOException {
-        Uri resUri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(context.getResources().getResourcePackageName(resId))
-                .appendPath(context.getResources().getResourceTypeName(resId))
-                .appendPath(context.getResources().getResourceEntryName(resId))
-                .build();
-
-        Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/" + name);
-
-        InputStream is = mContext.getResources().openRawResource(resId);
-        OutputStream os = mContext.getContentResolver().openOutputStream(cacheUri);
-
-        FileUtils.copy(is, os);
-
-        return cacheUri;
-    }
-
-    private static Uri generateNewUri(Context context, String filename) {
-        File outFile = new File(context.getExternalCacheDir(), filename);
-        return Uri.fromFile(outFile);
-    }
-
-    /**
-     * Creates a MediaFormat with the basic set of values.
-     */
-    private static MediaFormat createMediaFormat() {
-        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
-        return format;
-    }
-
-    private MediaTranscodeManager getManager() {
-        for (int count = 1; count <= CONNECT_SERVICE_RETRY_COUNT; count++) {
-            Log.d(TAG, "Trying to connect to service. Try count: " + count);
-            MediaTranscodeManager manager = mContext.getSystemService(MediaTranscodeManager.class);
-            if (manager != null) {
-                return manager;
-            }
-            try {
-                // Sleep a bit before retry.
-                Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
-            } catch (InterruptedException ie) {
-                /* ignore */
-            }
-        }
-
-        throw new UnsupportedOperationException("Failed to acquire MediaTranscodeManager");
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        Log.d(TAG, "setUp");
-        super.setUp();
-
-        mContext = getInstrumentation().getContext();
-        mMediaTranscodeManager = getManager();
-        assertNotNull(mMediaTranscodeManager);
-        androidx.test.InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
-
-        // Setup source HEVC file uri.
-        mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC, "VideoOnlyHEVC.mp4");
-
-        // Setup source AVC file uri.
-        mSourceAVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyAVC,
-                "VideoOnlyAVC.mp4");
-
-        // Setup destination file.
-        mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    // [[ $(adb shell whoami) == "root" ]]
-    private boolean checkIfRoot() {
-        try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation()
-                .executeShellCommand("whoami");
-             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
-                     new FileInputStream(result.getFileDescriptor())))) {
-            String line;
-            while ((line = bufferedReader.readLine()) != null) {
-                if (line.contains("root")) {
-                    return true;
-                }
-            }
-        } catch (IOException ie) {
-            return false;
-        }
-        return false;
-    }
-
-    private String executeShellCommand(String cmd) throws Exception {
-        return UiDevice.getInstance(
-                InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
-    }
-
-    @Test
-    public void testHandleTranscoderServiceDied() throws Exception {
-        if (!checkIfRoot()) {
-            throw new AssertionError("must be root to run this test; try adb root?");
-        }
-
-        Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-        Semaphore sessionStartedSemaphore = new Semaphore(0);
-
-        // Transcode a 15 seconds video, so that the transcoding is not finished when we kill the
-        // service.
-        Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
-        TranscodingRequest request =
-                new TranscodingRequest.Builder()
-                        .setSourceUri(mSourceHEVCVideoUri)
-                        .setDestinationUri(destinationUri)
-                        .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                        .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                        .setVideoTrackFormat(createMediaFormat())
-                        .build();
-        Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-        Log.i(TAG, "transcoding to " + createMediaFormat());
-
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                listenerExecutor,
-                TranscodingSession -> {
-                    Log.d(TAG,
-                            "Transcoding completed with result: " + TranscodingSession.getResult());
-                    transcodeCompleteSemaphore.release();
-                });
-        assertNotNull(session);
-
-        AtomicInteger progressUpdateCount = new AtomicInteger(0);
-
-        // Set progress update executor and use the same executor as result listener.
-        session.setOnProgressUpdateListener(listenerExecutor,
-                new TranscodingSession.OnProgressUpdateListener() {
-                    @Override
-                    public void onProgressUpdate(TranscodingSession session, int newProgress) {
-                        if (newProgress > 0) {
-                            sessionStartedSemaphore.release();
-                        }
-                    }
-                });
-
-        // Wait for progress update so the session is in running state.
-        sessionStartedSemaphore.tryAcquire(TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        assertTrue("session is not running",
-                session.getStatus() == TranscodingSession.STATUS_RUNNING);
-
-        // Kills the service and expects receiving failure of the session.
-        executeShellCommand("pkill -f media.transcoding");
-
-        Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode result.");
-        boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        assertTrue("Invalid session status",
-                session.getStatus() == TranscodingSession.STATUS_FINISHED);
-        assertTrue("Invalid session result",
-                session.getResult() == TranscodingSession.RESULT_ERROR);
-
-
-        boolean retrysession = false;
-        // Wait till service is available again.
-        Log.d(TAG, "Retry the failed transcoding session");
-        while (!retrysession) {
-            try {
-                session.retry();
-                // Break out when session retry succeeds.
-                break;
-            } catch (MediaTranscodingException.ServiceNotAvailableException ex) {
-                // Sleep for 10 milliseconds to wait.
-                Thread.sleep(10);
-            }
-        }
-
-        finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        // Check the make sure session is successfully finished after retry.
-        assertTrue("Invalid session status",
-                session.getStatus() == TranscodingSession.STATUS_FINISHED);
-        assertTrue("Invalid session result",
-                session.getResult() == TranscodingSession.RESULT_SUCCESS);
-    }
-}
-
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
deleted file mode 100644
index 8231988..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.ApplicationMediaCapabilities;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.TranscodingTestConfig;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.ParcelFileDescriptor;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/*
- * Functional tests for MediaTranscodeManager in the media framework.
- * The test uses actual media.Transcoding service as backend to fully
- * test the API functionality.
- *
- * To run this test suite:
-     make frameworks/base/media/tests/MediaTranscodingTest
-     make mediatranscodingtest
-
-     adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
-     adb shell am instrument -e class \
-     com.android.mediatranscodingtest.MediaTranscodeManagerTest \
-     -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodeManagerTest
-        extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
-    private static final String TAG = "MediaTranscodeManagerTest";
-    /** The time to wait for the transcode operation to complete before failing the test. */
-    private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
-
-    /** Maximum number of retry to connect to the service. */
-    private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
-    /** Interval between trying to reconnect to the service. */
-    private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
-    private Context mContext;
-    private MediaTranscodeManager mMediaTranscodeManager = null;
-    private Uri mSourceHEVCVideoUri = null;
-    private Uri mSourceAVCVideoUri = null;
-    private Uri mDestinationUri = null;
-
-    // Setting for transcoding to H.264.
-    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
-    private static final int BIT_RATE = 20000000;            // 20Mbps
-    private static final int WIDTH = 1920;
-    private static final int HEIGHT = 1080;
-
-    // Threshold for the psnr to make sure the transcoded video is sane.
-    private static final int PSNR_THRESHOLD = 20;
-
-    public MediaTranscodeManagerTest() {
-        super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class);
-    }
-
-
-    // Copy the resource to cache.
-    private Uri resourceToUri(Context context, int resId, String name) throws IOException {
-        Uri resUri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(context.getResources().getResourcePackageName(resId))
-                .appendPath(context.getResources().getResourceTypeName(resId))
-                .appendPath(context.getResources().getResourceEntryName(resId))
-                .build();
-
-        Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/" + name);
-
-        InputStream is = mContext.getResources().openRawResource(resId);
-        OutputStream os = mContext.getContentResolver().openOutputStream(cacheUri);
-
-        FileUtils.copy(is, os);
-
-        return cacheUri;
-    }
-
-    private static Uri generateNewUri(Context context, String filename) {
-        File outFile = new File(context.getExternalCacheDir(), filename);
-        return Uri.fromFile(outFile);
-    }
-
-    // Generates a invalid uri which will let the mock service return transcoding failure.
-    private static Uri generateInvalidTranscodingUri(Context context) {
-        File outFile = new File(context.getExternalCacheDir(), "InvalidUri.mp4");
-        return Uri.fromFile(outFile);
-    }
-
-    /**
-     * Creates a MediaFormat with the basic set of values.
-     */
-    private static MediaFormat createMediaFormat() {
-        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
-        return format;
-    }
-
-    private MediaTranscodeManager getManager() {
-        for (int count = 1; count <= CONNECT_SERVICE_RETRY_COUNT; count++) {
-            Log.d(TAG, "Trying to connect to service. Try count: " + count);
-            MediaTranscodeManager manager = mContext.getSystemService(MediaTranscodeManager.class);
-            if (manager != null) {
-                return manager;
-            }
-            try {
-                // Sleep a bit before retry.
-                Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
-            } catch (InterruptedException ie) {
-                /* ignore */
-            }
-        }
-
-        throw new UnsupportedOperationException("Failed to acquire MediaTranscodeManager");
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        Log.d(TAG, "setUp");
-        super.setUp();
-
-        mContext = getInstrumentation().getContext();
-        mMediaTranscodeManager = getManager();
-        assertNotNull(mMediaTranscodeManager);
-        androidx.test.InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
-
-        // Setup source HEVC file uri.
-        mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC, "VideoOnlyHEVC.mp4");
-
-        // Setup source AVC file uri.
-        mSourceAVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyAVC,
-                "VideoOnlyAVC.mp4");
-
-        // Setup destination file.
-        mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-
-    /**
-     * Verify that setting null destination uri will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithNullDestinationUri() throws Exception {
-        assertThrows(IllegalArgumentException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setDestinationUri(null)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that setting invalid pid will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingWithInvalidClientPid() throws Exception {
-        assertThrows(IllegalArgumentException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setClientPid(-1)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that setting invalid uid will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingWithInvalidClientUid() throws Exception {
-        assertThrows(IllegalArgumentException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setClientUid(-1)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that setting null source uri will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithNullSourceUri() throws Exception {
-        assertThrows(IllegalArgumentException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(null)
-                            .setDestinationUri(mDestinationUri)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that not setting source uri will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithoutSourceUri() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that not setting destination uri will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithoutDestinationUri() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that setting image transcoding mode will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithUnsupportedMode() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_IMAGE)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-        });
-    }
-
-    /**
-     * Verify that setting video transcoding without setting video format will throw exception.
-     */
-    @Test
-    public void testCreateTranscodingRequestWithoutVideoFormat() throws Exception {
-        assertThrows(UnsupportedOperationException.class, () -> {
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(mSourceHEVCVideoUri)
-                            .setDestinationUri(mDestinationUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .build();
-        });
-    }
-
-    void testTranscodingWithExpectResult(Uri srcUri, Uri dstUri, int expectedResult)
-            throws Exception {
-        Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-        TranscodingTestConfig testConfig = new TranscodingTestConfig();
-        testConfig.passThroughMode = true;
-        testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding.
-
-        TranscodingRequest request =
-                new TranscodingRequest.Builder()
-                        .setSourceUri(srcUri)
-                        .setDestinationUri(dstUri)
-                        .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                        .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                        .setVideoTrackFormat(createMediaFormat())
-                        .setTestConfig(testConfig)
-                        .build();
-        Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                listenerExecutor,
-                TranscodingSession -> {
-                    Log.d(TAG,
-                            "Transcoding completed with result: " + TranscodingSession.getResult());
-                    assertTrue("Transcoding should failed.",
-                            TranscodingSession.getResult() == expectedResult);
-                    transcodeCompleteSemaphore.release();
-                });
-        assertNotNull(session);
-
-        if (session != null) {
-            Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
-            boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                    TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-            assertTrue("Transcode failed to complete in time.", finishedOnTime);
-        }
-
-        if (expectedResult == TranscodingSession.RESULT_SUCCESS) {
-            // Checks the destination file get generated.
-            File file = new File(dstUri.getPath());
-            assertTrue("Failed to create destination file", file.exists());
-
-            // Removes the file.
-            file.delete();
-        }
-    }
-
-    // Tests transcoding from invalid a invalid  and expects failure.
-    @Test
-    public void testTranscodingInvalidSrcUri() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        Uri invalidSrcUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
-                + mContext.getPackageName() + "/source.mp4");
-        Log.d(TAG, "Transcoding from source: " + invalidSrcUri);
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        // The full path of this file is:
-        // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
-                + mContext.getPackageName() + "/temp.mp4");
-        Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
-        testTranscodingWithExpectResult(invalidSrcUri, destinationUri,
-                TranscodingSession.RESULT_ERROR);
-    }
-
-    // Tests transcoding to a uri in res folder and expects failure as we could not write to res
-    // folder.
-    @Test
-    public void testTranscodingToResFolder() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        // The full path of this file is:
-        // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
-                + mContext.getPackageName() + "/temp.mp4");
-        Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
-        testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
-                TranscodingSession.RESULT_ERROR);
-    }
-
-    // Tests transcoding to a uri in internal storage folder and expects success.
-    @Test
-    public void testTranscodingToCacheDir() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        // The full path of this file is:
-        // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/temp.mp4");
-
-        testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
-                TranscodingSession.RESULT_SUCCESS);
-    }
-
-    // Tests transcoding to a uri in internal files directory and expects success.
-    @Test
-    public void testTranscodingToInternalFilesDir() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        // Create a file Uri:
-        // file:///storage/emulated/0/Android/data/com.android.mediatranscodingtest/files/temp.mp4
-        Uri destinationUri = Uri.fromFile(new File(mContext.getFilesDir(), "temp.mp4"));
-        Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
-        testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
-                TranscodingSession.RESULT_SUCCESS);
-    }
-
-    // Tests transcoding to a uri in external files directory and expects success.
-    @Test
-    public void testTranscodingToExternalFilesDir() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/files/temp.mp4
-        Uri destinationUri = Uri.fromFile(new File(mContext.getExternalFilesDir(null), "temp.mp4"));
-        Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
-        testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
-                TranscodingSession.RESULT_SUCCESS);
-    }
-
-    @Test
-    public void testTranscodingFromHevcToAvc() throws Exception {
-        Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        // The full path of this file is:
-        // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
-        ApplicationMediaCapabilities clientCaps =
-                new ApplicationMediaCapabilities.Builder().build();
-        MediaFormatResolver resolver = new MediaFormatResolver()
-                .setSourceVideoFormatHint(MediaFormat.createVideoFormat(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC, WIDTH, HEIGHT))
-                .setClientCapabilities(clientCaps);
-        assertTrue(resolver.shouldTranscode());
-        MediaFormat videoTrackFormat = resolver.resolveVideoFormat();
-        assertNotNull(videoTrackFormat);
-
-        int pid = android.os.Process.myPid();
-        int uid = android.os.Process.myUid();
-
-        TranscodingRequest request =
-                new TranscodingRequest.Builder()
-                        .setSourceUri(mSourceHEVCVideoUri)
-                        .setDestinationUri(destinationUri)
-                        .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                        .setClientPid(pid)
-                        .setClientUid(uid)
-                        .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                        .setVideoTrackFormat(videoTrackFormat)
-                        .build();
-        Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-        assertEquals(pid, request.getClientPid());
-        assertEquals(uid, request.getClientUid());
-
-        Log.i(TAG, "transcoding to " + videoTrackFormat);
-
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                listenerExecutor,
-                TranscodingSession -> {
-                    Log.d(TAG,
-                            "Transcoding completed with result: " + TranscodingSession.getResult());
-                    assertEquals(TranscodingSession.getResult(), TranscodingSession.RESULT_SUCCESS);
-                    transcodeCompleteSemaphore.release();
-                });
-        assertNotNull(session);
-
-        if (session != null) {
-            Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
-            boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                    TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-            assertTrue("Transcode failed to complete in time.", finishedOnTime);
-        }
-
-        // TODO(hkuang): Validate the transcoded video's width and height, framerate.
-
-        // Validates the transcoded video's psnr.
-        MediaTranscodingTestUtil.VideoTranscodingStatistics stats =
-                MediaTranscodingTestUtil.computeStats(mContext, mSourceAVCVideoUri, destinationUri);
-        assertTrue("PSNR: " + stats.mAveragePSNR + " is too low",
-                stats.mAveragePSNR >= PSNR_THRESHOLD);
-    }
-
-
-    @Test
-    public void testCancelTranscoding() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-        Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-
-        // Transcode a 15 seconds video, so that the transcoding is not finished when we cancel.
-        Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
-        TranscodingRequest request =
-                new TranscodingRequest.Builder()
-                        .setSourceUri(srcUri)
-                        .setDestinationUri(destinationUri)
-                        .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                        .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                        .setVideoTrackFormat(createMediaFormat())
-                        .build();
-        Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                listenerExecutor,
-                TranscodingSession -> {
-                    Log.d(TAG,
-                            "Transcoding completed with result: " + TranscodingSession.getResult());
-                    assertEquals(TranscodingSession.getResult(),
-                            TranscodingSession.RESULT_CANCELED);
-                    transcodeCompleteSemaphore.release();
-                });
-        assertNotNull(session);
-
-        // TODO(hkuang): Wait for progress update before calling cancel to make sure transcoding is
-        // started.
-
-        session.cancel();
-        Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
-        boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                30, TimeUnit.MILLISECONDS);
-        assertTrue("Fails to cancel transcoding", finishedOnTime);
-    }
-
-
-    @Test
-    public void testTranscodingProgressUpdate() throws Exception {
-        Log.d(TAG, "Starting: testMediaTranscodeManager");
-
-        Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-        final CountDownLatch statusLatch = new CountDownLatch(1);
-
-        // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        // The full path of this file is:
-        // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
-        Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
-        TranscodingRequest request =
-                new TranscodingRequest.Builder()
-                        .setSourceUri(mSourceHEVCVideoUri)
-                        .setDestinationUri(destinationUri)
-                        .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                        .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                        .setVideoTrackFormat(createMediaFormat())
-                        .build();
-        Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-        Log.i(TAG, "transcoding to " + createMediaFormat());
-
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                listenerExecutor,
-                TranscodingSession -> {
-                    Log.d(TAG,
-                            "Transcoding completed with result: " + TranscodingSession.getResult());
-                    assertEquals(TranscodingSession.getResult(), TranscodingSession.RESULT_SUCCESS);
-                    transcodeCompleteSemaphore.release();
-                });
-        assertNotNull(session);
-
-        AtomicInteger progressUpdateCount = new AtomicInteger(0);
-
-        // Set progress update executor and use the same executor as result listener.
-        session.setOnProgressUpdateListener(listenerExecutor,
-                new TranscodingSession.OnProgressUpdateListener() {
-                    int mPreviousProgress = 0;
-
-                    @Override
-                    public void onProgressUpdate(TranscodingSession session, int newProgress) {
-                        assertTrue("Invalid proress update", newProgress > mPreviousProgress);
-                        assertTrue("Invalid proress update", newProgress <= 100);
-                        if (newProgress > 0) {
-                            statusLatch.countDown();
-                        }
-                        mPreviousProgress = newProgress;
-                        progressUpdateCount.getAndIncrement();
-                        Log.i(TAG, "Get progress update " + newProgress);
-                    }
-                });
-
-        try {
-            statusLatch.await();
-            // The transcoding should not be finished yet as the clip is long.
-            assertTrue("Invalid status", session.getStatus() == TranscodingSession.STATUS_RUNNING);
-        } catch (InterruptedException e) {
-        }
-
-        Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
-        boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        assertTrue("Transcode failed to complete in time.", finishedOnTime);
-        assertTrue("Failed to receive at least 10 progress updates",
-                progressUpdateCount.get() > 10);
-    }
-
-    // [[ $(adb shell whoami) == "root" ]]
-    private boolean checkIfRoot() throws IOException {
-        try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation()
-                .executeShellCommand("whoami");
-             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
-                     new FileInputStream(result.getFileDescriptor())))) {
-            String line;
-            while ((line = bufferedReader.readLine()) != null) {
-                if (line.contains("root")) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private String executeShellCommand(String cmd) throws Exception {
-        return UiDevice.getInstance(
-                InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
-    }
-}
-
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
deleted file mode 100644
index b152450..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.MediaTranscodingException;
-import android.net.Uri;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/*
- * Benchmarking for MediaTranscodeManager in the media framework.
- *
- * Note: This benchmarking requires to push all the files from http://go/transcodingbenchmark
- * to /data/user/0/com.android.mediatranscodingtest/cache/ directory after installing the apk.
- *
- * TODO(hkuang): Change it to download from server automatically instead of manually.
- *
- * To run this test suite:
-     make frameworks/base/media/tests/MediaTranscodingTest
-     make mediatranscodingtest
-
-     adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-      // Push the files to /data/user/0/com.android.mediatranscodingtest/cache/
-     adb push $DOWNLOADPATH/*.mp4 /data/user/0/com.android.mediatranscodingtest/cache/
-
-     adb shell am instrument -e class \
-     com.android.mediatranscodingtest.MediaTranscodingBenchmark \
-     -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodingBenchmark
-        extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
-    private static final String TAG = "MediaTranscodingBenchmark";
-    // TODO(hkuang): Change this to query from MediaCodecInfo.CodecCapabilities for different
-    // resolution.
-    private static final int MINIMUM_TRANSCODING_FPS = 80;
-    private static final int LOOP_COUNT = 3;
-    // Default Setting for transcoding to H.264.
-    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
-    private static final int BIT_RATE = 20000000;            // 20Mbps
-    private static final int WIDTH = 1920;
-    private static final int HEIGHT = 1080;
-    private Context mContext;
-    private MediaTranscodeManager mMediaTranscodeManager = null;
-
-    public MediaTranscodingBenchmark() {
-        super("com.android.MediaTranscodingBenchmark", MediaTranscodingTest.class);
-    }
-
-    /**
-     * Creates a MediaFormat with the basic set of values.
-     */
-    private static MediaFormat createMediaFormat() {
-        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
-        return format;
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        Log.d(TAG, "setUp");
-        super.setUp();
-        mContext = getInstrumentation().getContext();
-        mMediaTranscodeManager = mContext.getSystemService(MediaTranscodeManager.class);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    /*
-     * Transcode the sourceFileName to destinationFileName with LOOP_COUNT.
-     */
-    private void transcode(final String sourceFileName, final String destinationFileName)
-            throws IOException, InterruptedException,
-            MediaTranscodingException.ServiceNotAvailableException {
-        AtomicLong totalTimeMs = new AtomicLong();
-        AtomicLong transcodingTime = new AtomicLong();
-        Uri srcUri = getUri(sourceFileName);
-        Uri dstUri = getUri(destinationFileName);
-
-        MediaTranscodingTestUtil.VideoFileInfo info =
-                MediaTranscodingTestUtil.extractVideoFileInfo(mContext, getUri(sourceFileName));
-
-        int timeoutSeconds = calMaxTranscodingWaitTimeSeconds(info.mNumVideoFrames,
-                MINIMUM_TRANSCODING_FPS);
-        Log.d(TAG, "Start Transcoding " + info.toString() + " " + timeoutSeconds);
-
-        for (int loop = 0; loop < LOOP_COUNT; ++loop) {
-            Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-            TranscodingRequest request =
-                    new TranscodingRequest.Builder()
-                            .setSourceUri(srcUri)
-                            .setDestinationUri(dstUri)
-                            .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
-                            .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
-                            .setVideoTrackFormat(createMediaFormat())
-                            .build();
-            Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
-            long startTimeMs = System.currentTimeMillis();
-            TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
-                    listenerExecutor,
-                    TranscodingSession -> {
-                        Log.d(TAG,
-                                "Transcoding completed with result: "
-                                        + TranscodingSession.getResult());
-                        assertEquals(TranscodingSession.getResult(),
-                                TranscodingSession.RESULT_SUCCESS);
-                        transcodingTime.set(System.currentTimeMillis() - startTimeMs);
-                        totalTimeMs.addAndGet(transcodingTime.get());
-                        transcodeCompleteSemaphore.release();
-                    });
-
-            if (session != null) {
-                Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
-                boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
-                        timeoutSeconds, TimeUnit.SECONDS);
-                assertTrue("Transcode failed to complete in time.", finishedOnTime);
-            }
-            Log.i(TAG, "Loop: " + loop + " take " + transcodingTime.get() + " ms ");
-        }
-
-        float fps = info.mNumVideoFrames * 1000 * LOOP_COUNT / totalTimeMs.get();
-        Log.i(TAG, "Transcoding " + info.toString() + " Transcoding fps: " + fps);
-    }
-
-    // Calculate the maximum wait time based on minimum transcoding throughput and frame number.
-    private int calMaxTranscodingWaitTimeSeconds(int numberFrames, int minTranscodingFps) {
-        float waitTime = (float) numberFrames / (float) minTranscodingFps;
-        // If waitTimeSeconds is 0, wait for 1 second at least.
-        int waitTimeSeconds = (int) Math.ceil(waitTime);
-        return waitTimeSeconds == 0 ? 1 : waitTimeSeconds;
-    }
-
-    private Uri getUri(final String fileName) {
-        String path = mContext.getCacheDir().getAbsolutePath();
-        return new Uri.Builder().scheme(ContentResolver.SCHEME_FILE).appendPath(path).appendPath(
-                fileName).build();
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith66FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_66frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith66FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_66frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith361FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_361frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith361FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_361frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith943FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_943frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith943FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_943frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith1822FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_1822frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith1822FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_1822frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith3648FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_3648frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith3648FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith11042FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_11042frame_h264_22Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingAVCToAVCWith11042FramesWithAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_11042frame_h264_22Mbps_30fps_aac";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingHEVCToAVCWith107FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_107frame_hevc_4Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingHEVCToAVCWith928FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_928frame_hevc_4Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingHEVCToAVCWith1863FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_1863frame_hevc_4Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingHEVCToAVCWith3863FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_3863frame_hevc_4Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-
-    @Test
-    public void testBenchmarkingHEVCToAVCWith9374FramesWithoutAudio() throws Exception {
-        String videoNameWithoutExtension = "video_1920x1080_9374frame_hevc_4Mbps_30fps";
-        String testVideoName = videoNameWithoutExtension + ".mp4";
-        String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
-        transcode(testVideoName, transcodedVideoName);
-    }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java
deleted file mode 100644
index 6f83bad..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.PowerManager;
-
-public class MediaTranscodingTest extends Activity {
-    private PowerManager.WakeLock mWakeLock = null;
-
-    public MediaTranscodingTest() {
-    }
-
-    /** Called when the activity is first created. */
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.surface_view);
-
-        //Acquire the full wake lock to keep the device up
-        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MediaTranscodingTest");
-        mWakeLock.acquire();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        mWakeLock.release();
-    }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
deleted file mode 100644
index 76050ac..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-import junit.framework.TestSuite;
-
-
-/**
- * Instrumentation Test Runner for all MediaTranscoding tests.
- *
- * Running all tests:
- *
- * adb shell am instrument \
- *  -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- */
-
-public class MediaTranscodingTestRunner extends InstrumentationTestRunner {
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(MediaTranscodeManagerDiedTest.class);
-        suite.addTestSuite(ApplicationMediaCapabilitiesTest.class);
-        suite.addTestSuite(MediaTranscodeManagerTest.class);
-        suite.addTestSuite(MediaTranscodingBenchmark.class);
-        return suite;
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return MediaTranscodingTestRunner.class.getClassLoader();
-    }
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-    }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java
deleted file mode 100644
index 69f124f..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import static org.junit.Assert.assertTrue;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.ImageFormat;
-import android.media.Image;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.util.Log;
-import android.util.Size;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.Locale;
-
-
-/* package */ class MediaTranscodingTestUtil {
-    private static final String TAG = "MediaTranscodingTestUtil";
-
-    // Helper class to extract the information from source file and transcoded file.
-    static class VideoFileInfo {
-        String mUri;
-        int mNumVideoFrames = 0;
-        int mWidth = 0;
-        int mHeight = 0;
-        float mVideoFrameRate = 0.0f;
-        boolean mHasAudio = false;
-
-        public String toString() {
-            String str = mUri;
-            str += " Width:" + mWidth;
-            str += " Height:" + mHeight;
-            str += " FrameRate:" + mWidth;
-            str += " FrameCount:" + mNumVideoFrames;
-            str +=  " HasAudio:" + (mHasAudio ? "Yes" : "No");
-            return str;
-        }
-    }
-
-    static VideoFileInfo extractVideoFileInfo(Context ctx, Uri videoUri) throws IOException {
-        VideoFileInfo info = new VideoFileInfo();
-        AssetFileDescriptor afd =  null;
-        MediaMetadataRetriever retriever = null;
-
-        try {
-            afd = ctx.getContentResolver().openAssetFileDescriptor(videoUri, "r");
-            retriever = new MediaMetadataRetriever();
-            retriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-
-            info.mUri = videoUri.getLastPathSegment();
-            Log.i(TAG, "Trying to transcode to " + info.mUri);
-            String width = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
-            String height = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
-            if (width != null && height != null) {
-                info.mWidth = Integer.parseInt(width);
-                info.mHeight = Integer.parseInt(height);
-            }
-
-            String frameRate = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE);
-            if (frameRate != null) {
-                info.mVideoFrameRate = Float.parseFloat(frameRate);
-            }
-
-            String frameCount = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT);
-            if (frameCount != null) {
-                info.mNumVideoFrames = Integer.parseInt(frameCount);
-            }
-
-            String hasAudio = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
-            if (hasAudio != null) {
-                info.mHasAudio = hasAudio.equals("yes");
-            }
-        } finally {
-            if (retriever != null) {
-                retriever.close();
-            }
-            if (afd != null) {
-                afd.close();
-            }
-        }
-        return info;
-    }
-
-    static VideoTranscodingStatistics computeStats(final Context ctx, final Uri sourceMp4,
-            final Uri transcodedMp4)
-            throws Exception {
-        // First decode the sourceMp4 to a temp yuv in yuv420p format.
-        Uri sourceYUV420PUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + ctx.getCacheDir().getAbsolutePath() + "/sourceYUV420P.yuv");
-        Size sourceSize = decodeMp4ToYuv(ctx, sourceMp4, sourceYUV420PUri);
-
-        // Second decode the transcodedMp4 to a temp yuv in yuv420p format.
-        Uri transcodedYUV420PUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
-                + ctx.getCacheDir().getAbsolutePath() + "/transcodedYUV420P.yuv");
-        Size transcodedSize = decodeMp4ToYuv(ctx, transcodedMp4, transcodedYUV420PUri);
-
-        assertTrue(sourceSize.equals(transcodedSize));
-
-        // Then Compute the psnr of transcodedYUV420PUri against sourceYUV420PUri.
-        return computePsnr(ctx, sourceYUV420PUri, transcodedYUV420PUri, sourceSize.getWidth(),
-                transcodedSize.getHeight());
-    }
-
-    private static Size decodeMp4ToYuv(final Context ctx, final Uri fileUri, final Uri yuvUri)
-            throws Exception {
-        AssetFileDescriptor fileFd = null;
-        MediaExtractor extractor = null;
-        MediaCodec codec = null;
-        AssetFileDescriptor yuvFd = null;
-        FileOutputStream out = null;
-        int width = 0;
-        int height = 0;
-
-        try {
-            fileFd = ctx.getContentResolver().openAssetFileDescriptor(fileUri,"r");
-            extractor = new MediaExtractor();
-            extractor.setDataSource(fileFd.getFileDescriptor(), fileFd.getStartOffset(),
-                    fileFd.getLength());
-
-            // Selects the video track.
-            int trackCount = extractor.getTrackCount();
-            if (trackCount <= 0) {
-                throw new IllegalArgumentException("Invalid mp4 file");
-            }
-            int videoTrackIndex = -1;
-            for (int i = 0; i < trackCount; i++) {
-                extractor.selectTrack(i);
-                MediaFormat format = extractor.getTrackFormat(i);
-                if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
-                    videoTrackIndex = i;
-                    break;
-                }
-            }
-            if (videoTrackIndex == -1) {
-                throw new IllegalArgumentException("Can not find video track");
-            }
-
-            extractor.selectTrack(videoTrackIndex);
-            MediaFormat format = extractor.getTrackFormat(videoTrackIndex);
-            String mime = format.getString(MediaFormat.KEY_MIME);
-            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                    MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
-
-            // Opens the yuv file uri.
-            yuvFd = ctx.getContentResolver().openAssetFileDescriptor(yuvUri,
-                    "w");
-            out = new FileOutputStream(yuvFd.getFileDescriptor());
-
-            codec = MediaCodec.createDecoderByType(mime);
-            codec.configure(format,
-                    null,  // surface
-                    null,  // crypto
-                    0);    // flags
-            codec.start();
-
-            ByteBuffer[] inputBuffers = codec.getInputBuffers();
-            ByteBuffer[] outputBuffers = codec.getOutputBuffers();
-            MediaFormat decoderOutputFormat = codec.getInputFormat();
-
-            // start decode loop
-            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-
-            final long kTimeOutUs = 1000; // 1ms timeout
-            long lastOutputTimeUs = 0;
-            boolean sawInputEOS = false;
-            boolean sawOutputEOS = false;
-            int inputNum = 0;
-            int outputNum = 0;
-            boolean advanceDone = true;
-
-            long start = System.currentTimeMillis();
-            while (!sawOutputEOS) {
-                // handle input
-                if (!sawInputEOS) {
-                    int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
-
-                    if (inputBufIndex >= 0) {
-                        ByteBuffer dstBuf = inputBuffers[inputBufIndex];
-                        // sample contains the buffer and the PTS offset normalized to frame index
-                        int sampleSize =
-                                extractor.readSampleData(dstBuf, 0 /* offset */);
-                        long presentationTimeUs = extractor.getSampleTime();
-                        advanceDone = extractor.advance();
-
-                        if (sampleSize < 0) {
-                            Log.d(TAG, "saw input EOS.");
-                            sawInputEOS = true;
-                            sampleSize = 0;
-                        }
-                        codec.queueInputBuffer(
-                                inputBufIndex,
-                                0 /* offset */,
-                                sampleSize,
-                                presentationTimeUs,
-                                sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-                    } else {
-                        Log.d(TAG, "codec.dequeueInputBuffer() unrecognized return value:");
-                    }
-                }
-
-                // handle output
-                int outputBufIndex = codec.dequeueOutputBuffer(info, kTimeOutUs);
-
-                if (outputBufIndex >= 0) {
-                    if (info.size > 0) { // Disregard 0-sized buffers at the end.
-                        outputNum++;
-                        Log.i(TAG, "Output frame numer " + outputNum);
-                        Image image = codec.getOutputImage(outputBufIndex);
-                        dumpYUV420PToFile(image, out);
-                    }
-
-                    codec.releaseOutputBuffer(outputBufIndex, false /* render */);
-                    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        Log.d(TAG, "saw output EOS.");
-                        sawOutputEOS = true;
-                    }
-                } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    outputBuffers = codec.getOutputBuffers();
-                    Log.d(TAG, "output buffers have changed.");
-                } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    decoderOutputFormat = codec.getOutputFormat();
-                    width = decoderOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
-                    height = decoderOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
-                    Log.d(TAG, "output resolution " + width + "x" + height);
-                } else {
-                    Log.w(TAG, "codec.dequeueOutputBuffer() unrecognized return index");
-                }
-            }
-        } finally {
-            codec.stop();
-            codec.release();
-            extractor.release();
-            out.close();
-            fileFd.close();
-            yuvFd.close();
-        }
-        return new Size(width, height);
-    }
-
-    private static void dumpYUV420PToFile(Image image, FileOutputStream out) throws IOException {
-        int format = image.getFormat();
-
-        if (ImageFormat.YUV_420_888 != format) {
-            throw new UnsupportedOperationException("Only supports YUV420P");
-        }
-
-        int imageWidth = image.getWidth();
-        int imageHeight = image.getHeight();
-        byte[] bb = new byte[imageWidth * imageHeight];
-        byte[] lb = null;
-        Image.Plane[] planes = image.getPlanes();
-        for (int i = 0; i < planes.length; ++i) {
-            ByteBuffer buf = planes[i].getBuffer();
-
-            int width, height, rowStride, pixelStride, x, y;
-            rowStride = planes[i].getRowStride();
-            pixelStride = planes[i].getPixelStride();
-            if (i == 0) {
-                width = imageWidth;
-                height = imageHeight;
-            } else {
-                width = imageWidth / 2;
-                height = imageHeight / 2;
-            }
-
-            if (buf.hasArray()) {
-                byte b[] = buf.array();
-                int offs = buf.arrayOffset();
-                if (pixelStride == 1) {
-                    for (y = 0; y < height; ++y) {
-                        System.arraycopy(bb, y * width, b, y * rowStride + offs, width);
-                    }
-                } else {
-                    // do it pixel-by-pixel
-                    for (y = 0; y < height; ++y) {
-                        int lineOffset = offs + y * rowStride;
-                        for (x = 0; x < width; ++x) {
-                            bb[y * width + x] = b[lineOffset + x * pixelStride];
-                        }
-                    }
-                }
-            } else { // almost always ends up here due to direct buffers
-                int pos = buf.position();
-                if (pixelStride == 1) {
-                    for (y = 0; y < height; ++y) {
-                        buf.position(pos + y * rowStride);
-                        buf.get(bb, y * width, width);
-                    }
-                } else {
-                    // Reallocate linebuffer if necessary.
-                    if (lb == null || lb.length < rowStride) {
-                        lb = new byte[rowStride];
-                    }
-                    // do it pixel-by-pixel
-                    for (y = 0; y < height; ++y) {
-                        buf.position(pos + y * rowStride);
-                        // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
-                        buf.get(lb, 0, pixelStride * (width - 1) + 1);
-                        for (x = 0; x < width; ++x) {
-                            bb[y * width + x] = lb[x * pixelStride];
-                        }
-                    }
-                }
-                buf.position(pos);
-            }
-            // Write out the buffer to the output.
-            out.write(bb, 0, width * height);
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    // The following psnr code is leveraged from the following file with minor modification:
-    // cts/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Calculates PSNR value between two video frames.
-     */
-    private static double computePSNR(byte[] data0, byte[] data1) {
-        long squareError = 0;
-        assertTrue(data0.length == data1.length);
-        int length = data0.length;
-        for (int i = 0; i < length; i++) {
-            int diff = ((int) data0[i] & 0xff) - ((int) data1[i] & 0xff);
-            squareError += diff * diff;
-        }
-        double meanSquareError = (double) squareError / length;
-        double psnr = 10 * Math.log10((double) 255 * 255 / meanSquareError);
-        return psnr;
-    }
-
-    /**
-     * Calculates average and minimum PSNR values between
-     * set of reference and decoded video frames.
-     * Runs PSNR calculation for the full duration of the decoded data.
-     */
-    private static VideoTranscodingStatistics computePsnr(
-            Context ctx,
-            Uri referenceYuvFileUri,
-            Uri decodedYuvFileUri,
-            int width,
-            int height) throws Exception {
-        VideoTranscodingStatistics statistics = new VideoTranscodingStatistics();
-        AssetFileDescriptor referenceFd = ctx.getContentResolver().openAssetFileDescriptor(
-                referenceYuvFileUri, "r");
-        InputStream referenceStream = new FileInputStream(referenceFd.getFileDescriptor());
-
-        AssetFileDescriptor decodedFd = ctx.getContentResolver().openAssetFileDescriptor(
-                decodedYuvFileUri, "r");
-        InputStream decodedStream = new FileInputStream(decodedFd.getFileDescriptor());
-
-        int ySize = width * height;
-        int uvSize = width * height / 4;
-        byte[] yRef = new byte[ySize];
-        byte[] yDec = new byte[ySize];
-        byte[] uvRef = new byte[uvSize];
-        byte[] uvDec = new byte[uvSize];
-
-        int frames = 0;
-        double averageYPSNR = 0;
-        double averageUPSNR = 0;
-        double averageVPSNR = 0;
-        double minimumYPSNR = Integer.MAX_VALUE;
-        double minimumUPSNR = Integer.MAX_VALUE;
-        double minimumVPSNR = Integer.MAX_VALUE;
-        int minimumPSNRFrameIndex = 0;
-
-        while (true) {
-            // Calculate Y PSNR.
-            int bytesReadRef = referenceStream.read(yRef);
-            int bytesReadDec = decodedStream.read(yDec);
-            if (bytesReadDec == -1) {
-                break;
-            }
-            if (bytesReadRef == -1) {
-                // Reference file wrapping up
-                referenceStream.close();
-                break;
-            }
-            double curYPSNR = computePSNR(yRef, yDec);
-            averageYPSNR += curYPSNR;
-            minimumYPSNR = Math.min(minimumYPSNR, curYPSNR);
-            double curMinimumPSNR = curYPSNR;
-
-            // Calculate U PSNR.
-            bytesReadRef = referenceStream.read(uvRef);
-            bytesReadDec = decodedStream.read(uvDec);
-            double curUPSNR = computePSNR(uvRef, uvDec);
-            averageUPSNR += curUPSNR;
-            minimumUPSNR = Math.min(minimumUPSNR, curUPSNR);
-            curMinimumPSNR = Math.min(curMinimumPSNR, curUPSNR);
-
-            // Calculate V PSNR.
-            bytesReadRef = referenceStream.read(uvRef);
-            bytesReadDec = decodedStream.read(uvDec);
-            double curVPSNR = computePSNR(uvRef, uvDec);
-            averageVPSNR += curVPSNR;
-            minimumVPSNR = Math.min(minimumVPSNR, curVPSNR);
-            curMinimumPSNR = Math.min(curMinimumPSNR, curVPSNR);
-
-            // Frame index for minimum PSNR value - help to detect possible distortions
-            if (curMinimumPSNR < statistics.mMinimumPSNR) {
-                statistics.mMinimumPSNR = curMinimumPSNR;
-                minimumPSNRFrameIndex = frames;
-            }
-
-            String logStr = String.format(Locale.US, "PSNR #%d: Y: %.2f. U: %.2f. V: %.2f",
-                    frames, curYPSNR, curUPSNR, curVPSNR);
-            Log.v(TAG, logStr);
-
-            frames++;
-        }
-
-        averageYPSNR /= frames;
-        averageUPSNR /= frames;
-        averageVPSNR /= frames;
-        statistics.mAveragePSNR = (4 * averageYPSNR + averageUPSNR + averageVPSNR) / 6;
-
-        Log.d(TAG, "PSNR statistics for " + frames + " frames.");
-        String logStr = String.format(Locale.US,
-                "Average PSNR: Y: %.1f. U: %.1f. V: %.1f. Average: %.1f",
-                averageYPSNR, averageUPSNR, averageVPSNR, statistics.mAveragePSNR);
-        Log.d(TAG, logStr);
-        logStr = String.format(Locale.US,
-                "Minimum PSNR: Y: %.1f. U: %.1f. V: %.1f. Overall: %.1f at frame %d",
-                minimumYPSNR, minimumUPSNR, minimumVPSNR,
-                statistics.mMinimumPSNR, minimumPSNRFrameIndex);
-        Log.d(TAG, logStr);
-
-        referenceStream.close();
-        decodedStream.close();
-        referenceFd.close();
-        decodedFd.close();
-        return statistics;
-    }
-
-    /**
-     * Transcoding PSNR statistics.
-     */
-    protected static class VideoTranscodingStatistics {
-        public double mAveragePSNR;
-        public double mMinimumPSNR;
-
-        VideoTranscodingStatistics() {
-            mMinimumPSNR = Integer.MAX_VALUE;
-        }
-    }
-}
-
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/mime/OWNERS b/mime/OWNERS
new file mode 100644
index 0000000..2357979
--- /dev/null
+++ b/mime/OWNERS
@@ -0,0 +1,2 @@
+include platform/libcore:/OWNERS
+include /core/java/android/os/storage/OWNERS
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index e5273a9..92365d1 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -63,6 +63,7 @@
 ?application/x-android-drm-fl fl
 ?application/x-flac flac
 ?application/x-font pcf
+?application/x-mobipocket-ebook prc mobi
 ?application/x-mpegurl m3u m3u8
 ?application/x-pem-file pem
 ?application/x-pkcs12 p12 pfx
diff --git a/native/android/aidl/com/android/internal/compat/OWNERS b/native/android/aidl/com/android/internal/compat/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/native/android/aidl/com/android/internal/compat/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/native/graphics/OWNERS b/native/graphics/OWNERS
new file mode 100644
index 0000000..a6d1bc3
--- /dev/null
+++ b/native/graphics/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/OWNERS
diff --git a/opengl/java/android/opengl/OWNERS b/opengl/java/android/opengl/OWNERS
new file mode 100644
index 0000000..9c6c610
--- /dev/null
+++ b/opengl/java/android/opengl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 25421
+
+sumir@google.com
+prahladk@google.com
diff --git a/packages/AppPredictionLib/OWNERS b/packages/AppPredictionLib/OWNERS
new file mode 100644
index 0000000..3a5d23d
--- /dev/null
+++ b/packages/AppPredictionLib/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/appprediction/OWNERS
diff --git a/packages/Backup/OWNERS b/packages/Backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/Backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/BackupEncryption/OWNERS b/packages/BackupEncryption/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/BackupEncryption/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/BackupRestoreConfirmation/OWNERS b/packages/BackupRestoreConfirmation/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
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/Connectivity/OWNERS b/packages/Connectivity/OWNERS
new file mode 100644
index 0000000..48e54da
--- /dev/null
+++ b/packages/Connectivity/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp
index 43e3868..14a3376 100644
--- a/packages/CtsShim/build/Android.bp
+++ b/packages/CtsShim/build/Android.bp
@@ -34,6 +34,8 @@
 
     compile_multilib: "both",
     jni_libs: ["libshim_jni"],
+
+    uses_libs: ["android.test.runner"],
 }
 
 genrule {
@@ -108,6 +110,7 @@
     compile_multilib: "both",
     jni_libs: ["libshim_jni"],
 
+    uses_libs: ["android.test.runner"],
 }
 
 //##########################################################
diff --git a/packages/EasterEgg/OWNERS b/packages/EasterEgg/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/packages/EasterEgg/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/packages/ExternalStorageProvider/OWNERS b/packages/ExternalStorageProvider/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/packages/ExternalStorageProvider/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/packages/FusedLocation/OWNERS b/packages/FusedLocation/OWNERS
new file mode 100644
index 0000000..5ac6028
--- /dev/null
+++ b/packages/FusedLocation/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/packages/MtpDocumentsProvider/OWNERS b/packages/MtpDocumentsProvider/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/packages/MtpDocumentsProvider/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/packages/PrintRecommendationService/OWNERS b/packages/PrintRecommendationService/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/packages/PrintRecommendationService/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
diff --git a/packages/PrintSpooler/OWNERS b/packages/PrintSpooler/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/packages/PrintSpooler/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
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/SettingsLib/HelpUtils/res/values-ar/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
index 7ab3abc..5b12fc5 100644
--- a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والتعليقات"</string>
+    <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والملاحظات والآراء"</string>
 </resources>
diff --git a/packages/SettingsLib/LayoutPreference/res/layout/layout_preference_frame.xml b/packages/SettingsLib/LayoutPreference/res/layout/layout_preference_frame.xml
index ee4ce49..4412e95 100644
--- a/packages/SettingsLib/LayoutPreference/res/layout/layout_preference_frame.xml
+++ b/packages/SettingsLib/LayoutPreference/res/layout/layout_preference_frame.xml
@@ -17,4 +17,5 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
-             android:layout_height="wrap_content"/>
+             android:layout_height="wrap_content"
+             android:importantForAccessibility="no"/>
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/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 41af185..c2b26bc 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktief. Tik om te wissel."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Mediakodewisselinginstellings"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiveer kodewisseling"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiveer kodewisseling vir programme"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ignoreer kodewisselingverstekke"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Aktiveer kodewisseling"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Aanvaar dat programme moderne formate steun"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Lopende dienste"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Sien en beheer dienste wat tans aktief is"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery word tydelik beperk"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimeer tans vir batterygesondheid"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedraade oorfoon"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Af"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Diensverskaffernetwerk verander tans"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data is af"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie gestel om data te gebruik nie"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Geen foon nie."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Foon, een staaf."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Foon, twee stawe."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Foon, drie stawe."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Foonsein is vol."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Geen data nie."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data, een staaf."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data, twee stawe."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data, drie stawe."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasein vol."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet is ontkoppel."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet gekoppel."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8e4e402..65ce6e0 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ገቢር። ለመቀያየር ነካ ያድርጉ።"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"የመተግበሪያ ዝግጁ የመሆን ሁኔታ፦<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"የሚዲያ ትራንስኮዲንግ ቅንብሮች"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ትራንስኮንግን አሰናክል"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ለመተግበሪያዎች ትራንስኮዲንግን ያንቁ"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"የትራንስኮዲንግ ነባሪዎችን ሻር"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ትራንስኮዲንግን ያንቁ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"መተግበሪያዎች ዘመናዊ ቅርጸቶችን እንደሚደግፉ አድርገው ይቁጠሩ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"የWebView ትግበራ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ባትሪ ለጊዜው ተገድቧል"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ለባትሪ ጤና ማመቻቸት"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ባለገመድ ጆሮ ማዳመጫ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"አብራ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"አጥፋ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"የአገልግሎት አቅራቢ አውታረ መረብን በመቀየር ላይ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3ጂ"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"ኤጅ"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"ጂፒአርኤስ"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"ሰ"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"ሰ+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4ጂ"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ምንም ስልክ የለም።"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"የስልክ አንድ አሞሌ"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"የስልክ ሁለት አሞሌ"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"የስልክ ሦስት አሞሌ"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"የስልክ አመልካች ሙሉ ነው።"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ምንም ውሂብ የለም።"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"የውሂብ አንድ አሞሌ"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"የውሂብ ሁለት አሞሌዎች።"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"የውሂብ ሦስት አሞሌዎች።"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"የውሂብ አመልካች ሙሉ ነው።"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ኤተርኔት ተነቅሏል።"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ኤተርኔት ተገናኝቷል።"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 691ec046..3ea96c7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"نشط، انقر للتبديل."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"حالة تطبيق وضع الاستعداد:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"إعدادات تحويل ترميز الوسائط"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"إيقاف تحويل الترميز"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"تفعيل تحويل الترميز للتطبيقات"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"إلغاء الإعدادات التلقائية لتحويل الترميز"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"تفعيل تحويل الترميز"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"افتراض أن التطبيق يتوافق مع التنسيقات الحديثة"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏تطبيق WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - تأثير محدود على البطارية مؤقتًا"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - التحسين لسلامة البطارية"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string>
@@ -518,7 +519,7 @@
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
-    <string name="help_label" msgid="3528360748637781274">"المساعدة والتعليقات"</string>
+    <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات والآراء"</string>
     <string name="storage_category" msgid="2287342585424631813">"مساحة التخزين"</string>
     <string name="shared_data_title" msgid="1017034836800864953">"البيانات المشتركة"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"عرض البيانات المشتركة وتعديلها"</string>
@@ -568,4 +569,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"سمّاعة سلكية"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"تفعيل"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"إيقاف"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"شبكة الجيل الثالث"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"‏شبكة EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"‏شبكة GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+‎"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"شبكة الجيل الرابع"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"شبكة الجيل الرابع أو أحدث"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+‎"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"تم إيقاف بيانات الجوال"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"لم يتم الضبط على استخدام البيانات"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ليست هناك إشارة بالهاتف."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"إشارة الهاتف تتكون من شريط واحد."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"إشارة الهاتف تتكون من شريطين."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"إشارة الهاتف تتكون من ثلاثة أشرطة."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"إشارة الهاتف كاملة."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"لا تتوفر بيانات."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"إشارة البيانات تتكون من شريط واحد."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"إشارة البيانات تتكون من شريطين."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"إشارة البيانات تتكون من ثلاثة أشرطة."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"إشارة البيانات كاملة."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"‏تم قطع اتصال Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"‏تم إنشاء اتصال Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 61214e0..a259687 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্ৰিয়। ট\'গল কৰিবলৈ টিপক।"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"এপ্ ষ্টেণ্ডবাই অৱস্থাত আছে:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্ৰান্সক\'ডিঙৰ ছেটিং"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ট্ৰান্সক\'ডিং অক্ষম কৰক"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"এপৰ বাবে ট্ৰান্সক\'ডিং সক্ষম কৰক"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ট্ৰেন্সক’ডিং ডিফ’ল্ট অ’ভাৰৰাইড কৰক"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ট্ৰেন্সক’ডিং সক্ষম কৰক"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"এপে আধুনিক ফৰ্মেট সমৰ্থন কৰে বুলি ধৰি লওক"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ৱেবভিউ প্ৰয়োগ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰী সাময়িকভাৱে সীমিত কৰা হৈছে"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তাঁৰযুক্ত হেডফ\'ন"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"অন"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"অফ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"বাহক নেটৱৰ্কৰ পৰিৱৰ্তন"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"জিপিআৰএছ"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"এলটিই"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"এলটিই+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ফ\'নত ছিগনেল নাই৷"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ফ\'নৰ ছিগনেলৰ তিনিডাল দণ্ড আছে।"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফ\'নৰ ছিগনেল পূৰা আছে৷"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নাই।"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ডেটা ছিগনেলৰ এডাল দণ্ড।"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ডেটা ছংনেলৰ তিনিডাল দণ্ড।"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ডেটা ছিংগনেলত তিনিডাল দণ্ড আছে।"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ডেটা ছিগনেল পূৰা আছে।"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ইথাৰনেট সংযোগ হৈছে।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index db61527..2cbd681 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivdir. Keçid etmək üçün basın."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media yenidən kodlaşdırma ayarları"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Yenidən kodlaşdırmanı deaktiv edin"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Tətbiqlər üçün yenidən kodlaşdırmanı aktiv edin"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Yenidən kodlaşdırma defoltlarını əvəzləyin"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Yenidən kodlaşdırmanı aktiv edin"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Tətbiqlərin müasir formatları dəstəklədiyini qəbul edin"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView icrası"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batareya müvəqqəti məhdudlaşdırılıb"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjiyə qənaət üçün optimallaşdırma"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli qulaqlıq"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktiv"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Deaktiv"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator şəbəkəsinin dəyişilməsi"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil data deaktivdir"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Data istifadə etmək üçün ayarlanmayıb"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon yoxdur."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Şəbəkə bir xətdir."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Şəbəkə iki xətdir."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Şəbəkə üç xətdir."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tam şəbəkə."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Məlumat yoxdur."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data bir xətdir."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data iki xətdir."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data üç xətdir."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data siqnalı tamdır."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kəsilib."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet qoşuludur."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 70fb363..4d8e348 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivna. Dodirnite da biste je deaktivirali."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravnosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Podešavanja transkodiranja medija"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogući transkodiranje"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Zameni podrazumevana podešavanja transkodiranja"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Podrazumevaj da aplikacije podržavaju moderne formate"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Primena WebView-a"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je trenutno ograničena"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizuje se radi stanja baterije"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promena mreže mobilnog operatera"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni podaci su isključeni"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije podešeno za korišćenje podataka"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal telefona ima jednu crtu."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal telefona od dve crte."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal telefona od tri crte."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je pun."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal za podatke ima jednu crtu."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal za podatke od dve crte."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal za podatke od tri crte."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za podatke je najjači."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa eternetom je prekinuta."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Eternet je povezan."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 8a0db82..4d6f3ac 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Актыўная. Краніце, каб пераключыць."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Налады перакадзіравання мультымедыя"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Выключыць перакадзіраванне"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Уключыць перакадзіраванне для праграм"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Перавызначыць стандартныя налады перакадзіравання"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Уключыць перакадзіраванне"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Лічыца, што праграмы падтрымліваюць сучасныя фарматы"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Рэалізацыя WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарад акумулятара часова абмежаваны"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Аптымізацыя стану акумулятара"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Правадныя навушнікі"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Уключана"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выключана"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змяненне аператара сеткі"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мабільная перадача даных выключана"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Не зададзена для выкарыстання даных"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Няма тэлефона."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Адна планка на тэлефоне."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"2 планкі тэлефона."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"3 планкі тэлефона."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Поўны сігнал тэлефона."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Няма дадзеных."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Адна планка дадзеных."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"2 планкі дадзеных."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"3 планкі дадзеных."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Поўны сігнал перадачы дадзеных."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet адлучаны."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet падлучаны."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 27dcf10..ef0412b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Докоснете, за да превключите."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Състояние на готовност на приложението: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки за прекодирането на мултимедия"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Деактивиране на прекодирането"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Активиране на прекодирането за приложения"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Отмяна на стандартните настройки за прекодирането"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Активиране на прекодирането"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Предполагане, че приложенията поддържат съвременни формати"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Внедряване на WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Батерията е временно ограничена"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизиране за състоян. на батерията"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Слушалки с кабел"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Включване"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Изключване"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промяна на мрежата на оператора"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилните данни са изключени"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Не е зададено да използва данни"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Няма телефон."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефонът е с една чертичка."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефонът е с две чертички."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефонът е с три чертички."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналът за телефона е пълен."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Няма данни."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Данните са с една чертичка."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Данните са с две чертички."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Данните са с три чертички."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналът за данни е пълен."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Връзката с Ethernet е прекратена."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Установена е връзка с Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 29862e6..5b95399 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্রান্সকোডিং সেটিংস"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ট্রান্সকোডিং বন্ধ করুন"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"অ্যাপের জন্য ট্রান্সকোডিং চালু করুন"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ট্রান্সকোডিং ডিফল্ট সেটিংস ওভাররাইড করুন"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ট্রান্সকোডিং চালু করুন"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"অ্যাপ মর্ডার্ন ফর্ম্যাটে কাজ করবে বলে ধরে নিন"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ওয়েবভিউ প্রয়োগ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারি কিছুক্ষণের জন্য সীমিত করা হয়েছে"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তার যুক্ত হেডফোন"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"চালু আছে"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"বন্ধ আছে"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তন করা হচ্ছে"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"কোনো ফোনের সংকেত নেই৷"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"তিন দন্ড ফোনের সংকেত রয়েছে৷"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফোনের সংকেত পূর্ণ রয়েছে৷"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নেই৷"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"এক দন্ড ডেটার সংকেত৷"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"দুই দন্ড ডেটার সংকেত রয়েছে৷"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"তিন দন্ড ডেটার সংকেত৷"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"পূর্ণ ডেটার সংকেত রয়েছে৷"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ইথারনেট সংযুক্ত হয়েছে৷"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 4704ec8..00d8087 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Greška u konfiguraciji IP-a"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Niste povezani zbog slabog kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Greška pri povezivanju na WiFi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji."</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Nije se moguće povezati"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Nije se moguće povezati na aplikaciju \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Provjerite lozinku i pokušajte ponovo"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite za promjenu opcije."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje mirovanja aplikacije:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke transkodiranja medija"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućite transkodiranje"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Zaobiđi zadane postavke transkodiranja"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Postavljanje WebViewa"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi očuvanja baterije"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključi"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključi"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Prijenos podataka na mobilnoj mreži je isključen"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za korištenje podataka"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefonskog signala."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal na jednoj crtici."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal na dvije crtice."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal na tri crtice."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Prijenos podataka na jednoj crtici."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Prijenos podataka na dvije crtice."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Prijenos podataka na tri crtice."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za prijenos podataka pun."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa Ethernetom je prekinuta."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet je spojen."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5d04963..300b475 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicació activa. Toca per desactivar-la."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estat de les aplicacions inactives: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configuració de la transcodificació de contingut multimèdia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desactiva la transcodificació"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Activa la transcodificació per a les aplicacions"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Substitueix els valors predeterminats de la transcodificació"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Activa la transcodificació"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assumeix que les aplicacions són compatibles amb formats moderns"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serveis en execució"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualitza i controla els serveis en execució"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementació de WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporalment"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimitzant per a l\'estat de la bateria"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculars amb cable"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activa"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactiva"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"S\'han desactivat les dades mòbils"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"No s\'ha definit per utilitzar dades"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"No hi ha senyal de telèfon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Senyal de telèfon: una barra"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Senyal de telèfon: dues barres."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Senyal de telèfon: tres barres."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Senyal de telèfon: complet."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Senyal de dades: no n\'hi ha"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Senyal de dades: una barra."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Senyal de dades: dues barres."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Senyal de dades: tres barres."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Senyal de dades: complet."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"S\'ha desconnectat l\'Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connectada"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index a99a4da..a9a5f48 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivní. Klepnutím možnost přepnete."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostního režimu aplikace: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavení překódování médií"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Zakázat překódování"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Povolit překódování pro aplikace"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Přepsat výchozí nastavení překódování"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Povolit překódování"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Předpokládat, že aplikace podporují moderní formáty"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Spuštěné služby"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementace WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterie dočasně omezena"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizace pro výdrž baterie"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelová sluchátka"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnout"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnout"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Probíhá změna sítě operátora"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilní data jsou vypnuta"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nenastaveno k využití dat"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Žádná telefonní síť."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jedna čárka signálu telefonní sítě."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvě čárky signálu telefonní sítě."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tři čárky signálu telefonní sítě."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefonní sítě."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Žádné datové připojení."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čárka signálu datové sítě."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dvě čárky signálu datové sítě."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tři čárky signálu datové sítě."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál datové sítě."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Síť ethernet je odpojena."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Síť ethernet je připojena."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c90155e..738ed3c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryk for at skifte."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Standbystatus for appen:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Indstillinger for omkodning af medier"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkodning"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivér omkodning for apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Tilsidesæt standardindstillingerne for omkodning"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivér omkodning"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Gå ud fra, at apps understøtter moderne formater"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Kørende tjenester"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vis og administrer kørende tjenester"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidigt begrænset"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerer batteritilstanden"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Høretelefoner med ledning"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Til"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Fra"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skift af mobilnetværk"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er deaktiveret"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke indstillet til at anvende data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon en bjælke."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon to bjælker."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tre bjælker."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal fuldt."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data en bjælke."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data to bjælker."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tre bjælker."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal fuldt."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er ikke tilsluttet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet er tilsluttet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index b5b9fc4..e274d63 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Zum Wechseln tippen."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Einstellungen für Medientranscodierung"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodierung deaktivieren"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodierung für Apps aktivieren"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Standardeinstellungen für Transcodierung überschreiben"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodierung aktivieren"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Voraussetzen, dass Apps moderne Formate unterstützen"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-Implementierung"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akku vorübergehend eingeschränkt"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimierung des Akkuzustands"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelgebundene Kopfhörer"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"An"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Aus"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilfunknetzwerk wird gewechselt"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile Daten deaktiviert"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nicht für Datennutzung konfiguriert"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Kein Telefon"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonsignal - ein Balken"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonsignal - zwei Balken"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonsignal - drei Balken"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Volle Telefonsignalstärke"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Keine Daten"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datensignal - ein Balken"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datensignal - zwei Balken"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datensignal - drei Balken"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Volle Datensignalstärke"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet nicht verbunden"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet verbunden"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 203ec40..66244eb 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ενεργό. Πατήστε για εναλλαγή."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Κατάσταση αναμονής εφαρμογής:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Ρυθμίσεις διακωδικοποίησης μέσων"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Απενεργοποίηση διακωδικοποίησης"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ενεργοποίηση διακωδικοποίησης για εφαρμογές"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Παράκαμψη προεπιλογών διακωδικοποίησης"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Ενεργοποίηση διακωδικοποίησης"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Να θεωρείται ότι οι εφαρμογές χρησιμοποιούν σύγχρονες μορφές"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Υλοποίηση WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η μπαταρία περιορίστηκε προσωρινά."</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Βελτιστοποίηση κατάστασης μπαταρίας"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ενσύρματα ακουστικά"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ενεργό"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ανενεργό"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Αλλαγή δικτύου εταιρείας κινητής τηλεφωνίας"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Δεν υπάρχει τηλέφωνο."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Μία γραμμή τηλεφώνου."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Δύο γραμμές τηλεφώνου."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Τρεις γραμμές μπαταρίας."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Πλήρες σήμα τηλεφώνου."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Δεν υπάρχουν δεδομένα."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Μία γραμμή δεδομένων."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Δύο γραμμές δεδομένων."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Τρεις γραμμές δεδομένων."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Πλήρες σήμα δεδομένων."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Το Ethernet αποσυνδέθηκε."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Το Ethernet συνδέθηκε."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index f8019d2..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 7135de5..6f11e80 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index f8019d2..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index f8019d2..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 54290d2..bfca1095 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎Active. Tap to toggle.‎‏‎‎‏‎"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎App standby state:‎‏‎‎‏‏‎<xliff:g id="BUCKET"> %s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‎Media transcoding settings‎‏‎‎‏‎"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎Disable transcoding‎‏‎‎‏‎"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎Enable transcoding for apps‎‏‎‎‏‎"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎Override transcoding defaults‎‏‎‎‏‎"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎Enable transcoding‎‏‎‎‏‎"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎Assume apps support modern formats‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎Running services‎‏‎‎‏‎"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎View and control currently running services‎‏‎‎‏‎"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎WebView implementation‎‏‎‎‏‎"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until charged‎‏‎‎‏‎"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until charged‎‏‎‎‏‎"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Battery limited temporarily‎‏‎‎‏‎"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Optimizing for battery health‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎Charging‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Charging rapidly‎‏‎‎‏‎"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎Wired headphone‎‏‎‎‏‎"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎On‎‏‎‎‏‎"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎Off‎‏‎‎‏‎"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎Carrier network changing‎‏‎‎‏‎"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎3G‎‏‎‎‏‎"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎EDGE‎‏‎‎‏‎"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎1X‎‏‎‎‏‎"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‎GPRS‎‏‎‎‏‎"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‎H‎‏‎‎‏‎"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎H+‎‏‎‎‏‎"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎4G‎‏‎‎‏‎"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎4G+‎‏‎‎‏‎"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎LTE‎‏‎‎‏‎"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎LTE+‎‏‎‎‏‎"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎Mobile data off‎‏‎‎‏‎"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎Not set to use data‎‏‎‎‏‎"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎No phone.‎‏‎‎‏‎"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎Phone one bar.‎‏‎‎‏‎"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‎Phone two bars.‎‏‎‎‏‎"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎Phone three bars.‎‏‎‎‏‎"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎Phone signal full.‎‏‎‎‏‎"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎No data.‎‏‎‎‏‎"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎Data one bar.‎‏‎‎‏‎"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎Data two bars.‎‏‎‎‏‎"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎Data three bars.‎‏‎‎‏‎"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎Data signal full.‎‏‎‎‏‎"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎Ethernet disconnected.‎‏‎‎‏‎"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎Ethernet connected.‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 08ff550..44ae8c2 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Presiona para activar o desactivar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la app en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contenido multimedia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Anular los valores predeterminados de transcodificación"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar la transcodificación"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Suponer que las apps admiten formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"En ejecución"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar servicios actuales en ejecución"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batería limitada temporalmente"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: Optimizando el estado de la batería"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápido"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activar"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivar"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de proveedor de red"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos móviles desactivados"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"No se configuró para usar datos"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de teléfono"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de teléfono"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de teléfono"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Señal de teléfono completa"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"No hay datos."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dos barras de datos"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de datos"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos completa"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 6f6a1a1..236394c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Toca para alternar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de la transcodificación multimedia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en las aplicaciones"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar transcodificación"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Considerar que las aplicaciones admiten formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicios en ejecución"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar los servicios en ejecución"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta cargarse completamente"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta cargarse completamente)"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: batería limitada temporalmente"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: preservando estado de la batería"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activado"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivado"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambiando la red del operador"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos desactiv."</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"No está establecido para usar los datos"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de cobertura"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de cobertura"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura al máximo"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Sin datos"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dos barras de datos"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de datos"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos al máximo"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Conexión Ethernet desconectada."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Conexión Ethernet conectada."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9d6326e..c8fd94f 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivne. Puudutage vahetamiseks."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Rakenduse ootelolek:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Meedia transkodeerimise seaded"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Keela transkodeerimine"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Luba rakenduste puhul transkodeerimine"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Alista transkodeerimise vaikeseaded"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Luba transkodeerimine"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Oleta, et rakendused toetavad kaasaegseid vorminguid"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Käitatud teenused"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView\' rakendamine"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akutase on ajutiselt piiratud"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimeerimine aku seisukorra põhjal"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Juhtmega kõrvaklapid"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Sees"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Väljas"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaatori võrku muudetakse"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilne andmeside on väljas"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ei ole andmeside kasutamiseks seadistatud"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefonisignaal puudub"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonisignaal: üks pulk."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonisignaal: kaks pulka."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonisignaal: kolm pulka."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonisignaal on tugev."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Andmed puuduvad."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Andmesignaal: üks pulk."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Andmeside: kaks pulka."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Andmeside: kolm pulka."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Andmesignaal on tugev."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Etherneti-ühendus on katkestatud."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Etherneti-ühendus on loodud."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 01afa17..226ffba 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Multimedia-edukia transkodetzeko ezarpenak"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desgaitu transkodetzeko aukera"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Gaitu aplikazioak transkodetzeko aukera"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ez erabili transkodetzearen balio lehenetsiak"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Gaitu transkodetzea"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Arduratu aplikazioek formatu modernoak onartzeaz"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria mugatuta egongo da aldi batez"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimizatzen bateria egoera onean mantentzeko"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Entzungailu kableduna"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktibatu"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desaktibatu"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operadorearen sarea aldatzen"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Desaktibatuta dago datu-konexioa"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ez dago ezarrita datuak erabiltzeko"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ez dago telefono-zenbakirik."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono-seinaleak barra bat du."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono-seinaleak bi barra ditu."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono-seinaleak hiru barra ditu."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono-seinale osoa."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ez dago daturik."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datu-seinaleak barra bat du."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datu-seinaleak bi barra ditu."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datu-seinaleak hiru barra ditu."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datu-seinale osoa."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bidezko konexioa eten da."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet bidez konektatu da."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index dd7ab96..917a637 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -34,7 +34,7 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"گذرواژه را بررسی و دوباره امتحان کنید"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"در محدوده نیست"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"اتصال به‌صورت خودکار انجام نمی‌شود"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"بدون دسترسی به اینترنت"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"دسترسی به اینترنت ندارد"</string>
     <string name="saved_network" msgid="7143698034077223645">"ذخیره‌شده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"‏اتصال خودکار ازطریق %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"اتصال خودکار ازطریق ارائه‌دهنده رتبه‌بندی شبکه"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال. برای تغییر حالت ضربه بزنید."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"وضعیت حالت آماده به‌کار برنامه:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"تنظیمات تراتبدیل رسانه"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"غیرفعال کردن تراتبدیل"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"فعال کردن تراتبدیل برای برنامه‌ها"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ملغی کردن پیش‌فرض‌های تراتبدیل"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"فعال کردن تراتبدیل"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"فرض شود برنامه‌ها از قالب‌های مدرن پشتیبانی می‌کنند"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"سرویس‌های در حال اجرا"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویس‌های در حال اجرای فعلی"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"اجرای وب‌نما"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - باتری موقتاً محدود شده است"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بهینه‌سازی برای سلامت باتری"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"هدفون سیمی"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"روشن"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"خاموش"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"تغییر شبکه شرکت مخابراتی"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+‎"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+‎"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+‎"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"داده تلفن همراه خاموش است"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"برای استفاده از داده تنظیم نشده است"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"بدون تلفن."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"یک نوار برای تلفن."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"دو نوار برای تلفن."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"سه نوار برای تلفن."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"قدرت امواج تلفن همراه کامل است."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"داده‌ای وجود ندارد."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"یک نوار برای داده."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"دو نوار برای داده."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"سه نوار برای داده."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"قدرت سیگنال داده کامل است."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"اترنت قطع شد."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"اترنت متصل شد."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index b86b02d..6081b2a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivinen. Vaihda koskettamalla."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Median transkoodausasetukset"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Poista transkoodaus käytöstä"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ota sovellusten transkoodaus käyttöön"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ohita transkoodauksen oletukset"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Salli transkoodaus"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Oleta, että sovellukset tukevat nykyaikaisia formaatteja"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tarkastele ja hallitse käynnissä olevia palveluita."</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-käyttöönotto"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun käyttöä rajoitettu tilapäisesti"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun kunnon optimointi"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Langalliset kuulokkeet"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Päällä"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Poissa päältä"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaattorin verkko muuttuu"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilidata poistettu käytöstä"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ei käytä dataa"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ei puhelinverkkoyhteyttä."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Puhelinverkkosignaali - yksi palkki."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Puhelinverkkosignaali - kaksi palkkia."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Puhelinverkkosignaali - kolme palkkia."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Vahva puhelinverkkosignaali."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ei datasignaalia."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datasignaali - yksi palkki."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datasignaali - kaksi palkkia."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datasignaali - kolme palkkia"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Vahva kuuluvuus."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet on irrotettu."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet on yhdistetty."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 0bca1db..91d14d4 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Touchez ici pour la désactiver."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"État de l\'application en veille :<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des éléments multimédias"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Remplacer les valeurs par défaut de transcodage"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Présumer que les applications prennent en charge les formats modernes"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pile limitée temporairement"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimisation pour la santé de la pile"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
@@ -492,7 +493,6 @@
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Les adresses MAC sont randomisées"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="one">%1$d appareil connecté</item>
-      <item quantity="many">%1$d devices connected</item>
       <item quantity="other">%1$d appareils connectés</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
@@ -565,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Écouteurs filaires"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activé"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Désactivé"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Changer de réseau de fournisseur de services"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour l\'utilisation des données cellulaires"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal moyen"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal bon"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connecté."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ebde43b..2518fe1 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Échec de configuration de l\'adresse IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Non connecté en raison de la faible qualité du réseau"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Échec de la connexion Wi-Fi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification."</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Connexion impossible"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Impossible de se connecter au réseau \"<xliff:g id="AP_NAME">%1$s</xliff:g>\""</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Vérifiez le mot de passe et réessayez"</string>
@@ -251,7 +251,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"Certification affichage sans fil"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"Autoriser l\'enregistrement d\'infos Wi-Fi détaillées"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Limiter la recherche Wi‑Fi"</string>
-    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Chgt aléatoire d\'adresse MAC en Wi-Fi"</string>
+    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Changement aléatoire d\'adresse MAC en Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"Données mobiles toujours actives"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Appuyez ici pour la désactiver."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"État de mise en veille de l\'application : <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des contenus multimédias"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ignorer les paramètres de transcodage par défaut"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Supposer que les applications sont compatibles avec les formats modernes"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterie limitée temporairement"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimisation pour préserver batterie"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
@@ -492,7 +493,6 @@
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"La sélection des adresses MAC est aléatoire"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="one">%1$d appareil connecté</item>
-      <item quantity="many">%1$d devices connected</item>
       <item quantity="other">%1$d appareils connectés</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
@@ -565,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Casque filaire"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Allumé"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Éteint"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Modification du réseau de l\'opérateur"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour utiliser les données"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal moyen"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal bon"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connecté"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index b040817..486afe3 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicación activa. Toca para alternar a configuración."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado en espera da aplicación: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contido multimedia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desactivar transcodificación"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Activar transcodificación para as aplicacións"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Activar transcodificación"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Considerar que as aplicacións admiten formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizos en uso"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Comproba e controla os servizos actualmente en uso"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> (batería limitada temporalmente)"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimizando para manter a batería en bo estado"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activar"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivar"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de rede do operador"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Os datos móbiles están desactivados"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Non se configurou para utilizar datos"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sen teléfono"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Unha barra de cobertura"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dúas barras de cobertura"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura ao máximo"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Sen datos"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Unha barra de sinal de datos"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Sinal de datos: dúas barras"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de sinal de datos"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de datos: completo"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Desconectouse a Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Conectouse a Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index c1bd7ca..2bebe36 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ફૉર્મેટ બદલવાની પ્રક્રિયા બંધ કરો"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ફૉર્મેટ બદલવાની પ્રક્રિયાના ડિફૉલ્ટ સેટિંગ ઓવરરાઇડ કરો"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ધારો કે ઍપ આધુનિક ફૉર્મેટ પર કામ કરે છે"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - બૅટરીનો વપરાશ હંગામી રૂપે મર્યાદિત છે"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"વાયરવાળો હૅડફોન"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ચાલુ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"બંધ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"કૅરીઅર નેટવર્કમાં ફેરફાર થઈ રહ્યો છે"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"મોબાઇલ ડેટા બંધ છે"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"કોઈ ફોન નથી."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ફોન એક બાર."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ફોન બે બાર."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ફોન ત્રણ બાર."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"પૂર્ણ ફોન સિગ્નલ."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"કોઈ ડેટા નથી."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ડેટા એક બાર."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ડેટા બે બાર."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ડેટા ત્રણ બાર."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ડેટા સિગ્નલ પૂર્ણ."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ઇથરનેટ કનેક્ટ થયું."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index d9153a1..824ab25 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"वाईफ़ाई कनेक्‍शन विफलता"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"पुष्टि नहीं हो सकी"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"कनेक्ट नहीं हो पा रहा है"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' से कनेक्ट नहीं हो पा रहा है"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"पासवर्ड जाँचें और दोबारा कोशिश करें"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करने के लिए टैप करें."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ऐप्लिकेशन स्टैंडबाय की स्थिति:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रांसकोडिंग सेटिंग"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रांसकोडिंग को बंद करें"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ऐप्लिकेशन के लिए ट्रांसकोडिंग चालू करें"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ट्रांसकोडिंग की डिफ़ॉल्ट सेटिंग बदलें"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रांसकोडिंग चालू करें"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"मानकर चलें कि ऐप्लिकेशन, नए फ़ॉर्मैट के साथ काम करेंगे"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबव्यू लागू करें"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - कुछ समय के लिए, बैटरी का सीमित इस्तेमाल होगा"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर वाला हेडफ़ोन"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"चालू है"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद है"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का नेटवर्क बदल रहा है"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3जी"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"एलटीई"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद है"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"कोई फ़ोन नहीं."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फ़ोन एक बार."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फ़ोन दो बार."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फ़ोन सि‍ग्‍नल पूरा."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"कोई डेटा नहीं."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दो बार."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तीन बार."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सि‍ग्‍नल पूरा."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ईथरनेट डिस्‍कनेक्‍ट किया गया."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ईथरनेट कनेक्‍ट किया गया."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index b51e096..cd21a5f 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite da biste to promijenili."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke konvertiranja medija"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućivanje konvertiranja"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućivanje konvertiranja za aplikacije"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Nadjačaj zadane postavke konvertiranja"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Omogući konvertiranje"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pregledajte i kontrolirajte pokrenute usluge"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacija WebViewa"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi zdravlja baterije"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G i više"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni su podaci isključeni"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za upotrebu podataka"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal jedan stupac."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal dva stupca."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal tri stupca."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal jedan stupac."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Podatkovni signal dva stupca."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Podatkovni signal tri stupca."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal pun."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Prekinuta je veza s ethernetom."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Uspostavljena je veza s ethernetom."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 33770fc..c3b859c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Bekapcsolva. Koppintson ide a váltáshoz."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Alkalmazás készenléti állapota:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Médiaátkódolási beállítások"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Átkódolás letiltása"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Átkódolás engedélyezése az alkalmazásoknál"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Az átkódolás alapértelmezett beállításainak felülbírálása"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Átkódolás engedélyezése"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Annak feltételezése, hogy az alkalmazások támogatják a modern formátumokat"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Futó szolgáltatások"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-megvalósítás"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésből"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor ideiglenesen korlátozva"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor-élettartam optimalizálása"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vezetékes fejhallgató"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Be"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ki"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Szolgáltatói hálózat váltása"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiladatok kikapcsolva"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nincs beállítva az adathasználat"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nincs telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon egy sáv."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon két sáv."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon három sáv."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonjel megtelt."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nincsenek adatok."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Adat egy sáv."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Adat két sáv."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Adat három sáv."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Adatjel teljes."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet leválasztva."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet csatlakoztatva."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 06d70f8..041ad0e 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Հավելվածի սպասման կարգավիճակ՝ <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Մեդիա ֆայլերի վերակոդավորման կարգավորումներ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Անջատել վերակոդավորումը"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Միացնել վերակոդավորումը հավելվածների համար"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Չեղարկել վերակոդավորման կանխադրված կարգավորումները"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Միացնել վերակոդավորումը"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Ենթադրել, որ հավելվածներն աջակցում են ժամանակակից ձևաչափեր"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Մարտկոցը ժամանակավորապես սահմանափակված է"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Օպտիմալացվում է"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Լարով ականջակալ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Միացնել"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Անջատել"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Օպերատորի ցանցի փոփոխություն"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Բջջային ինտերնետն անջատված է"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Հեռախոս չկա:"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Հեռախոսի մեկ գիծ:"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Հեռախոսի երկու գիծ:"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Հեռախոսի երեք գիծ:"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Հեռախոսի ազդանշանը լիքն է:"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Տվյալներ չկան:"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Տվյալների մեկ գիծ:"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Տվյալների երկու գիծ:"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Տվյալների երեք գիծ:"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Տվյալների ազդանշանը լրիվ է:"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet-ը անջատված է:"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet-ը կապակցված է:"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 4123d9e..69d4582 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketuk untuk beralih."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Status standby aplikasi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Setelan transcoding media"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Menonaktifkan transcoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Mengaktifkan transcoding untuk aplikasi"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ganti default transcoding"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Aktifkan transcoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Asumsikan aplikasi mendukung format modern"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Layanan yang sedang berjalan"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Penerapan WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Daya baterai terbatas untuk sementara"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengoptimalkan untuk kesehatan baterai"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Headphone berkabel"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktif"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Nonaktif"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Jaringan operator berubah"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Kuota nonaktif"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak disetel untuk menggunakan data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Tidak dapat melakukan panggilan."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ponsel satu batang."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Ponsel dua batang."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Ponsel tiga batang."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinyal ponsel penuh."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Tidak ada data yang diterima."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu batang."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data dua batang."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tiga batang."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinyal data penuh."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet terputus."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet tersambung."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 3b9bef8..f401364 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Virkt. Ýttu til að breyta."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Biðstaða forrits: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Stillingar efnisumkóðunar"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Slökkva á umkóðun"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Kveikja á umkóðun í forritum"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Hnekkja sjálfgefinni umkóðun"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Kveikja á umkóðun"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Gera ráð fyrir að forrit styðji nútímasnið"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Þjónustur í gangi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Skoða og stjórna þjónustum í gangi"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Innleiðing WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Rafhlaða takmörkuð tímabundið"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fínstillir fyrir rafhlöðuendingu"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Heyrnartól með snúru"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Kveikt"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Slökkt"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skiptir um farsímakerfi"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Slökkt á farsímagögnum"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ekki stillt á að nota gögn"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ekkert símasamband."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Styrkur símasambands er eitt strik."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Styrkur símasambands er tvö strik."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Styrkur símasambands er þrjú strik."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Fullur styrkur símasambands."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Engin gögn."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sendistyrkur gagnatengingar er eitt strik."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Sendistyrkur gagnatengingar tvö strik."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Sendistyrkur gagnatengingar er þrjú strik."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Fullur sendistyrkur gagnatengingar."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet aftengt."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet tengt."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 1ab6b24..ef5e2ff 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Attiva. Tocca per attivare/disattivare."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stato di standby dell\'app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Impostazioni transcodifica contenuti multimediali"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Disattiva transcodifica"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Attiva transcodifica per le app"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Sostituisci impostazioni predefinite transcodifica"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Attiva transcodifica"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Presupponi che le app supportino i formati moderni"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servizi in esecuzione"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementazione di WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria momentaneamente limitata"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ottimizzazione per integrità batteria"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Cuffie con cavo"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio della rete dell\'operatore"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dati mobili disattivati"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Non impostato per l\'utilizzo dei dati"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nessun telefono."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono: una barra."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono: due barre."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono: tre barre."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Massimo segnale telefonico."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nessun dato."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: una barra."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dati: due barre."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dati: tre barre."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Massimo segnale dati."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Connessione Ethernet annullata."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Connessione Ethernet stabilita."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 15868d5..4cc6775 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"אפליקציה פעילה. הקש כדי להחליף מצב."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"אפליקציה במצב המתנה:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"הגדרות של המרת קידוד למדיה"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"השבתה של המרת קידוד"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"הפעלה של המרת קידוד לאפליקציות"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ביטול ברירות המחדל של המרת קידוד"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"הפעלת המרת קידוד"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"הנחת העבודה היא שאפליקציות תומכות בפורמטים מודרניים"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏יישום WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - הסוללה מוגבלת באופן זמני"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> ﹣ מופעל מיטוב לשמירה על תקינות הסוללה"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"אוזניות חוטיות"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"פועלת"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"כבויה"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"רשת ספק משתנה"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"+H"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"+4G"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"+LTE"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"חבילת הגלישה כבויה"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"לא מוגדרת לשימוש בנתונים"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"אין טלפון."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"פס אחד של טלפון."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"שני פסים של טלפון."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"שלושה פסים של טלפון."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"אות הטלפון מלא."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"אין נתונים."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"פס אחד של נתונים."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"שני פסים של נתונים."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"שלושה פסים של נתונים."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"אות הנתונים מלא."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"אתרנט מנותק."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"אתרנט מחובר."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 89ee98e..9e9db3d 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"有効です。タップすると切り替わります。"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"アプリ スタンバイ状態: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"メディアのコード変換設定"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"コード変換を無効にする"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"アプリに対しコード変換を有効にする"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"デフォルトのコード変換をオーバーライド"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"コード変換を有効にする"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"アプリによる最新形式のサポートを想定"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView の実装"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の使用が一時的に制限されています"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の状態を最適化"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線ヘッドフォン"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ON"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"OFF"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"携帯通信会社のネットワークを変更します"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"モバイルデータ OFF"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"データを使用するように設定されていません"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"電波状態:なし"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電波状態:レベル1"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電波状態:レベル2"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電波状態:レベル3"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電波状態:フル"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"データ信号:なし"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"データ信号:レベル1"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"データ信号:レベル2"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"データ信号:レベル3"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"データ信号:フル"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"イーサネット接続を解除しました。"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"イーサネットに接続しました。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d188578..ec39008 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"აქტიური. შეეხეთ გადასართავად."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"აპის მოლოდინის რეჟიმის მდგომარეობა:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"მედიის ტრანსკოდირების პარამეტრები"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ტრანსკოდირების გათიშვა"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ტრანსკოდირების ჩართვა აპებისთვის"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ტრანსკოდირების ნაგულისხმევების უგულებელყოფა"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ტრანსკოდირების ჩართვა"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"დაშვება, რომ აპებს აქვთ თანამედროვე ფორმატების მხარდაჭერა"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView რეალიზაცია"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> — ბატარეა დროებით შეზღუდულია"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> — ოპტიმიზაცია ბატარეის გამართულობისთვის"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"სადენიანი ყურსასმენი"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ჩართვა"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"გამორთვა"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"ოპერატორის ქსელის შეცვლა"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"მობილური ინტერნეტი გამორთულია"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ტელეფონი არ არის."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ტელეფონის სიგნალი სრულია."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"მონაცემები არ არის."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"თარიღი ზოლზე."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"მონაცემების გადაცემა: ორი ზოლი"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"მონაცემების გადაცემა: სამი ზოლი"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet კავშირი შეწყვეტილია."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet დაკავშირებულია."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 2bc1c4d..881a13c 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Медиамазмұнды қайта кодтау параметрлері"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Қайта кодтауды өшіру"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Қолданбалар үшін қайта кодтауға рұқсат ету"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Қайта қодтаудың әдепкі параметрлерін қайта анықтау"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Қайта кодтауды қосу"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Қолданбалар қазіргі заманғы форматтарды қолдайды делік"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView қызметі"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарея жұмысы уақытша шектелген"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Сымды құлақаспап"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Қосу"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өшіру"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор желісін өзгерту"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильдік деректер өшірулі"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Деректерді пайдалануға реттелмеген."</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон жоқ."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон бір баған."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон екі баған."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон үш баған."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толық."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Дерекқор жоқ."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дерекқор бір баған."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дерекқор екі баған."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Дерекқор үш баған."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дерекқор сигналы толы."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажыратылған."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet қосылған."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 7306cf8..14f7788 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ស្ថាន​ភាព​មុខងារ​ផ្អាក​ដំណើរការ​កម្មវិធី៖<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"ការកំណត់​ការបំប្លែង​កូដមេឌៀ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"បិទ​ការបំប្លែងកូដ"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"បើក​ការបំប្លែងកូដ​សម្រាប់​កម្មវិធី"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"លុបពីលើលំនាំដើម​នៃការបំប្លែងកូដ"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"បើក​ការបំប្លែងកូដ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"សន្មតថាកម្មវិធី​អាចប្រើ​ទម្រង់ទំនើបបាន"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្ម​កំពុង​ដំណើរការ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និង​គ្រប់គ្រង​សេវាកម្ម​កំពុង​ដំណើរការ​បច្ចុប្បន្ន"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ការអនុវត្ត WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​សាកថ្មពេញ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានដាក់កម្រិតថ្ម​ជាបណ្ដោះអាសន្ន"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងបង្កើនប្រសិទ្ធភាព​គុណភាពថ្ម"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"កាស​មានខ្សែ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"បើក"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"បិទ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"បណ្តាញ​ក្រុមហ៊ុនសេវាទូរសព្ទ​កំពុងផ្លាស់ប្តូរ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ទិន្នន័យ​ទូរសព្ទចល័ត​បានបិទ"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"មិនបានកំណត់​ឱ្យប្រើ​ទិន្នន័យ​ទេ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"គ្មាន​ទូរស័ព្ទ។"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"សេវា​ទូរស័ព្ទ​មួយ​កាំ។"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"សេវា​ទូរស័ព្ទ​ពីរ​កាំ។"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"សេវា​ទូរស័ព្ទ​បី​កាំ​។"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"សេវា​ទូរស័ព្ទ​ពេញ។"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"គ្មាន​ទិន្នន័យ​។"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ទិន្នន័យ​មួយ​​កាំ។"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ទិន្នន័យ​ពីរ​​កាំ។"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ទិន្នន័យ​បី​កាំ។"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"សញ្ញា​ទិន្នន័យ​ពេញ។"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"បានភ្ជាប់អ៊ីសឺរណិត។"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 0c1502c..a279d22 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್‌ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ಆ್ಯಪ್‌ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಅತಿಕ್ರಮಿಸಿ"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ಆ್ಯಪ್‌ಗಳು ಆಧುನಿಕ ಫಾರ್ಮ್ಯಾಟ್‌ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ ಎಂದು ಊಹಿಸಿ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತವಾಗಿದೆ"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್‌ಫೋನ್"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ಆನ್ ಆಗಿದೆ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ಆಫ್ ಆಗಿದೆ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"ವಾಹಕ ನೆಟ್‌ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ಫೋನ್ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ಫೋನ್ ಸಂಕೇತ ಪೂರ್ತಿ ಇದೆ."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ಯಾವುದೇ ಡೇಟಾ ಇಲ್ಲ."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ಡೇಟಾ ಒಂದು ಪಟ್ಟಿ."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ಡೇಟಾ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ಡೇಟಾ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ಡೇಟಾ ಸಂಕೇತ ತುಂಬಿದೆ."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕಗೊಳಿಸಲಾಗಿದೆ."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 1322344..de69488 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"활성화되었습니다. 전환하려면 탭하세요."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"앱 대기 상태:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"미디어 트랜스코딩 설정"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"트랜스코딩 사용 중지"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"앱 트랜스코딩 사용 설정"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"트랜스코딩 기본값 재정의"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"트랜스코딩 사용"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"앱이 최신 형식을 지원하는 것으로 가정"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 구현"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 일시적으로 배터리 사용 제한"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 배터리 상태 최적화 중"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"유선 헤드폰"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"사용"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"사용 안 함"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"이동통신사 네트워크 변경"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G 이상"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"모바일 데이터 꺼짐"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"데이터를 사용하도록 설정되지 않음"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"휴대전화의 신호가 없습니다."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"휴대전화 신호 막대가 하나입니다."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"휴대전화 신호 막대가 두 개입니다."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"휴대전화 신호 막대가 세 개입니다."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"휴대전화의 신호가 강합니다."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"데이터가 없습니다."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"데이터 신호 막대가 하나입니다."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"데이터 신호 막대가 두 개입니다."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"데이터 신호 막대가 세 개입니다."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"데이터 신호가 강합니다."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"이더넷에서 연결 해제되었습니다."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"이더넷에 연결되었습니다."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 9697aa7..e70460f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа файлдарды транскоддоо жөндөөлөрү"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Транскоддоону өчүрүү"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Колдонмолорду транскоддоону күйгүзүү"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Демейки жүргүзүлгөн транскоддоону өзгөртүп коюу"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Транскоддоо жүргүзүүнү иштетүү"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Колдонмолордо заманбап форматтар колдоого алынат"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяны колдонуу убактлуу чектелген"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареянын кубатын үнөмдөө иштетилди"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Зымдуу гарнитура"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Күйгүзүү"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өчүрүү"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Байланыш оператору өзгөртүлүүдө"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилдик Интернет өчүрүлгөн"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон сигналы жок."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон сигналы бир таякча."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон сигналы эки таякча."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон сигналы үч таякча."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толук."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал жок."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Мобилдик интернеттин сигналы бир таякча."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Мобилдик интернеттин сигналы эки таякча."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Мобилдик интернеттин сигналы үч таякча."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Мобилдик интернеттин сигналы толук."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажырады."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet туташты."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 7201222..c63cec8 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ສະຖານະສະແຕນບາຍແອັບ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"ການຕັ້ງຄ່າການປ່ຽນຮູບແບບລະຫັດມີເດຍ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດສຳລັບແອັບ"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ຍົກເລີກຄ່າເລີ່ມຕົ້ນການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ເປີດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ສົມມຸດວ່າແອັບຮອງຮັບຮູບແບບສະໄໝໃໝ່"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈຳກັດແບັດເຕີຣີຊົ່ວຄາວ"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ຫູຟັງແບບມີສາຍ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ເປີດ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ປິດ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"ການປ່ຽນເຄືອຂ່າຍຜູ້ໃຫ້ບໍລິການ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ບໍ່ມີໂທລະສັບ."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ສັນຍານນຶ່ງຂີດ."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ສັນຍານສອງຂີດ."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ສັນຍານສາມຂີດ."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ສັນຍານເຕັມ."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ບໍ່ມີຂໍ້ມູນ."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ຂໍ້ມູນສອງຂີດ."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ຂໍ້ມູນສາມຂີດ."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ສັນ​ຍານຂໍ້ມູນ​ເຕັມ."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ອີ​ເທີ​ເນັດ​ຕັດ​ເຊື່ອມ​ຕໍ່​ແລ້ວ."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ອີ​ເທີ​ເນັດ​ເຊື່ອມ​ຕໍ່​ແລ້ວ."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index e62eeb2..d040edf 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktyvi. Palieskite, kad perjungtumėte."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Programų budėjimo režimo būsena: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Medijos perkodavimo nustatymai"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Išjungti perkodavimą"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Įjungti programų perkodavimą"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Perkodavimo numatytųjų nustatymų nepaisymas"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Perkodavimo įgalinimas"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Manoma, kad programos palaiko modernius formatus"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Vykdomos paslaugos"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"„WebView“ diegimas"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akumuliatorius laikinai apribotas"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimizuoj. siekiant apsaugoti akum."</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Laidinės ausinės"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Įjungta"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Išjungta"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Keičiamas operatoriaus tinklas"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiliojo ryšio duomenys išjungti"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nenustatyta naudoti duomenis"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nėra telefono."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Viena telefono juosta."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvi telefono juostos."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Trys telefono juostos."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono signalas stiprus."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Duomenų nėra."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Viena duomenų juosta."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dvi duomenų juostos."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Trys duomenų juostos."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Stiprus duomenų signalas."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Atsijungta nuo eterneto."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Prijungta prie eterneto."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 2f30561..74c0dd5 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktīva. Pieskarieties, lai pārslēgtu."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Lietotnes gaidstāves stāvoklis: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Multivides failu pārkodēšanas iestatījumi"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Atspējot pārkodēšanu"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Iespējot pārkodēšanu noteiktām lietotnēm"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ignorēt pārkodēšanas noklusējuma iestatījumus"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Iespējot pārkodēšanu"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Pieņemt, ka lietotnēs tiek atbalstīti moderni formāti"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktīvie pakalpojumi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ieviešana"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>, akumulatora uzlāde pagaidām ierobežota"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: akumulatora darbības optimizēšana"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vadu austiņas"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ieslēgts"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izslēgts"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilo sakaru operatora tīkla mainīšana"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilie dati izslēgti"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nav iestatīts datu lietošanai"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nav tālruņa."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tālrunis: viena josla."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tālrunis: divas joslas."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tālrunis: trīs joslas."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Pilna piekļuve tālruņa signālam"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nav datu."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: viena josla"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dati: divas joslas."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dati: trīs joslas."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Pilna piekļuve datu signālam."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Pārtraukts savienojums ar tīklu Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Izveidots savienojums ar tīklu Ethernet."</string>
 </resources>
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-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 1936fe2..739bceb 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Допрете за да смените."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Состојба на мирување на апликацијата: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Поставки за транскодирање аудиовизуелни содржини"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Оневозможи транскодирање"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Овозможете транскодирање за апликациите"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Отфрли стандардни вредности за транскодирање"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Овозможи транскодирање"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Претпостави дека апликациите поддржуваат модерни формати"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Воведување WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батеријата е привремено ограничена"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Се оптимизира за состојба на батерија"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичени слушалки"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вклучено"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Исклучено"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Променување на мрежата на операторот"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилниот интернет е исклучен"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Не е поставен да користи интернет"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Нема сигнал."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон една цртичка.."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон две цртички."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон три цртички."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналот за телефон е исполнет."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Нема податоци."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Податоци една цртичка."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигналот за податоци е на две цртички."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Податоци три цртички."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналот за податоци е исполнет."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Етернетот е исклучен."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Етернетот е поврзан."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index de4a49a..122b481 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്‌റ്റാൻഡ്‌ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"മീഡിയ ട്രാൻസ്കോഡ് ചെയ്യൽ ക്രമീകരണം"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കുക"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ആപ്പുകൾക്കായി ട്രാൻസ്കോഡ് ചെയ്യുന്നത് പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ട്രാൻസ്കോഡ് ചെയ്യൽ ഡിഫോൾട്ടുകൾ അസാധുവാക്കുക"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ആപ്പുകൾ ആധുനിക ഫോർമാറ്റുകളെ പിന്തുണയ്ക്കുമെന്ന് കരുതുക"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView നടപ്പാക്കൽ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി താൽക്കാലം പരിമിതപ്പെടുത്തി"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"വയേർഡ് ഹെഡ്ഫോൺ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ഓണാണ്"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ഓഫാണ്"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"കാരിയർ നെറ്റ്‌വർക്ക് മാറ്റൽ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDG"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ഫോൺ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ഫോണിൽ ഒരു ബാർ."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ഫോണിൽ രണ്ട് ബാർ."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ഫോണിൽ മൂന്ന് ബാർ."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ഫോൺ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ഡാറ്റാ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ഡാറ്റ ഒരു ബാർ."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ഡാറ്റ രണ്ട് ബാറുകൾ."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ഡാറ്റ മൂന്ന് ബാർ."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ഡാറ്റ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ഇതർനെറ്റ് കണക്റ്റുചെയ്‌തു."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index dee8add..c7a2edd 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP тохируулга амжилтгүй"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Сүлжээний чанар муу байгаа тул холбогдож чадсангүй"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi холболт амжилтгүй"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Гэрчлэлийн асуудал"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Баталгаажуулалтын асуудал"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Холбогдож чадсангүй"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'-д холбогдож чадсангүй"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Нууц үгийг шалгаад дахин оролдоно уу"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Идэвхтэй байна. Унтраах/асаахын тулд дарна уу."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Апп зогсолтын горимын төлөв:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа хөрвүүлгийн тохиргоо"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Хөрвүүлгийг идэвхгүй болгох"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Аппуудад хөрвүүлгийг идэвхжүүлэх"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Хөрвүүлгийн өгөгдмөлийг дарах"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Хөрвүүлгийг идэвхжүүлэх"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Аппыг орчин үеийн форматыг дэмждэг гэж үздэг"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView хэрэгжилт"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг түр хугацаанд хязгаарласан"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейн чанарыг оновчилж байна"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
@@ -534,7 +535,7 @@
     <string name="user_add_user_item_title" msgid="2394272381086965029">"Хэрэглэгч"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Хязгаарлагдсан профайл"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Шинэ хэрэглэгч нэмэх үү?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, ханын цаас болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, дэлгэцийн зураг болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Хэрэглэгчийг одоо тохируулах уу?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"Хэрэглэгч төхөөрөмжийг авч өөрийн профайлыг тохируулах боломжтой эсэхийг шалгана уу"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Утастай чихэвч"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Асаах"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Унтраах"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор компанийн сүлжээг өөрчилж байна"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобайл дата унтраалттай байна"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Дата ашиглахаар тохируулаагүй"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Утас байхгүй."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Утас нэг баганатай."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Утас хоёр баганатай."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Утас гурван баганатай."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Утасны дохио дүүрэн."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Дата байхгүй."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дата нэг баганатай."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дата хоёр баганатай."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Дата гурван баганатай."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дата дохио дүүрэн."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet саллаа."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet холбогдсон."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 60ad68e..d29cb59 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"अ‍ॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रान्सकोडिंगची सेटिंग्ज"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिंग बंद करा"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ॲप्ससाठी ट्रान्सकोडिंग सुरू करा"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिंग डीफॉल्ट ओव्हरराइड करा"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिंग सुरू करा"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"असे गृहीत धरा की, ॲप्स आधुनिक फॉरमॅटना सपोर्ट करतात"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरी तात्पुरती मर्यादित आहे"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर असलेला हेडफोन"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"सुरू करा"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद करा"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"वाहक नेटवर्क बदलत आहे"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"३G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"१X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"४G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"४G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद आहे"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा वापरण्यासाठी सेट केलेले नाही"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"कोणताही फोन नाही."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एक बार."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दोन बार."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सिग्नल पूर्ण."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"कोणताही डेटा नाही."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दोन बार."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तीन बार."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सिग्नल पूर्ण."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट डिस्कनेक्ट केले."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"इथरनेट कनेक्ट केले."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index e4d5912..c593e4b 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketik untuk menogol."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Keadaan tunggu sedia apl:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Tetapan transpengekodan media"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Lumpuhkan transpengekodan"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Dayakan transpengekodan untuk apl"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Batalkan transpengekodan lalai"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Dayakan transpengekodan"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Mengambil alih sokongan apl format moden"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Perkhidmatan dijalankan"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Pelaksanaan WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateri terhad untuk sementara"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengoptimuman untuk kesihatan bateri"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fon kepala berwayar"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Hidup"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Mati"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rangkaian pembawa berubah"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Data mudah alih dimatikan"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak ditetapkan untuk menggunakan data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Tiada telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon satu bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon dua bar."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tiga bar."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isyarat telefon penuh."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Tiada data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data dua bar."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tiga bar."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Isyarat data penuh."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet diputuskan sambungan."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet disambungkan."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 09a8bf8..aa9d3d6 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"အထောက်အထားစိစစ်မှု ပြဿနာ"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"ချိတ်ဆက်၍ မရပါ"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' နှင့် ချိတ်ဆက်၍ မရပါ"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"စကားဝှက်ကို စစ်ဆေးပြီး ထပ်လုပ်ကြည့်ပါ"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"အက်ပ်ကို အရန်သင့်ထားရှိခြင်း အခြေအနေ-<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"မီဒီယာအမျိုးအစားပြောင်းခြင်း ဆက်တင်များ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"အမျိုးအစားပြောင်းခြင်းကို ပိတ်ရန်"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"အက်ပ်များအတွက် အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"အမျိုးအစားပြောင်းခြင်း၏ မူရင်းဆက်တင်များကို အစားထိုးရန်"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ဤအက်ပ်များက ဖော်မက်အသစ်များကို ပံ့ပိုးသည်"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView အကောင်အထည်ဖော်မှု"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီ ယာယီကန့်သတ်ထားသည်"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ကြိုးတပ်နားကြပ်"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ဖွင့်ထားသည်"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ပိတ်ထားသည်"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"ဝန်ဆောင်မှုပေးသူ ကွန်ရက် ပြောင်းလဲနေသည်။"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ဖုန်းလိုင်းမရှိပါ။"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ဖုန်းလိုင်းတစ်ဘား။"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ဖုန်းလိုင်းသုံးဘား။"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ဖုန်းလိုင်းအပြည့်။"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ဒေတာမရှိပါ။"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ဒေတာတစ်ဘား။"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ဒေတာထုတ်လွှင့်မှု ၂ဘားဖမ်းမိခြင်း။"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ဒေတာသုံးဘား။"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ဒေတာထုတ်လွှင့်မှုအပြည့်ဖမ်းမိခြင်း"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet ချိတ်ဆက်ထား။"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d1af289..9494c39 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -34,7 +34,7 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Sjekk passordet og prøv igjen"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Utenfor område"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Kobler ikke til automatisk"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen Internett-tilgang"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen internettilgang"</string>
     <string name="saved_network" msgid="7143698034077223645">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatisk tilkoblet via %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trykk for å slå av/på."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Hvilemodus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Innstillinger for omkoding av medier"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkoding"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiver omkoding for apper"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Overstyr omkodingsstandarder"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Slå på omkoding"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Anta at apper støtter moderne formater"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidig begrenset"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimaliserer batteritilstanden"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hodetelefoner med kabel"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Bytting av operatørnettverk"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er slått av"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke konfigurert til å bruke data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon – én stolpe."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon – to stolper."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon – tre stolper."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal er fullt."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data – én stolpe"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data – to stolper."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data – tre stolper."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal er fullt."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er frakoblet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet er tilkoblet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 0c6114b..e31fb4e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"मिडिया ट्रान्सकोडिङ सेटिङ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिङ अफ गर्नुहोस्"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"एपहरूमा ट्रान्सकोडिङ अन गर्नुहोस्"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी पूर्वनिर्धारित सेटिङ परिवर्तन गर्नुहोस्"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - केही समयका लागि ब्याट्री प्रयोग सीमित गरिएको छ"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"तारसहितको हेडफोन"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"अन छ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"अफ छ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"सेवा प्रदायकको नेटवर्क परिवर्तन गर्ने आइकन"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा निष्क्रिय छ"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"फोन छैन्।"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एउटा पट्टि।"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दुई पट्टि।"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तिन पट्टिहरू।"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सङ्केत भरिएको।"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"डेटा छैन।"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटाको एउटा पट्टि।"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दुई बाधाहरू।"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तिन बाधाहरू।"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा संकेत पूर्ण।"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट विच्छेद भयो।"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"इथरनेट जोडियो।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index a409756..0b75fdd 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Actief. Tik om te schakelen."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stand-bystatus app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Instellingen voor mediatranscodering"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodering uitschakelen"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodering inschakelen voor apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Standaardwaarden voor transcodering overschrijven"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodering inschakelen"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Aannemen dat apps moderne indelingen ondersteunen"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterij tijdelijk beperkt"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimaliseren voor batterijduur"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedrade hoofdtelefoon"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Uit"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Netwerk van provider wordt gewijzigd"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data uit"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Gebruik van gegevens is niet ingesteld"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Geen telefoonsignaal."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoon: één streepje."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoon: twee streepjes."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoon: drie streepjes."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefoonsignaal is op volle sterkte."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Geen gegevens."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Gegevens: één streepje."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Gegevens: twee streepjes."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Gegevens: drie streepjes."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Gegevenssignaal is op volle sterkte."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetverbinding verbroken."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet verbonden."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 0a0eeff..cfde61f 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ନିମ୍ନ ମାନର ନେଟ୍‌ୱର୍କ କାରଣରୁ ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"ୱାଇଫାଇ ସଂଯୋଗ ବିଫଳ ହୋଇଛି"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ସତ୍ୟାପନରେ ସମସ୍ୟା"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ପ୍ରମାଣୀକରଣରେ ସମସ୍ୟା"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"ସଂଯୋଗ କରିପାରିବ ନାହିଁ"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' ସହିତ ସଂଯୁକ୍ତ ହୋଇପାରୁନାହିଁ"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"ପାସ୍‌ୱର୍ଡ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍‌ କରନ୍ତୁ"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ଟ୍ରାନ୍ସକୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ଆପଗୁଡ଼ିକ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ସକ୍ଷମ କରନ୍ତୁ"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ଟ୍ରାନ୍ସକୋଡିଂ ଡିଫଲ୍ଟଗୁଡ଼ିକୁ ଓଭରରାଇଡ୍ କରନ୍ତୁ"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ଟ୍ରାନ୍ସକୋଡିଂକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ଧରିନିଅନ୍ତୁ ଆପଗୁଡ଼ିକ ଆଧୁନିକ ଫର୍ମାଟଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍‌ଭ୍ୟୁ ପ୍ରୟୋଗ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ ଅଛି"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ତାରଯୁକ୍ତ ହେଡଫୋନ୍"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ଚାଲୁ ଅଛି"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ବନ୍ଦ ଅଛି"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"କେରିଅର୍‍ ନେଟ୍‌ୱର୍କ ବଦଳୁଛି"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ମୋବାଇଲ୍‌ ଡାଟା ବନ୍ଦ ଅଛି"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ଫୋନର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ଫୋନ୍‍ରେ ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ଫୋନ୍ ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"କୌଣସି ଡାଟା ନାହିଁ।"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ଡାଟାର ଗୋଟିଏ ବାର ଅଛି।"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ଡାଟାର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ଡାଟାର ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ଡାଟା ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ଇଥରନେଟ୍‍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ଇଥରନେଟ୍‍ ସଂଯୁକ୍ତ ହୋଇଛି।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index c9c37d9..1221862 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"ਮੀਡੀਆ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਬੰਦ ਕਰੋ"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਦੀਆਂ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ਮੰਨ ਲਓ ਕਿ ਐਪਾਂ ਆਧੁਨਿਕ ਫਾਰਮੈਟਾਂ ਦਾ ਸਮਰਥਨ ਕਰਦੀਆਂ ਹਨ"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਕੁਝ ਸਮੇਂ ਲਈ ਸੀਮਤ"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ਤਾਰ ਵਾਲੇ ਹੈੱਡਫ਼ੋਨ"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ਚਾਲੂ"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ਬੰਦ"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"ਕੈਰੀਅਰ ਨੈੱਟਵਰਕ ਦੀ ਬਦਲੀ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ਡਾਟਾ ਵਰਤਣ ਲਈ ਸੈੱਟ ਨਹੀਂ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ਕੋਈ  ਡਾਟਾ  ਨਹੀਂ।"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">" ਡਾਟਾ  ਇੱਕ ਬਾਰ।"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">" ਡਾਟਾ  ਦੋ ਬਾਰਸ।"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">" ਡਾਟਾ  ਤਿੰਨ ਬਾਰ।"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">" ਡਾਟਾ  ਸਿਗਨਲ ਪੂਰਾ।"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ਈਥਰਨੈੱਟ ਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e894c2c..102835c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktywna. Dotknij, by zmienić."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stan aplikacji w trybie czuwania: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Ustawienia transkodowania multimediów"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Wyłącz transkodowanie"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Włącz transkodowanie dla aplikacji"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Zastąp ustawienia domyślne transkodowania"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Włącz transkodowanie"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Zakładaj, że aplikacje obsługują nowoczesne formaty"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Uruchomione usługi"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Wyświetl obecnie uruchomione usługi i nimi zarządzaj"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacja WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – bateria tymczasowo ograniczona"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optymalizuję, by utrzymać baterię w dobrym stanie"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Słuchawki przewodowe"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Włączono"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Wyłączono"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Zmiana sieci operatora"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Wyłączona"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie skonfigurowano do transmisji danych"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Brak sygnału telefonu."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: jeden pasek."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: dwa paski."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: trzy paski."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon: pełna moc sygnału."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Brak danych."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dane: jeden pasek."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dane: dwa paski."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dane: trzy paski."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Dane: pełna moc sygnału."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Rozłączono z siecią Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Połączono z siecią Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index acaabc7..99019a6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Alteração de rede da operadora"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de sinal de dados."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras do sinal de dados."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2c1a967..238e54b 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Toque para ativar/desativar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado do Modo de espera das apps:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Definições da transcodificação de multimédia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar a transcodificação"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ative a transcodificação para apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Substituir as predefinições da transcodificação"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar a transcodificação"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Assumir que as apps suportam formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços actualmente em execução"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Bateria limitada temporariamente."</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – A otimizar o estado da bateria"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auscultadores com fios"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ligado"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desligado"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rede do operador em mudança."</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Não definido para utilizar dados"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de telefone."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de telefone."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de telefone."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal de telefone completo."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Sem dados."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de dados."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de dados."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras de dados."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados completo."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desligada."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet ligada."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index acaabc7..99019a6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Alteração de rede da operadora"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de sinal de dados."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras do sinal de dados."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 57a0454..df95dbc 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atingeți pentru a comuta."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Setări pentru transcodarea conținutului media"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Dezactivați transcodarea"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Activați transcodarea pentru aplicații"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Modificați setările prestabilite de transcodare"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Activați transcodarea"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Presupuneți că aplicațiile acceptă formatele moderne"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterie limitată temporar"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se fac optimizări pentru buna funcționare a bateriei"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Căști cu fir"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activat"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Dezactivat"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Se schimbă rețeaua operatorului"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Date mobile dezactivate"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nu este setat pentru a folosi datele"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nu există semnal pentru telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Semnal pentru telefon: o bară."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Semnal pentru telefon: două bare."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Semnal pentru telefon: trei bare."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Semnal pentru telefon: complet."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nu există semnal pentru date."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Semnal pentru date: o bară."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Semnal pentru date: două bare."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Semnal pentru date: trei bare."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Semnal pentru date: complet."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet deconectat."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectat."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 09b8de0..68826d7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Включено. Нажмите, чтобы отключить."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Статус приложения в режиме ожидания:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки перекодирования медиафайлов"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Отключить перекодирование"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Включить перекодирование для приложений"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Переопределять настройки транскодирования по умолчанию"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Включить перекодирование"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Считать, что приложения поддерживают современные форматы кодирования"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Сервис WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> • Уровень заряда временно ограничен"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"Оптимизация для увеличения срока службы батареи (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Проводные наушники"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вкл."</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выкл."</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Сменить сеть"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильный Интернет отключен"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Мобильный Интернет по умолчанию не используется."</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Сигнал телефонной сети отсутствует."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефонной сети: одно деление."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефонной сети: два деления."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефонной сети: три деления."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Надежный телефонный сигнал."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал передачи данных отсутствует."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал передачи данных: одно деление."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигнал передачи данных: два деления."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Сигнал передачи данных: три деления."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Надежный сигнал передачи данных."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Устройство отключено от Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Устройство подключено к Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index d36140f..736445d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"සක්‍රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"යෙදුම් පොරොත්තු තත්ත්වය:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"මාධ්‍ය ට්‍රාන්ස්කෝඩින් සැකසීම්"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ට්‍රාන්ස්කෝඩින් අබල කරන්න"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"යෙදුම් සඳහා ට්‍රාන්ස්කෝඩින් සබල කරන්න"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ට්‍රාන්ස්කෝඩින් පෙරනිමි ප්‍රතික්ෂේප කරන්න"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ට්‍රාන්ස්කෝඩින් සබල කරන්න"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"යෙදුම් නවීන ආකෘති සඳහා සහාය දක්වයි යැයි උපකල්පනය කරමු"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ක්‍රියාත්මක කිරීම"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරිය තාවකාලිකව සීමිතයි"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරි සෞඛ්‍යය සඳහා ප්‍රශස්ත කරමින්"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්‍ර ආරෝපණය"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"රැහැන්ගත කළ හෙඩ්ෆෝන්"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ක්‍රියාත්මකයි"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ක්‍රියාවිරහිතයි"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"වාහක ජාලය වෙනස් වෙමින්"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"ජංගම දත්ත ක්‍රියාවිරහිතයි"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"දුරකථනයක් නැත."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"දුරකථනය තීරු එකයි."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"දුරකථනය තීරු දෙකයි."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"දුරකථනය තීරු තුනයි."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"දත්ත නැත."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"දත්ත තීරු එකයි."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"දත්ත තීරු 2."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"දත්ත තීරු 3."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"දත්ත සංඥාව පිරී ඇත."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ඊතර්නෙට් සම්බන්ධ කරන ලදී."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 096e95e..265ec8f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Zlyhanie konfigurácie adresy IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Nepripojené z dôvodu siete nízkej kvality"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Zlyhanie pripojenia Wi‑Fi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením totožnosti"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Nedá sa pripojiť"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"K sieti <xliff:g id="AP_NAME">%1$s</xliff:g> sa nedá pripojiť"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Skontrolujte heslo a skúste to znova"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktívne. Prepnite klepnutím."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostného režimu aplikácie: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavenia prekódovania médií"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Vypnúť prekódovanie"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Zapnúť prekódovanie aplikácií"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Prepísať predvolené nastavenia prekódovania"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Povoliť prekódovanie"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Prepdokladať, že aplikácie podporujú moderné formáty"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Spustené služby"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Zobrazovať a riadiť aktuálne spustené služby"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Implementácia WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batéria je dočasne obmedzená"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizácia stavu batérie"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Slúchadlá s káblom"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnúť"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnúť"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mení sa sieť operátora"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilné dáta sú vypnuté"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie je nastavené na používanie dát"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Žiadna telefónna sieť."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jeden stĺpec signálu telefónnej siete."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dve čiarky signálu telefónnej siete."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tri čiarky signálu telefónnej siete."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefónnej siete."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Žiadna dátová sieť."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čiarka signálu dátovej siete."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dve čiarky signálu dátovej siete."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tri čiarky signálu dátovej siete."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál dátovej siete."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Sieť ethernet je odpojená"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Sieť ethernet je pripojená"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 345fa36..2e6fc0e 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dotaknite se za preklop."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravljenosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavitve prekodiranja predstavnosti"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogočanje prekodiranja"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogočanje prekodiranja za aplikacije"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Preglasi privzete nastavitve prekodiranja"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Omogoči prekodiranje"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Aplikacije naj bi podpirale sodobne oblike zapisov"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Zagnane storitve"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Izvedba spletnega pogleda"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je začasno omejena"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizacija za ohran. zmog. baterije"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žične slušalke"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vklop"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izklop"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Spreminjanje omrežja operaterja"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Ni nastavljeno za uporabo prenosa podatkov"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ni telefona."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon z eno črtico."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon z dvema črticama."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon s tremi črticami."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je poln."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ni podatkov."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal z eno črtico."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Podatki z dvema črticama."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Podatki s tremi črticami."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal poln."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetna povezava je prekinjena."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernetna povezava je vzpostavljena."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 3953a6a4f..5774d9b 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trokit për ta ndryshuar."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Gjendja e gatishmërisë e aplikacionit:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Cilësimet e transkodimit të multimediave"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Çaktivizo transkodimin"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivizo transkodimin për aplikacionet"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Anulo parazgjedhjet e transkodimit"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivizo transkodimin"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Supozo se aplikacionet i mbështetin formatet moderne"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Shërbimet në ekzekutim"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Zbatimi i WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateria e kufizuar përkohësisht"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po optimizohet për integritetin e baterisë"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kufje me tela"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktive"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Joaktive"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rrjeti i operatorit celular po ndryshohet"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Të dhënat celulare janë joaktive"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Nuk është caktuar të përdorë të dhënat"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Nuk ka telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoni ka edhe një vijë."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoni ka dy vija."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoni ka tre vija."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinjali i telefonit është i plotë."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Nuk ka të dhëna."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sinjali është vetëm një vijë."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Të dhënat kanë dy vija."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Sinjali është me tre vija."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinjali i të dhënave është i plotë."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Lidhja e eternetit u shkëput."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Lidhja e eternetit u lidh."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 70b2879..207ca74 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активна. Додирните да бисте је деактивирали."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Стање приправности апликације: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Подешавања транскодирања медија"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Онемогући транскодирање"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Омогућите транскодирање за апликације"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Замени подразумевана подешавања транскодирања"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Омогући транскодирање"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Подразумевај да апликације подржавају модерне формате"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Примена WebView-а"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – батерија је тренутно ограничена"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизује се ради стања батерије"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
@@ -565,4 +566,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичане слушалице"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Укључено"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Искључено"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промена мреже мобилног оператера"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилни подаци су искључени"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Није подешено за коришћење података"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Нема телефона."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефона има једну црту."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефона од две црте."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефона од три црте."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигнал телефона је пун."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Нема података."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал за податке има једну црту."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигнал за податке од две црте."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Сигнал за податке од три црте."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигнал за податке је најјачи."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Веза са етернетом је прекинута."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Етернет је повезан."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f466e88..7afd344 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryck om du vill inaktivera."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Status för strömsparfunktion för appar:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Inställningar för medieomkodning"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Inaktivera omkodning"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivera omkodning för appar"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Åsidosätta standardinställningar för omkodning"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivera omkodning"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Anta att appar har stöd för moderna format"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktiva tjänster"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visa och styr aktiva tjänster"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – batteriet är tillfälligt begränsat"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerar batteriets livslängd"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hörlurar med sladd"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Byter leverantörsnätverk"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata har inaktiverats"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Inte inställd på mobildata"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: en stapel."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: två staplar."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: tre staplar."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignalen är full."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Inga data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data: en stapel."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data: två staplar."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data: tre staplar."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignalen är full."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet har kopplats från."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet har anslutits."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index e1060fec..084b5c93 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Inatumika. Gusa ili ugeuze."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Hali ya kisitisha programu:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Mipangilio ya kubadilisha muundo wa faili ya maudhui"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Zima ubadilishaji muundo wa faili"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Washa ubadilishaji muundo wa faili kwenye programu"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Batilisha chaguomsingi za kubadilisha miundo ya faili"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Ruhusu ubadilishaji wa miundo ya faili"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Chukulia kuwa programu zinatumia miundo ya kisasa"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Huduma zinazoendeshwa"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Onyesha na udhibiti huduma zinazoendeshwa kwa sasa"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Utekelezaji wa WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Imebakisha <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ijae chaji"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri imedhibitiwa kwa muda"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inaboresha muda wa kutumia betri"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vipokea sauti vya waya"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Umewashwa"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Umezimwa"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mabadiliko katika mtandao wa mtoa huduma"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Umezima data ya mtandao wa simu"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Haijawekewa mipangilio ya kutumia data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Hakuna simu"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Mwambaa mmoja wa simu."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Miambaa miwili ya simu"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Miambaa mitatu ya simu."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Ishara ya simu imejaa."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Hakuna data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Upapi mmoja wa habari"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Miamba miwili ya data."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Fito tatu za habari."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Ishara ya data imejaa."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethaneti imeondolewa."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethaneti imeunganishwa."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index ba98d79..5fdf8bd 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"செயலில் உள்ளது. மாற்ற, தட்டவும்."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"காத்திருப்பில் உள்ள ஆப்ஸின் நிலை:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"மீடியா குறிமாற்ற அமைப்புகள்"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"குறிமாற்றத்தை முடக்கு"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ஆப்ஸுக்குக் குறிமாற்றத்தை இயக்கு"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"இயல்புநிலை குறிமாற்றங்களை மீறிச் செயல்படு"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"குறிமாற்றத்தை இயக்கு"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ஆப்ஸ் மாடர்ன் வடிவங்களை ஆதரிக்கும்படி அமை"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>-பேட்டரி தற்காலிகக் கட்டுப்பாட்டிலுள்ளது"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"வயருள்ள ஹெட்ஃபோன்"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ஆன்"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ஆஃப்"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"மொபைல் நிறுவன நெட்வொர்க்கை மாற்றும்"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"சிக்னல் இல்லை."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"சிக்னல் முழுமையாக உள்ளது."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"டேட்டா சிக்னல் இல்லை."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"தரவு சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"தரவின் சிக்னல் இரண்டு கோடு வரை உள்ளது."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"தரவு சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"தரவு சிக்னல் முழுமையாக உள்ளது."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ஈத்தர்நெட் இணைக்கப்பட்டது."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 0b93979..38f08b2 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"యాప్ స్టాండ్‌బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"మీడియా ట్రాన్స్‌కోడింగ్ సెట్టింగ్‌లు"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ట్రాన్స్‌కోడింగ్‌ను డిజేబుల్ చేయండి"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"యాప్‌ల కోసం ట్రాన్స్‌కోడింగ్‌ను ఎనేబుల్ చేయండి"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ట్రాన్స్‌కోడింగ్ ఆటోమేటిక్ సెట్టింగ్‌లను ఓవర్‌రైడ్ చేయండి"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ట్రాన్స్‌కోడింగ్‌ను ఎనేబుల్ చేయండి"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"యాప్‌లు ఆధునిక ఫార్మాట్‌లకు సపోర్ట్ చేస్తాయని అనుకోండి"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> -బ్యాటరీ తాత్కాలికంగా పరిమితం చేయబడింది"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - బ్యాటరీ స్థితిని ఆప్టిమైజ్ చేయడం కోసం"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"వైర్ ఉన్న హెడ్‌ఫోన్"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ఆన్‌లో ఉంది"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ఆఫ్‌లో ఉంది"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"క్యారియర్ నెట్‌వర్క్ మారుతోంది"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"మొబైల్ డేటా ఆఫ్‌లో ఉంది"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"డేటాను ఉపయోగించే విధంగా సెట్ చేయలేదు"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ఫోన్ లేదు."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ఫోన్ ఒక బారు."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ఫోన్ రెండు బార్లు."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ఫోన్ మూడు బార్లు."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ఫోన్ సిగ్నల్ పూర్తిగా ఉంది."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"డేటా లేదు."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"డేటా ఒక బారు."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"డేటా రెండు బార్‌లు."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"డేటా మూడు బార్లు."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"డేటా సిగ్నల్ సంపూర్ణంగా ఉంది."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ఈథర్‌నెట్ డిస్‌కనెక్ట్ చేయబడింది."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ఈథర్‌నెట్ కనెక్ట్ చేయబడింది."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index a31e146..dabb9d3 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"ใช้งานอยู่ แตะเพื่อสลับ"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"สถานะการสแตนด์บายของแอป:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"การตั้งค่าการแปลงสื่อ"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ปิดใช้การแปลง"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"เปิดใช้การแปลงสำหรับแอป"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ลบล้างค่าเริ่มต้นของการแปลง"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"เปิดใช้การแปลง"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"ถือว่าแอปรองรับรูปแบบสมัยใหม่"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"การใช้งาน WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จแบตเตอรี่จำกัดชั่วคราว"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"หูฟังแบบมีสาย"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"เปิด"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ปิด"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"เน็ตมือถือปิดอยู่"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"ไม่มีสัญญาณโทรศัพท์"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"สัญญาณโทรศัพท์สองขีด"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"สัญญาณโทรศัพท์สามขีด"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"สัญญาณโทรศัพท์เต็ม"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"ไม่มีข้อมูล"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"สัญญาณข้อมูลหนึ่งขีด"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"สัญญาณข้อมูลสองขีด"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"สัญญาณข้อมูลสามขีด"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"สัญญาณข้อมูลเต็ม"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"เชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index bbb7779..b451d89 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Pagkabigo ng Configuration ng IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Pagkabigo ng Koneksyon sa WiFi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pagpapatotoo"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pag-authenticate"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Hindi makakonekta"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Hindi makakonekta sa \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Suriin ang password at subukang muli"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. I-tap upang i-toggle."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Status ng app standby:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Mga setting ng pag-transcode ng media"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"I-disable ang pag-transcode"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"I-enable ang pag-transcode para sa mga app"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"I-override ang mga default ng pagta-transcode"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"I-enable ang pagta-transcode"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Ipagpalagay na sinusuportahan ng mga app ang mga modernong format"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Mga tumatakbong serbisyo"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Pagpapatupad sa WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pansamantalang limitado ang baterya"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ino-optimize para sa tagal ng baterya"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired na headphone"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Naka-on"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Naka-off"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Nagpapalit ng carrier network"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Naka-off ang mobile data"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Hindi nakatakdang gumamit ng data"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Walang telepono."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telepono na isang bar."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telepono na dalawang bar."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telepono na tatlong bar."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Puno ang signal ng telepono."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Walang data."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data na isang bar."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data na dalawang bar."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data na tatlong bar."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Puno ang signal ng data."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Nadiskonekta ang Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Nakakonekta ang Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index fba7f41..e1ff56b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Etkin. Geçiş yapmak için dokunun."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Uygulamayı beklemeye alma durumu: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Medya kod dönüştürme ayarları"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Kod dönüştürmeyi devre dışı bırak"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Uygulamalar için kod dönüştürmeyi etkinleştir"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Kod dönüştürme varsayılanlarını geçersiz kıl"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Kod dönüştürmeyi etkinleştir"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Uygulamaların modern biçimleri desteklediğini varsay"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Çalışan hizmetler"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Web Görünümü kullanımı"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil geçici olarak sınırlı"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil sağlığı için optimize ediliyor"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kablolu kulaklık"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Açık"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Kapalı"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operatör ağı değiştiriliyor"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil veri kapalı"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Veri kullanmak üzere ayarlanmadı"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon sinyali yok."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon sinyali bir çubuk."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon sinyali iki çubuk."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon sinyali üç çubuk."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon sinyali tam."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Veri yok."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Veri sinyali bir çubuk."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Veri sinyali iki çubuk."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Veri sinyali üç çubuk."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Veri sinyali tam."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kesildi."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet bağlandı."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b633752..6806ce6 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Активний додаток. Торкніться, щоб дезактивувати."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Режим очікування: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Налаштування перекодування медіафайлів"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Вимкнути перекодування"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Увімкнути перекодування додатків"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Замінити стандартні налаштування перекодування"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Увімкнути перекодування"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Вважати, що додатки підтримують сучасні формати"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Застосування WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – дані акумулятора тимчасово недоступні"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – стан акумулятора оптимізується"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
@@ -566,4 +567,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Дротові навушники"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Увімкнено"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Вимкнено"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змінення мережі оператора"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобільне передавання даних вимкнено"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Не вибрано для використання даних"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Немає сигналу телефону."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Одна смужка сигналу телефону."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Дві смужки сигналу телефону."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Три смужки сигналу телефону."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Максимальний сигнал телефону."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Немає сигналу даних."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Одна смужка сигналу даних."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дві смужки сигналу даних."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Три смужки сигналу даних."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Максимальний сигнал даних."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet відключено."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet підключено."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index b4d8ad2..4363f0b 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"میڈیا ٹرانسکوڈنگ کی ترتیبات"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"ٹرانسکوڈنگ غیر فعال کریں"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"ایپس کے لئے ٹرانسکوڈنگ فعال کریں"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"ٹرانسکوڈنگ ڈیفالٹس کو اوور رائیڈ کریں"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"ٹرانسکوڈنگ فعال کریں"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"فرض کریں کہ ایپس جدید فارمیٹس کو سپورٹ کرتی ہیں"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"‏WebView کا نفاذ"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری عارضی طور پر محدود ہے"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری کی صحت کیلئے بہتر بنایا جا رہا ہے"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"وائرڈ ہیڈ فون"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"آن"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"آف"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"کیریئر نیٹ ورک کی تبدیلی"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X‎"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+‎"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+‎"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+‎"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"موبائل ڈیٹا آف ہے"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"ڈیٹا استعمال کرنے کے لیے سیٹ نہیں ہے"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"کوئی فون نہیں ہے۔"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"فون کا ایک بار۔"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"فون کے دو بارز۔"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"فون کے تین بارز۔"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"فون سگنل پورا ہے۔"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"کوئی ڈیٹا نہیں ہے۔"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ڈیٹا کا ایک بار۔"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ڈیٹا کے دو بارز۔"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ڈیٹا کے تین بارز۔"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ڈیٹا سگنل بھرا ہوا ہے۔"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ایتھرنیٹ منقطع ہے۔"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ایتھرنیٹ منسلک ہے۔"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 2f06fcf..0770dcc 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -25,7 +25,7 @@
     <item msgid="3288373008277313483">"Qidiruv…"</item>
     <item msgid="6050951078202663628">"Ulanmoqda…"</item>
     <item msgid="8356618438494652335">"Tasdiqdan o‘tilmoqda…"</item>
-    <item msgid="2837871868181677206">"IP manzil o‘zlashtirilmoqda…"</item>
+    <item msgid="2837871868181677206">"IP manzil olinmoqda…"</item>
     <item msgid="4613015005934755724">"Ulangan"</item>
     <item msgid="3763530049995655072">"Muzlatildi"</item>
     <item msgid="7852381437933824454">"Uzilmoqda…"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 5bb422e..1eecf88 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP manzilini sozlab bo‘lmadi"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tasdiqdan o‘tishda muammo"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tekshiruvda muammo"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Tarmoqqa ulanilmadi"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"“<xliff:g id="AP_NAME">%1$s</xliff:g>” nomli tarmoqqa ulanilmadi"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Parolni tekshirib, qaytadan urining"</string>
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Faol. O‘zgartirish uchun bu yerga bosing."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Kutish rejimi holati: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Media transkripsiyasi sozlamalari"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Transkripsiyani faolsizlantirish"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Ilovalar uchun transkripsiyani yoqish"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Transkripsiya parametrlarini almashtirish"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Transkripsiyasini yoqish"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Ilovalarda zamonaviy kodlash formatlari ishlaydi deb hisoblash"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ta’minotchisi"</string>
@@ -432,8 +433,8 @@
     <skip />
     <string name="power_discharge_by_enhanced" msgid="563438403581662942">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
-    <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
+    <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> gacha"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya quvvati tugash vaqti: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kam qoldi"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻladi"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻladi"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quvvat darajasi vaqtincha cheklangan"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batareya quvvati muvozanatlanmoqda"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli quloqlik"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Yoniq"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Oʻchiq"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobil tarmoqni o‘zgartirish"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil internet yoqilmagan"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Signal yo‘q."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon bitta panelda."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon ikkita panelda."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon uchta panelda."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon signali to‘liq."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ma’lumotlar yo‘q."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Ma’lumotlar bitta panelda."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Ma’lumotlar ikkita panelda."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Ma’lumotlar uchta panelda."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Internet signali butun."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Qurilma Ethernet tarmog‘idan uzildi."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Qurilma Ethernet tarmog‘iga ulandi."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0acf941..643fdb9 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Hiện hoạt. Nhấn để chuyển đổi."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Trạng thái chờ ứng dụng:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Cài đặt chuyển mã nội dung nghe nhìn"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Tắt tùy chọn chuyển mã"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Bật tùy chọn chuyển mã cho ứng dụng"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Ghi đè tùy chọn chuyển mã mặc định"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Bật tính năng chuyển mã"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Giả định rằng các ứng dụng hỗ trợ định dạng hiện đại"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Các dịch vụ đang chạy"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Xem và kiểm soát các dịch vụ đang chạy"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Triển khai WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc đầy"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc đầy"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Thời lượng pin bị hạn chế tạm thời"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang tối ưu hóa để cải thiện độ bền của pin"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Tai nghe có dây"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Đang bật"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Đang tắt"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Thay đổi mạng của nhà mạng"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Đã tắt dữ liệu di động"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Chưa được đặt để sử dụng dữ liệu"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Không có điện thoại nào."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tín hiệu điện thoại một vạch."</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tín hiệu điện thoại hai vạch."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tín hiệu điện thoại ba vạch."</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tín hiệu điện thoại đầy đủ."</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Không có dữ liệu."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Tín hiệu dữ liệu một vạch."</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Tín hiệu dữ liệu hai vạch."</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tín hiệu dữ liệu ba vạch."</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Tín hiệu dữ liệu đầy đủ."</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Đã ngắt kết nối Ethernet."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Đã kết nối Ethernet."</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index ca2ad87..81d8106 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"已启用。点按即可切换。"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"应用待机状态:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"媒体转码设置"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"停用转码功能"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"为应用启用转码功能"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"覆盖转码默认设置"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"启用转码"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"假设应用支持现代格式"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 实现"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暂时限用电池"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在针对电池状况进行优化"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有线耳机"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"开启"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"关闭"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"运营商网络正在更改"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"移动数据网络已关闭"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"未设置为使用移动数据"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"没有手机信号。"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"手机信号强度为一格。"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"手机信号强度为两格。"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"手机信号强度为三格。"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"手机信号满格。"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"没有数据网络信号。"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"数据信号强度为一格。"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"数据信号强度为两格。"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"数据信号强度为三格。"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"数据信号满格。"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太网已断开连接。"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"以太网已连接。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 16ca19d..39a12aa 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕按即可切換。"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"備用應用程式狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼設定"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"為應用程式啟用轉碼功能"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼功能"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新型格式"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池充電"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在優化電池狀態"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"流動網絡供應商網絡正在變更"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"流動數據已關閉"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"未設定至可使用資料"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度為一格。"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度為兩格。"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度為三格。"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網絡。"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網絡訊號強度為一格。"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"數據網絡訊號強度為兩格。"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"數據網絡訊號強度為三格。"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網絡訊號滿格。"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太網連接中斷。"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"已連接以太網。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 810119b..cc35ed3 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕觸即可切換。"</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"應用程式待命狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼功能設定"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新格式"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 實作"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池用量"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 針對電池狀態進行最佳化調整"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"電信業者網路正在進行變更"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"行動數據已關閉"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"並未設為使用行動數據"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度一格。"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度兩格。"</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度三格。"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網路。"</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網路訊號強度一格。"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"數據網路訊號強度兩格。"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"數據網路訊號強度三格。"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網路訊號滿格。"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"未連上乙太網路。"</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"已連上乙太網路。"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 23beeb1..bcc6369 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -400,8 +400,9 @@
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Kuyasebenza. Thepha ukuze ushintshe."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Isimo sokulinda kohlelo lokusebenza:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="transcode_settings_title" msgid="2581975870429850549">"Amasethingi wemidiya yokudlulisela ikhodi"</string>
-    <string name="transcode_enable_all" msgid="9102460144086871903">"Khubaza ukudlulisela ikhodi"</string>
-    <string name="transcode_skip_apps" msgid="8249721984597390142">"Nika amandla ukudlulisela ikhodi kwezinhlelo zokusebenza"</string>
+    <string name="transcode_user_control" msgid="6176368544817731314">"Khipha okuzenzakalelayo kokudlulisela ikhodi"</string>
+    <string name="transcode_enable_all" msgid="2411165920039166710">"Nika amandla ukudlulisela ikhodi"</string>
+    <string name="transcode_default" msgid="3784803084573509491">"Kuthathe njengokungathi izinhlelo zokusebenza zisekela amafomethi esimanje"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Amasevisi asebenzayo"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Buka futhi ulawule amasevisi  asebenzayo okwamanje"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"Ukufakwa ke-WebView"</string>
@@ -449,7 +450,7 @@
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string>
-    <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ibhethri ikhawulelwe okwesikhashana"</string>
+    <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ilungiselela impilo yebhethri"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
@@ -564,4 +565,29 @@
     <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ama-headphone anentambo"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vuliwe"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Valiwe"</string>
+    <string name="carrier_network_change_mode" msgid="4257621815706644026">"Inethiwekhi yenkampani yenethiwekhi iyashintsha"</string>
+    <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+    <string name="data_connection_edge" msgid="4625509456544797637">"I-EDGE"</string>
+    <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+    <string name="data_connection_gprs" msgid="1251945769006770189">"I-GPRS"</string>
+    <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+    <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+    <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+    <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+    <string name="data_connection_lte" msgid="7675461204366364124">"I-LTE"</string>
+    <string name="data_connection_lte_plus" msgid="6643158654804916653">"I-LTE+"</string>
+    <string name="cell_data_off_content_description" msgid="2280700839891636498">"Idatha yeselula ivaliwe"</string>
+    <string name="not_default_data_content_description" msgid="6517068332106592887">"Akusethiwe ukuze kusetshenziswe idatha"</string>
+    <string name="accessibility_no_phone" msgid="2687419663127582503">"Ayikho ifoni."</string>
+    <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ibha eyodwa yefoni"</string>
+    <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Amabha amabilil efoni."</string>
+    <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Amabha amathathu efoni"</string>
+    <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isiginali yefoni igcwele"</string>
+    <string name="accessibility_no_data" msgid="4563181886936931008">"Ayikho idatha."</string>
+    <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Idatha enye yebha"</string>
+    <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Amabha amabili edatha"</string>
+    <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Amabha amathathu edatha"</string>
+    <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Igcwele i-signal yedatha"</string>
+    <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"I-Ethernet inqanyuliwe."</string>
+    <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"I-Ethernet ixhunyiwe."</string>
 </resources>
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 22213cb..f518b74 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1004,9 +1004,6 @@
     <!-- Settings item title to select the default behavior for transcoding if an encodig is not supported by an app. [CHAR LIMIT=85] -->
     <string name="transcode_default">Assume apps support modern formats</string>
 
-    <!-- Settings category title for selecting apps to be enabled for transcoding. [CHAR LIMIT=85] -->
-    <string name="transcode_skip_apps">Enable transcoding for apps</string>
-
     <!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
     <string name="runningservices_settings_title">Running services</string>
     <!-- Services settings screen, setting option summary for the user to go to the screen to view running services  -->
@@ -1115,7 +1112,7 @@
     <string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until charged</string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
     <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until charged</string>
-    <!-- [CHAR_LIMIT=40] Label for battery level chart when charge been limited -->
+    <!-- [CHAR_LIMIT=80] Label for battery level chart when charge been limited -->
     <string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Optimizing for battery health</string>
 
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
@@ -1407,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/media/MediaOutputSliceConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
index fc16eb6..61af5a7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
@@ -22,16 +22,6 @@
 public class MediaOutputSliceConstants {
 
     /**
-     * Key for the Media output setting.
-     */
-    public static final String KEY_MEDIA_OUTPUT = "media_output";
-
-    /**
-     * Key for the Media output group setting.
-     */
-    public static final String KEY_MEDIA_OUTPUT_GROUP = "media_output_group";
-
-    /**
      * Key for the Remote Media slice.
      */
     public static final String KEY_REMOTE_MEDIA = "remote_media";
@@ -47,19 +37,6 @@
     public static final String KEY_SESSION_INFO_ID = "key_session_info_id";
 
     /**
-     * Activity Action: Show a settings dialog containing {@link MediaDevice} to transfer media.
-     */
-    public static final String ACTION_MEDIA_OUTPUT =
-            "com.android.settings.panel.action.MEDIA_OUTPUT";
-
-    /**
-     * Activity Action: Show a settings dialog containing {@link MediaDevice} to handle media group
-     * operation.
-     */
-    public static final String ACTION_MEDIA_OUTPUT_GROUP =
-            "com.android.settings.panel.action.MEDIA_OUTPUT_GROUP";
-
-    /**
      * A string extra specifying a media package name.
      */
     public static final String EXTRA_PACKAGE_NAME =
@@ -72,12 +49,6 @@
             "com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
 
     /**
-     * An intent action to dismiss media output dialog.
-     */
-    public static final String ACTION_DISMISS_MEDIA_OUTPUT_DIALOG =
-            "com.android.systemui.action.DISMISS_MEDIA_OUTPUT_DIALOG";
-
-    /**
      * Settings package name.
      */
     public static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
new file mode 100644
index 0000000..09f285b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
@@ -0,0 +1,235 @@
+/*
+ * 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.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.
+ */
+public class MobileMappings {
+
+    /**
+     * Generates the RAT key from the TelephonyDisplayInfo.
+     */
+    public static String getIconKey(TelephonyDisplayInfo telephonyDisplayInfo) {
+        if (telephonyDisplayInfo.getOverrideNetworkType()
+                == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
+            return toIconKey(telephonyDisplayInfo.getNetworkType());
+        } else {
+            return toDisplayIconKey(telephonyDisplayInfo.getOverrideNetworkType());
+        }
+    }
+
+    /**
+     * Converts the networkType into the RAT key.
+     */
+    public static String toIconKey(@Annotation.NetworkType int networkType) {
+        return Integer.toString(networkType);
+    }
+
+    /**
+     * Converts the displayNetworkType into the RAT key.
+     */
+    public static String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) {
+        switch (displayNetworkType) {
+            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA";
+            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus";
+            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_NR);
+            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus";
+            default:
+                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/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
new file mode 100644
index 0000000..b8030f1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
@@ -0,0 +1,286 @@
+/*
+ * 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.mobile;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyDisplayInfo;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+/**
+ * Tracks the mobile signal status for the SysUI and Settings.
+ *
+ * This class is not threadsafe. All the mobile statuses monitored by this class is stored in
+ * MobileStatus. Whoever uses this class should only rely on the MobileStatusTracker#Callback
+ * to get the latest mobile statuses. Do not get mobile statues directly from
+ * MobileStatusTracker#MobileStatus.
+ */
+public class MobileStatusTracker {
+    private static final String TAG = "MobileStatusTracker";
+    private final TelephonyManager mPhone;
+    private final SubscriptionInfo mSubscriptionInfo;
+    private final Callback mCallback;
+    private final MobileStatus mMobileStatus;
+    private final PhoneStateListener mPhoneStateListener;
+    private final SubscriptionDefaults mDefaults;
+    private final Handler mReceiverHandler;
+
+    /**
+     * MobileStatusTracker constructors
+     *
+     * @param phone The TelephonyManager which corresponds to the subscription being monitored.
+     * @param receiverLooper The Looper on which the callback will be invoked.
+     * @param info The subscription being monitored.
+     * @param defaults The wrapper of the SubscriptionManager.
+     * @param callback The callback to notify any changes of the mobile status, users should only
+     *                 use this callback to get the latest mobile status.
+     */
+    public MobileStatusTracker(TelephonyManager phone, Looper receiverLooper,
+            SubscriptionInfo info, SubscriptionDefaults defaults, Callback callback) {
+        mPhone = phone;
+        mReceiverHandler = new Handler(receiverLooper);
+        mPhoneStateListener = new MobilePhoneStateListener();
+        mSubscriptionInfo = info;
+        mDefaults = defaults;
+        mCallback = callback;
+        mMobileStatus = new MobileStatus();
+        updateDataSim();
+        mReceiverHandler.post(() -> mCallback.onMobileStatusChanged(
+                /* updateTelephony= */false, new MobileStatus(mMobileStatus)));
+    }
+
+    public PhoneStateListener getPhoneStateListener() {
+        return mPhoneStateListener;
+    }
+
+    /**
+     * Config the MobileStatusTracker to start or stop monitoring platform signals.
+     */
+    public void setListening(boolean listening) {
+        if (listening) {
+            mPhone.registerPhoneStateListener(mReceiverHandler::post, mPhoneStateListener);
+        } else {
+            mPhone.unregisterPhoneStateListener(mPhoneStateListener);
+        }
+    }
+
+    private void updateDataSim() {
+        int activeDataSubId = mDefaults.getActiveDataSubId();
+        if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
+            mMobileStatus.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
+        } else {
+            // There doesn't seem to be a data sim selected, however if
+            // there isn't a MobileSignalController with dataSim set, then
+            // QS won't get any callbacks and will be blank.  Instead
+            // lets just assume we are the data sim (which will basically
+            // show one at random) in QS until one is selected.  The user
+            // should pick one soon after, so we shouldn't be in this state
+            // for long.
+            mMobileStatus.dataSim = true;
+        }
+    }
+
+    private void setActivity(int activity) {
+        mMobileStatus.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+                || activity == TelephonyManager.DATA_ACTIVITY_IN;
+        mMobileStatus.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
+    }
+
+    private class MobilePhoneStateListener extends PhoneStateListener implements
+            PhoneStateListener.ServiceStateChangedListener,
+            PhoneStateListener.SignalStrengthsChangedListener,
+            PhoneStateListener.CallStateChangedListener,
+            PhoneStateListener.DataConnectionStateChangedListener,
+            PhoneStateListener.DataActivityListener,
+            PhoneStateListener.CarrierNetworkChangeListener,
+            PhoneStateListener.ActiveDataSubscriptionIdChangedListener,
+            PhoneStateListener.DisplayInfoChangedListener{
+
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength
+                        + ((signalStrength == null) ? ""
+                                : (" level=" + signalStrength.getLevel())));
+            }
+            mMobileStatus.signalStrength = signalStrength;
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onServiceStateChanged(ServiceState state) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onServiceStateChanged voiceState="
+                        + (state == null ? "" : state.getState())
+                        + " dataState=" + (state == null ? "" : state.getDataRegistrationState()));
+            }
+            mMobileStatus.serviceState = state;
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onDataConnectionStateChanged: state=" + state
+                        + " type=" + networkType);
+            }
+            mMobileStatus.dataState = state;
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onDataActivity(int direction) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onDataActivity: direction=" + direction);
+            }
+            setActivity(direction);
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */false, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onCarrierNetworkChange(boolean active) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onCarrierNetworkChange: active=" + active);
+            }
+            mMobileStatus.carrierNetworkChangeMode = active;
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onActiveDataSubscriptionIdChanged: subId=" + subId);
+            }
+            updateDataSim();
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */true, new MobileStatus(mMobileStatus));
+        }
+
+        @Override
+        public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
+            }
+            mMobileStatus.telephonyDisplayInfo = telephonyDisplayInfo;
+            mCallback.onMobileStatusChanged(
+                    /* updateTelephony= */ true, new MobileStatus(mMobileStatus));
+        }
+    }
+
+    /**
+     * Wrapper class of the SubscriptionManager, for mock testing purpose
+     */
+    public static class SubscriptionDefaults {
+        public int getDefaultVoiceSubId() {
+            return SubscriptionManager.getDefaultVoiceSubscriptionId();
+        }
+
+        public int getDefaultDataSubId() {
+            return SubscriptionManager.getDefaultDataSubscriptionId();
+        }
+
+        public int getActiveDataSubId() {
+            return SubscriptionManager.getActiveDataSubscriptionId();
+        }
+    }
+
+    /**
+     * Wrapper class which contains all the mobile status tracked by MobileStatusTracker.
+     */
+    public static class MobileStatus {
+        public boolean activityIn;
+        public boolean activityOut;
+        public boolean dataSim;
+        public boolean carrierNetworkChangeMode;
+        public int dataState = TelephonyManager.DATA_DISCONNECTED;
+        public ServiceState serviceState;
+        public SignalStrength signalStrength;
+        public TelephonyDisplayInfo telephonyDisplayInfo =
+                new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+
+        /**
+         * Empty constructor
+         */
+        public MobileStatus() { }
+
+        /**
+         * Copy constructors
+         *
+         * @param status Source MobileStatus
+         */
+        public MobileStatus(MobileStatus status) {
+            copyFrom(status);
+        }
+
+        protected void copyFrom(MobileStatus status) {
+            activityIn = status.activityIn;
+            activityOut = status.activityOut;
+            dataSim = status.dataSim;
+            carrierNetworkChangeMode = status.carrierNetworkChangeMode;
+            dataState = status.dataState;
+            // We don't do deep copy for the below members since they may be Mockito instances.
+            serviceState = status.serviceState;
+            signalStrength = status.signalStrength;
+            telephonyDisplayInfo = status.telephonyDisplayInfo;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            return builder.append("[activityIn=").append(activityIn).append(',')
+                .append("activityOut=").append(activityOut).append(',')
+                .append("dataSim=").append(dataSim).append(',')
+                .append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode).append(',')
+                .append("dataState=").append(dataState).append(',')
+                .append("serviceState=").append(serviceState == null ? ""
+                        : serviceState.toString()).append(',')
+                .append("signalStrength=").append(signalStrength == null ? ""
+                        : signalStrength.toString()).append(',')
+                .append("telephonyDisplayInfo=").append(telephonyDisplayInfo == null ? ""
+                        : telephonyDisplayInfo.toString()).append(']').toString();
+        }
+    }
+
+    /**
+     * Callback for notifying any changes of the mobile status.
+     *
+     * This callback will always be invoked on the receiverLooper which must be specified when
+     * MobileStatusTracker is constructed.
+     */
+    public interface Callback {
+        /**
+         * Notify the mobile status has been updated.
+         *
+         * @param updateTelephony Whether needs to update other Telephony related parameters, this
+         *                        is only used by SysUI.
+         * @param mobileStatus Holds the latest mobile statuses
+         */
+        void onMobileStatusChanged(boolean updateTelephony, MobileStatus mobileStatus);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
new file mode 100644
index 0000000..c2613a5
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.mobile;
+
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.R;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Telephony related icons and strings for SysUI and Settings.
+ */
+public class TelephonyIcons {
+    //***** Data connection icons
+    public static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
+
+    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;
+
+    public static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
+            "CARRIER_NETWORK_CHANGE",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.carrier_network_change_mode,
+            0,
+            false);
+
+    public static final MobileIconGroup THREE_G = new MobileIconGroup(
+            "3G",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_3g,
+            TelephonyIcons.ICON_3G,
+            true);
+
+    public static final MobileIconGroup WFC = new MobileIconGroup(
+            "WFC",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            0, 0, false);
+
+    public static final MobileIconGroup UNKNOWN = new MobileIconGroup(
+            "Unknown",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            0, 0, false);
+
+    public static final MobileIconGroup E = new MobileIconGroup(
+            "E",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_edge,
+            TelephonyIcons.ICON_E,
+            false);
+
+    public static final MobileIconGroup ONE_X = new MobileIconGroup(
+            "1X",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_cdma,
+            TelephonyIcons.ICON_1X,
+            true);
+
+    public static final MobileIconGroup G = new MobileIconGroup(
+            "G",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_gprs,
+            TelephonyIcons.ICON_G,
+            false);
+
+    public static final MobileIconGroup H = new MobileIconGroup(
+            "H",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_3_5g,
+            TelephonyIcons.ICON_H,
+            false);
+
+    public static final MobileIconGroup H_PLUS = new MobileIconGroup(
+            "H+",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_3_5g_plus,
+            TelephonyIcons.ICON_H_PLUS,
+            false);
+
+    public static final MobileIconGroup FOUR_G = new MobileIconGroup(
+            "4G",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_4g,
+            TelephonyIcons.ICON_4G,
+            true);
+
+    public static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
+            "4G+",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_4g_plus,
+            TelephonyIcons.ICON_4G_PLUS,
+            true);
+
+    public static final MobileIconGroup LTE = new MobileIconGroup(
+            "LTE",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_lte,
+            TelephonyIcons.ICON_LTE,
+            true);
+
+    public static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
+            "LTE+",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_lte_plus,
+            TelephonyIcons.ICON_LTE_PLUS,
+            true);
+
+    public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+            "5Ge",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_5ge_html,
+            TelephonyIcons.ICON_5G_E,
+            true);
+
+    public static final MobileIconGroup NR_5G = new MobileIconGroup(
+            "5G",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0,
+            0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_5g,
+            TelephonyIcons.ICON_5G,
+            true);
+
+    public static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
+            "5G_PLUS",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0,
+            0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_5g_plus,
+            TelephonyIcons.ICON_5G_PLUS,
+            true);
+
+    public static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+            "DataDisabled",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.cell_data_off_content_description,
+            0,
+            false);
+
+    public static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
+            "NotDefaultData",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.not_default_data_content_description,
+            0,
+            false);
+
+    // When adding a new MobileIconGround, check if the dataContentDescription has to be filtered
+    // in QSCarrier#hasValidTypeContentDescription
+
+    /** Mapping icon name(lower case) to the icon object. */
+    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);
+        ICON_NAME_TO_ICON.put("3g", THREE_G);
+        ICON_NAME_TO_ICON.put("wfc", WFC);
+        ICON_NAME_TO_ICON.put("unknown", UNKNOWN);
+        ICON_NAME_TO_ICON.put("e", E);
+        ICON_NAME_TO_ICON.put("1x", ONE_X);
+        ICON_NAME_TO_ICON.put("g", G);
+        ICON_NAME_TO_ICON.put("h", H);
+        ICON_NAME_TO_ICON.put("h+", H_PLUS);
+        ICON_NAME_TO_ICON.put("4g", FOUR_G);
+        ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
+        ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
+        ICON_NAME_TO_ICON.put("lte", LTE);
+        ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
+        ICON_NAME_TO_ICON.put("5g", NR_5G);
+        ICON_NAME_TO_ICON.put("5g_plus", NR_5G_PLUS);
+        ICON_NAME_TO_ICON.put("datadisable", DATA_DISABLED);
+        ICON_NAME_TO_ICON.put("notdefaultdata", NOT_DEFAULT_DATA);
+    }
+}
+
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java
index 1403631..99d2ff7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java
@@ -113,12 +113,13 @@
     private void addEmergencyNumberToTelephony() {
         final int subId = SubscriptionManager.getDefaultSubscriptionId();
         EmergencyNumber emergencyNumber = mock(EmergencyNumber.class);
+        when(emergencyNumber.isInEmergencyServiceCategories(EMERGENCY_SERVICE_CATEGORY_POLICE))
+                .thenReturn(true);
         Map<Integer, List<EmergencyNumber>> numbers = new ArrayMap<>();
         List<EmergencyNumber> numbersForSubId = new ArrayList<>();
         numbersForSubId.add(emergencyNumber);
         numbers.put(subId, numbersForSubId);
-        when(mTelephonyManager.getEmergencyNumberList(
-                EMERGENCY_SERVICE_CATEGORY_POLICE)).thenReturn(numbers);
+        when(mTelephonyManager.getEmergencyNumberList()).thenReturn(numbers);
         when(emergencyNumber.getNumber()).thenReturn(TELEPHONY_EMERGENCY_NUMBER);
     }
 }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5ad43e3..6c51f2f 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 -->
@@ -241,6 +241,12 @@
     <!-- Default for setting for Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED -->
     <bool name="def_hdmiControlAutoDeviceOff">false</bool>
 
+    <!-- Default for Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED -->
+    <bool name="def_swipe_bottom_to_notification_enabled">true</bool>
+
+    <!-- Default for Settings.Secure.ONE_HANDED_MODE_ENABLED -->
+    <bool name="def_one_handed_mode_enabled">false</bool>
+
     <!-- Default for Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY -->
     <integer name="def_accessibility_magnification_capabilities">3</integer>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 271f2a7..edb5506 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3342,7 +3342,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 195;
+            private static final int SETTINGS_VERSION = 197;
 
             private final int mUserId;
 
@@ -4786,6 +4786,35 @@
                     currentVersion = 196;
                 }
 
+                if (currentVersion == 196) {
+                    // Version 196: Set the default value for Secure Settings:
+                    // SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED & ONE_HANDED_MODE_ENABLED
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    final Setting swipeNotification = secureSettings.getSettingLocked(
+                            Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
+                    if (swipeNotification.isNull()) {
+                        final boolean defSwipeNotification = getContext().getResources()
+                                .getBoolean(R.bool.def_swipe_bottom_to_notification_enabled);
+                        secureSettings.insertSettingLocked(
+                                Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+                                defSwipeNotification ? "1" : "0", null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    final Setting oneHandedModeEnabled = secureSettings.getSettingLocked(
+                            Secure.ONE_HANDED_MODE_ENABLED);
+                    if (oneHandedModeEnabled.isNull()) {
+                        final boolean defOneHandedModeEnabled = getContext().getResources()
+                                .getBoolean(R.bool.def_one_handed_mode_enabled);
+                        secureSettings.insertSettingLocked(
+                                Secure.ONE_HANDED_MODE_ENABLED,
+                                defOneHandedModeEnabled ? "1" : "0", null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 197;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 40b0fcff..53d868a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -42,6 +42,8 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
 import android.util.Xml;
 import android.util.proto.ProtoOutputStream;
 
@@ -52,7 +54,6 @@
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -60,7 +61,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -806,13 +806,10 @@
             try {
                 out = destination.startWrite();
 
-                XmlSerializer serializer = Xml.newSerializer();
-                serializer.setOutput(out, StandardCharsets.UTF_8.name());
-                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
-                        true);
+                TypedXmlSerializer serializer = Xml.resolveSerializer(out);
                 serializer.startDocument(null, true);
                 serializer.startTag(null, TAG_SETTINGS);
-                serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+                serializer.attributeInt(null, ATTR_VERSION, version);
 
                 final int settingCount = settings.size();
                 for (int i = 0; i < settingCount; i++) {
@@ -908,7 +905,7 @@
         }
     }
 
-    static void writeSingleSetting(int version, XmlSerializer serializer, String id,
+    static void writeSingleSetting(int version, TypedXmlSerializer serializer, String id,
             String name, String value, String defaultValue, String packageName,
             String tag, boolean defaultSysSet, boolean isValuePreservedInRestore)
             throws IOException {
@@ -926,18 +923,18 @@
         if (defaultValue != null) {
             setValueAttribute(ATTR_DEFAULT_VALUE, ATTR_DEFAULT_VALUE_BASE64,
                     version, serializer, defaultValue);
-            serializer.attribute(null, ATTR_DEFAULT_SYS_SET, Boolean.toString(defaultSysSet));
+            serializer.attributeBoolean(null, ATTR_DEFAULT_SYS_SET, defaultSysSet);
             setValueAttribute(ATTR_TAG, ATTR_TAG_BASE64,
                     version, serializer, tag);
         }
         if (isValuePreservedInRestore) {
-            serializer.attribute(null, ATTR_PRESERVE_IN_RESTORE, Boolean.toString(true));
+            serializer.attributeBoolean(null, ATTR_PRESERVE_IN_RESTORE, true);
         }
         serializer.endTag(null, TAG_SETTING);
     }
 
     static void setValueAttribute(String attr, String attrBase64, int version,
-            XmlSerializer serializer, String value) throws IOException {
+            TypedXmlSerializer serializer, String value) throws IOException {
         if (version >= SETTINGS_VERSION_NEW_ENCODING) {
             if (value == null) {
                 // Null value -> No ATTR_VALUE nor ATTR_VALUE_BASE64.
@@ -956,7 +953,7 @@
         }
     }
 
-    private static void writeSingleNamespaceHash(XmlSerializer serializer, String namespace,
+    private static void writeSingleNamespaceHash(TypedXmlSerializer serializer, String namespace,
             String bannedHashCode) throws IOException {
         if (namespace == null || bannedHashCode == null) {
             return;
@@ -971,7 +968,7 @@
         return Integer.toString(keyValues.hashCode());
     }
 
-    private String getValueAttribute(XmlPullParser parser, String attr, String base64Attr) {
+    private String getValueAttribute(TypedXmlPullParser parser, String attr, String base64Attr) {
         if (mVersion >= SETTINGS_VERSION_NEW_ENCODING) {
             final String value = parser.getAttributeValue(null, attr);
             if (value != null) {
@@ -1039,8 +1036,7 @@
     @GuardedBy("mLock")
     private boolean parseStateFromXmlStreamLocked(FileInputStream in) {
         try {
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(in, StandardCharsets.UTF_8.name());
+            TypedXmlPullParser parser = Xml.resolvePullParser(in);
             parseStateLocked(parser);
             return true;
         } catch (XmlPullParserException | IOException e) {
@@ -1060,7 +1056,7 @@
         return stateFile.exists();
     }
 
-    private void parseStateLocked(XmlPullParser parser)
+    private void parseStateLocked(TypedXmlPullParser parser)
             throws IOException, XmlPullParserException {
         final int outerDepth = parser.getDepth();
         int type;
@@ -1080,10 +1076,10 @@
     }
 
     @GuardedBy("mLock")
-    private void parseSettingsLocked(XmlPullParser parser)
+    private void parseSettingsLocked(TypedXmlPullParser parser)
             throws IOException, XmlPullParserException {
 
-        mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
+        mVersion = parser.getAttributeInt(null, ATTR_VERSION);
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -1101,14 +1097,12 @@
                 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                 String defaultValue = getValueAttribute(parser, ATTR_DEFAULT_VALUE,
                         ATTR_DEFAULT_VALUE_BASE64);
-                String isPreservedInRestoreString = parser.getAttributeValue(null,
-                        ATTR_PRESERVE_IN_RESTORE);
-                boolean isPreservedInRestore = Boolean.parseBoolean(isPreservedInRestoreString);
+                boolean isPreservedInRestore = parser.getAttributeBoolean(null,
+                        ATTR_PRESERVE_IN_RESTORE, false);
                 String tag = null;
                 boolean fromSystem = false;
                 if (defaultValue != null) {
-                    fromSystem = Boolean.parseBoolean(parser.getAttributeValue(
-                            null, ATTR_DEFAULT_SYS_SET));
+                    fromSystem = parser.getAttributeBoolean(null, ATTR_DEFAULT_SYS_SET, false);
                     tag = getValueAttribute(parser, ATTR_TAG, ATTR_TAG_BASE64);
                 }
                 mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
@@ -1122,7 +1116,7 @@
     }
 
     @GuardedBy("mLock")
-    private void parseNamespaceHash(XmlPullParser parser)
+    private void parseNamespaceHash(TypedXmlPullParser parser)
             throws IOException, XmlPullParserException {
 
         final int outerDepth = parser.getDepth();
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index 9f448af..69eb713 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -17,15 +17,13 @@
 
 import android.os.Looper;
 import android.test.AndroidTestCase;
+import android.util.TypedXmlSerializer;
 import android.util.Xml;
 
-import org.xmlpull.v1.XmlSerializer;
-
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
 
 public class SettingsStateTest extends AndroidTestCase {
     public static final String CRAZY_STRING =
@@ -93,9 +91,7 @@
     public void testWriteReadNoCrash() throws Exception {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
 
-        XmlSerializer serializer = Xml.newSerializer();
-        serializer.setOutput(os, StandardCharsets.UTF_8.name());
-        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+        TypedXmlSerializer serializer = Xml.resolveSerializer(os);
         serializer.startDocument(null, true);
 
         for (int ch = 0; ch < 0x10000; ch++) {
@@ -118,12 +114,12 @@
                 serializer, "1", "k", "v", null, null, null, false, false);
     }
 
-    private void checkWriteSingleSetting(XmlSerializer serializer, String key, String value)
+    private void checkWriteSingleSetting(TypedXmlSerializer serializer, String key, String value)
             throws Exception {
         checkWriteSingleSetting(key + "/" + value, serializer, key, value);
     }
 
-    private void checkWriteSingleSetting(String msg, XmlSerializer serializer,
+    private void checkWriteSingleSetting(String msg, TypedXmlSerializer serializer,
             String key, String value) throws Exception {
         // Make sure the XML serializer won't crash.
         SettingsState.writeSingleSetting(
diff --git a/packages/SharedStorageBackup/OWNERS b/packages/SharedStorageBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/SharedStorageBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 7b1257b0..7ea9686 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" />
@@ -181,6 +182,8 @@
     <!-- Permissions needed to test system only camera devices -->
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.SYSTEM_CAMERA" />
+      <!-- Permissions needed to test onCameraOpened/Closed callbacks -->
+    <uses-permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" />
     <!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id -->
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <!-- Permission needed to enable/disable Bluetooth/Wifi -->
@@ -362,6 +365,12 @@
     <!-- Permissions required for CTS tests to close system dialogs -->
     <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
 
+    <!-- Permission required for CTS test - HideOverlayWindowsTest -->
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+
+    <!-- Permission required for CTS test - CtsHdmiCecHostTestCases -->
+    <uses-permission android:name="android.permission.HDMI_CEC" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index d50f08d..a2608a0 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -380,6 +380,11 @@
         public void onFinished() {
             mInfo.renameBugreportFile();
             mInfo.renameScreenshots();
+            if (mInfo.bugreportFile.length() == 0) {
+                Log.e(TAG, "Bugreport file empty. File path = " + mInfo.bugreportFile);
+                onError(BUGREPORT_ERROR_RUNTIME);
+                return;
+            }
             synchronized (mLock) {
                 sendBugreportFinishedBroadcastLocked();
                 mMainThreadHandler.post(() -> mInfoDialog.onBugreportFinished(mInfo));
@@ -408,10 +413,6 @@
         @GuardedBy("mLock")
         private void sendBugreportFinishedBroadcastLocked() {
             final String bugreportFilePath = mInfo.bugreportFile.getAbsolutePath();
-            if (mInfo.bugreportFile.length() == 0) {
-                Log.e(TAG, "Bugreport file empty. File path = " + bugreportFilePath);
-                return;
-            }
             if (mInfo.type == BugreportParams.BUGREPORT_MODE_REMOTE) {
                 sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath,
                         mInfo.bugreportFile);
@@ -617,12 +618,21 @@
 
         BugreportInfo info = new BugreportInfo(mContext, baseName, name,
                 shareTitle, shareDescription, bugreportType, mBugreportsDir);
+        synchronized (mLock) {
+            if (info.bugreportFile.exists()) {
+                Log.e(TAG, "Failed to start bugreport generation, the requested bugreport file "
+                        + info.bugreportFile + " already exists");
+                return;
+            }
+            info.createBugreportFile();
+        }
         ParcelFileDescriptor bugreportFd = info.getBugreportFd();
         if (bugreportFd == null) {
             Log.e(TAG, "Failed to start bugreport generation as "
                     + " bugreport parcel file descriptor is null.");
             return;
         }
+        info.createScreenshotFile(mBugreportsDir);
         ParcelFileDescriptor screenshotFd = null;
         if (isDefaultScreenshotRequired(bugreportType, /* hasScreenshotButton= */ !mIsTv)) {
             screenshotFd = info.getDefaultScreenshotFd();
@@ -1919,12 +1929,10 @@
             this.shareDescription = shareDescription == null ? "" : shareDescription;
             this.type = type;
             this.baseName = baseName;
-            createBugreportFile(bugreportsDir);
-            createScreenshotFile(bugreportsDir);
+            this.bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
         }
 
-        void createBugreportFile(File bugreportsDir) {
-            bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
+        void createBugreportFile() {
             createReadWriteFile(bugreportFile);
         }
 
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 3b02e3b..9476912 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -40,6 +40,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
@@ -513,6 +514,17 @@
     }
 
     @Test
+    public void testBugreportFinished_withEmptyBugreportFile() throws Exception {
+        sendBugreportStarted();
+
+        IoUtils.closeQuietly(mBugreportFd);
+        mBugreportFd = null;
+        sendBugreportFinished();
+
+        assertServiceNotRunning();
+    }
+
+    @Test
     public void testShareBugreportAfterServiceDies() throws Exception {
         sendBugreportStarted();
         waitForScreenshotButtonEnabled(true);
@@ -523,6 +535,18 @@
         assertActionSendMultiple(extras);
     }
 
+    @Test
+    public void testBugreportRequestTwice_oneStartBugreportInvoked() throws Exception {
+        sendBugreportStarted();
+        new BugreportRequestedReceiver().onReceive(mContext,
+                new Intent(INTENT_BUGREPORT_REQUESTED));
+        getInstrumentation().waitForIdleSync();
+
+        verify(mMockIDumpstate, times(1)).startBugreport(anyInt(), any(), any(), any(),
+                anyInt(), any(), anyBoolean());
+        sendBugreportFinished();
+    }
+
     private void cancelExistingNotifications() {
         // Must kill service first, because notifications from a foreground service cannot be
         // canceled.
@@ -576,9 +600,10 @@
      */
     private void sendBugreportStarted() throws Exception {
         Intent intent = new Intent(INTENT_BUGREPORT_REQUESTED);
-        intent.setPackage("com.android.shell");
-        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        mContext.sendBroadcast(intent);
+        // Ideally, we should invoke BugreportRequestedReceiver by sending
+        // INTENT_BUGREPORT_REQUESTED. But the intent has been protected broadcast by the system
+        // starting from S.
+        new BugreportRequestedReceiver().onReceive(mContext, intent);
 
         ArgumentCaptor<IDumpstateListener> listenerCap = ArgumentCaptor.forClass(
                 IDumpstateListener.class);
@@ -646,7 +671,9 @@
      * Callbacks to service to finish the bugreport.
      */
     private void sendBugreportFinished() throws Exception {
-        writeZipFile(mBugreportFd, BUGREPORT_FILE, BUGREPORT_CONTENT);
+        if (mBugreportFd != null) {
+            writeZipFile(mBugreportFd, BUGREPORT_FILE, BUGREPORT_CONTENT);
+        }
         if (mScreenshotFd != null) {
             writeScreenshotFile(mScreenshotFd, SCREENSHOT_CONTENT);
         }
diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp
index ae37efc..2664a03 100644
--- a/packages/StatementService/Android.bp
+++ b/packages/StatementService/Android.bp
@@ -21,6 +21,7 @@
     platform_apis: true,
     privileged: true,
     libs: ["org.apache.http.legacy"],
+    uses_libs: ["org.apache.http.legacy"],
     static_libs: [
         "libprotobuf-java-nano",
         "volley",
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 2ea0c22..fda1e36 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -74,6 +74,7 @@
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx-constraintlayout_constraintlayout",
+        "androidx.exifinterface_exifinterface",
         "kotlinx-coroutines-android",
         "kotlinx-coroutines-core",
         "iconloader_base",
@@ -140,6 +141,7 @@
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx-constraintlayout_constraintlayout",
+        "androidx.exifinterface_exifinterface",
         "kotlinx-coroutines-android",
         "kotlinx-coroutines-core",
         "iconloader_base",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2da958f..070c021 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -103,6 +103,7 @@
     <uses-permission android:name="android.permission.START_ACTIVITY_AS_CALLER" />
     <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
+    <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
 
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -390,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"
@@ -569,14 +570,10 @@
         <!-- People Space UI Screen -->
         <activity android:name=".people.PeopleSpaceActivity"
             android:label="People"
-            android:icon="@drawable/ic_music_note"
             android:exported="true"
-            android:enabled="false"
-            android:theme="@android:style/Theme.Material.NoActionBar"
-            android:launchMode="singleInstance">
+            android:theme="@android:style/Theme.Material.NoActionBar">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
             </intent-filter>
         </activity>
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index 6e86f26..4fc1973 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -60,8 +60,8 @@
      * Returns true if the last two gestures do not look like a double tap.
      *
      * Only works on data that has already been reported to the FalsingManager. Be sure that
-     * {@link #onTouchEvent(MotionEvent, int, int)} has already been called for all of the
-     * taps you want considered.
+     * {@link com.android.systemui.classifier.FalsingCollector#onTouchEvent(MotionEvent)}
+     * has already been called for all of the taps you want considered.
      *
      * This looks at the last two gestures on the screen, ensuring that they meet the following
      * criteria:
@@ -85,8 +85,6 @@
 
     boolean isReportingEnabled();
 
-    void onTouchEvent(MotionEvent ev, int width, int height);
-
     /** From com.android.systemui.Dumpable. */
     void dump(FileDescriptor fd, PrintWriter pw, String[] args);
 
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-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 276fa23..6f23f8c 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeer tans vir batterygesondheid"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Koppel jou laaier."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index ae5d1f6..62f9554 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ለባትሪ ጤና ማመቻቸት"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ኃይል መሙያዎን ያያይዙ።"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index fb03fe3..459d162 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • التحسين لسلامة البطارية"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"توصيل جهاز الشحن."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 8e8b13d..84a8afa 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"আপোনাৰ চ্চার্জাৰ সংযোগ কৰক।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index f9bff73..e184679 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerjiyə qənaət üçün optimallaşdırma"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Adapteri qoşun."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 3434ac6..3468740 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuje se radi dobrog stanja baterije"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 07d682f..4f8ce16 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Аптымізацыя стану акумулятара"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Падключыце зарадную прыладу."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 3890c11..0911efa 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизиране за състоянието на батерията"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Свържете зарядното си устройство."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index f916374..0c878b6 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 59a881d..83ad38c 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi očuvanja baterije"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 82d63c1..421ddb6 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està optimitzant per mantenir el bon estat de la bateria"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Connecta el carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index a4e653f..855d3f0 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizace pro výdrž baterie"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Připojte dobíjecí zařízení."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 604852c..b5955c7 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerer batteritilstanden"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Tilslut din oplader."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 0e2ea13..d700df3 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimierung des Akkuzustands"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 90e2550..b305698 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Βελτιστοποίηση για τη διατήρηση της καλής κατάστασης της μπαταρίας"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 7b0c638..54c1a2b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 2ef720e..d8591e2 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 7b0c638..54c1a2b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 7b0c638..54c1a2b 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index 471ef8b..30f47d2 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Battery limited temporarily‎‏‎‎‏‎"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Optimizing for battery health‎‏‎‎‏‎"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎Connect your charger.‎‏‎‎‏‎"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎Press Menu to unlock.‎‏‎‎‏‎"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎Network locked‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index a5750b5..4ea99cc 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se está optimizando el estado de la batería"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta tu cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 69488da..b7384c5e 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para preservar el estado de la batería"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta el cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index 948e134..a01d30d 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeerimine aku seisukorra põhjal"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Ühendage laadija."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index b1aa206..ce8ef20 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizatzen bateria egoera onean mantentzeko"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Konektatu kargagailua."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 8fecdd3..61e2e1f 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بهینه‌سازی برای سلامت باتری"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"شارژر را وصل کنید."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index c47de5d..021de77 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akun kunnon optimointi"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Kytke laturi."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index b330452..f215625 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation en fonction de la santé de la pile"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
@@ -67,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>
@@ -91,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>
@@ -119,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 0c13c0f..3e52f50 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation pour préserver la batterie"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
@@ -67,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>
@@ -91,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>
@@ -119,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-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 601b2e2..01a0fac 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para manter a batería en bo estado"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta o cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index 296124f..8ec7ba5 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index c1c9dd5..5869078 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्‍ट करें."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index 1b51b33..7e06973 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi zdravlja baterije"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 4dcb229..e6c10d8 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Az akkumulátor élettartamának optimalizálása…"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Csatlakoztassa a töltőt."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 354d932..c8ed16d 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Օպտիմալացվում է մարտկոցի աշխատանքային հզորության համար"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Միացրեք լիցքավորիչը:"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index d43823c..696f215 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengoptimalkan untuk kesehatan baterai"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index 233402b..3f3bec9 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Fínstillir til að bæta rafhlöðuendingu"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Tengdu hleðslutækið."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 87fd81c..47d17ce 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batteria momentaneamente limitata"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • È in corso l\'ottimizzazione per l\'integrità della batteria"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Collega il caricabatterie."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 6af70b4..8780dc5 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • מופעלת אופטימיזציה לשמירה על תקינות הסוללה"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"חבר את המטען."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index ab5a13c..b4aea61 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 電池の状態を最適化"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index b10ab61..7e1e59b 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ბატარეა დროებით შეზღუდულია"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ოპტიმიზაცია ბატარეის გამართულობისთვის"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index c415bbb..b20cb05 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Зарядтағышты қосыңыз."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 1a278e8..fb38bfd 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្ម"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងបង្កើនប្រសិទ្ធភាព​គុណភាពថ្ម"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាក​ថ្ម​របស់​អ្នក។"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ​ដើម្បី​ដោះ​សោ។"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញ​ជាប់​សោ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 961fcec..a527123 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್‌ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 2f93af9..7149cdf 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 상태 최적화 중"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"충전기를 연결하세요."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 7e92919..5327c01 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареянын кубатын үнөмдөө иштетилди"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Кубаттагычка туташтырыңыз."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index b96a2bb..0f662c3 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 773f7c4..cc8cdfd 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuojama siekiant apsaugoti akumuliatorių"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Prijunkite kroviklį."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 68bf4cd..d6fdfaf 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akumulatora darbības optimizēšana"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Pievienojiet uzlādes ierīci."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index e51f774..66744e7 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се оптимизира за состојба на батерија"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Поврзете го полначот."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 4b43914..66d0ac7 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്‌വർക്ക് ലോക്കുചെയ്‌തു"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 4667252..2ff4a22 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейн чанарыг оновчилж байна"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index bdd3904..e2ffc62 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"तुमचा चार्जर कनेक्ट करा."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index a517988..dcd460b 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengoptimuman untuk kesihatan bateri"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 07f3d38..bbeadd0 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"အားသွင်းကိရိယာကို ချိတ်ဆက်ပါ။"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index a391b92..8a3045a 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliserer batteritilstanden"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Koble til en batterilader."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 812aa38..6f8a108 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"तपाईंको चार्जर जोड्नुहोस्।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index f1c2033..a9fd827 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliseren voor batterijduur"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Sluit de oplader aan."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index be6e285..385c13b 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ଆପଣଙ୍କ ଚାର୍ଜର୍‍ ସଂଯୋଗ କରନ୍ତୁ।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍‌ କରାଯାଇଛି"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index a6ea6aa..43d549c 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ  ਲਾਕ  ਕੀਤਾ ਗਿਆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 9c6f271..76f755c 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optymalizuję, by utrzymać baterię w dobrym stanie"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Podłącz ładowarkę."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index d2d5fb9..29c46f8 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 7f0a4d88..b15c9dc 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente."</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A otimizar o estado da bateria"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Ligue o carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index d2d5fb9..29c46f8 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 572c1db..868d9f7 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se fac optimizări pentru buna funcționare a bateriei"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Conectați încărcătorul."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 2c87608..24d762d 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизация для увеличения срока службы батареи"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Подключите зарядное устройство."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 8682192..3a60782 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරි සෞඛ්‍යය සඳහා ප්‍රශස්ත කරමින්"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index d5e6093..98aa79a 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizuje sa na zaistenie dobrého stavu batérie"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Pripojte nabíjačku."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 82d5c54..cd41d9b 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizacija za ohranjanje zmogljivosti baterije"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index a67413fd..0ad97a4 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po optimizohet për integritetin e baterisë"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Lidh karikuesin."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index dec3165..90b8a3e 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизује се ради доброг стања батерије"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Прикључите пуњач."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 3ef2dfe..80323e6 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerar batteriets livslängd"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Anslut laddaren."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 5c5fc10..da35262 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inaboresha muda wa kutumia betri"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index c188301..ca92577 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"திறக்க, மெனுவை அழுத்தவும்."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 27a5b28..c69a8f5 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీ జీవితకాలాన్ని ఆప్టిమైజ్ చేయడం కోసం"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్‌ను కనెక్ట్ చేయండి."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్‌లాక్ చేయడానికి మెనుని నొక్కండి."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్‌వర్క్ లాక్ చేయబడింది"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index e506745..4fd3dd1 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"เสียบที่ชาร์จของคุณ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 912fd95..8f26ea9 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ino-optimize para sa tagal ng baterya"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Ikonekta ang iyong charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 5390c4c..53a1cc7 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pil sağlığı için optimize ediliyor"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Şarj cihazınızı takın."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 6263d79..a16576d 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Стан акумулятора оптимізується"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Підключіть зарядний пристрій."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index bf936cb..a14f20d 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی صحت کے لیے بہتر بنایا جا رہا ہے"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"اپنا چارجر منسلک کریں۔"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 0b23e16..24a14c7 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareya quvvati muvozanatlanmoqda"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Quvvatlash moslamasini ulang."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 9357eba..3221066 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang tối ưu hóa để cải thiện độ bền của pin"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 96728ab..a3921d0 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在针对电池状况进行优化"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"请连接充电器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index c683529..1054e36 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在優化電池狀態"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 7a3b5c5..7efa2f9 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 針對電池狀態進行最佳化調整"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index ec38cbe..d87622a 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -38,8 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
-    <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ilungiselela impilo yebhethri"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Xhuma ishaja yakho."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
diff --git a/packages/SystemUI/res/color/camera_foreground.xml b/packages/SystemUI/res/color/camera_foreground.xml
new file mode 100644
index 0000000..6e039cc
--- /dev/null
+++ b/packages/SystemUI/res/color/camera_foreground.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false"
+        android:color="@color/control_default_foreground" />
+  <item android:color="@color/GM2_grey_100" />
+</selector>
diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SystemUI/res/color/qs_background_dark.xml
deleted file mode 100644
index c47959a..0000000
--- a/packages/SystemUI/res/color/qs_background_dark.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="1"
-          android:color="?android:attr/colorBackground"/>
-</selector>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 43c9b73..4b225b7 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,6 +15,6 @@
   ~ limitations under the License
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/qs_background_dark" />
+    <solid android:color="?android:attr/colorBackgroundFloating" />
     <corners android:radius="8dp" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
index ca56ec1..108591b 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
@@ -16,6 +16,27 @@
   -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android"
             android:paddingMode="stack">
+    <item android:id="@android:id/background"
+        android:gravity="center_vertical|fill_horizontal">
+        <layer-list >
+            <item>
+                <shape
+                    android:tint="?android:attr/colorControlActivated"
+                    android:alpha="?android:attr/disabledAlpha">
+                    <size android:height="48dp" />
+                    <solid android:color="@color/white_disabled" />
+                    <corners android:radius="24dp" />
+                </shape>
+            </item>
+            <item
+                android:gravity="center_vertical|start"
+                android:start="32dp">
+                <com.android.systemui.util.AlphaTintDrawableWrapper
+                    android:drawable="@drawable/ic_brightness"
+                    android:tint="?android:attr/colorControlActivated" />
+            </item>
+        </layer-list>
+    </item>
     <item android:id="@android:id/progress"
           android:gravity="center_vertical|fill_horizontal">
         <clip
@@ -24,13 +45,4 @@
             android:gravity="left"
         />
     </item>
-    <item android:id="@android:id/background"
-          android:gravity="center_vertical|fill_horizontal">
-        <shape android:shape="rectangle"
-               android:tint="?android:attr/colorControlNormal">
-            <size android:height="48dp" />
-            <solid android:color="@color/white_disabled" />
-            <corners android:radius="24dp" />
-        </shape>
-    </item>
 </layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index a38b8b4..b5def5e 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -15,10 +15,21 @@
   ~ limitations under the License.
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle"
-       android:tint="?android:attr/colorControlActivated">
-    <size android:height="48dp" />
-    <solid android:color="@android:color/white" />
-    <corners android:radius="24dp"/>
-</shape>
\ No newline at end of file
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/slider_foreground">
+        <shape>
+            <size android:height="48dp" />
+            <solid android:color="?android:attr/colorControlActivated" />
+            <corners android:radius="24dp"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/slider_icon"
+        android:gravity="center_vertical|start"
+        android:start="32dp">
+        <com.android.systemui.util.AlphaTintDrawableWrapper
+            android:drawable="@drawable/ic_brightness"
+            android:tint="?android:attr/colorBackground"
+            android:alpha="0.8"/>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
index 55116c6..9f66581 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
@@ -19,8 +19,8 @@
         <shape android:shape="rectangle">
             <solid android:color="@color/magnification_switch_button_color" />
             <size
-                android:width="40dp"
-                android:height="40dp" />
+                android:width="48dp"
+                android:height="48dp" />
         </shape>
     </item>
 
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
index 5f571cf..659b020 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
@@ -19,8 +19,8 @@
         <shape android:shape="rectangle">
             <solid android:color="@color/magnification_switch_button_color" />
             <size
-                android:width="40dp"
-                android:height="40dp" />
+                android:width="48dp"
+                android:height="48dp" />
         </shape>
     </item>
 
diff --git a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
index 339cb70..c41d102 100644
--- a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
+++ b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
@@ -18,7 +18,8 @@
         android:width="16dp"
         android:height="16dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="#FF000000"
         android:pathData="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
index 71376d5..c6d133a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
@@ -19,7 +19,7 @@
         android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M20.5,6c-2.61,0.7 -5.67,1 -8.5,1s-5.89,-0.3 -8.5,-1L3,8c1.86,0.5 4,0.83 6,1v13h2v-6h2v6h2V9c2,-0.17 4.14,-0.5 6,-1l-0.5,-2zM12,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index 771b466..6fc2f20 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -17,7 +17,8 @@
     android:height="24dp"
     android:width="24dp"
     android:viewportHeight="24"
-    android:viewportWidth="24">
+    android:viewportWidth="24"
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="#FFFFFF"
         android:pathData="M13,8h-2v5.41l3.79,3.8 1.42,-1.42 -3.21,-3.2zM12,4c-4.97,0 -9,4.03 -9,9s4.03,9 9,9 9,-4.03 9,-9 -4.03,-9 -9,-9zM12,20c-3.86,0 -7,-3.14 -7,-7s3.14,-7 7,-7 7,3.14 7,7 -3.14,7 -7,7zM16.056,3.346l1.282,-1.535 4.607,3.85 -1.28,1.54zM2.056,5.654L6.663,1.81l1.28,1.536L3.338,7.19z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 18e2736..730c26f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index b0b9404..9ed77fe 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index 99be7b6..bffb5a4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 23cb206..ea467c6 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -18,7 +18,7 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal">
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="@android:color/white"
         android:pathData="M9 3l0.01 10.55c-0.6-0.34-1.28-0.55-2-0.55C4.79 13 3 14.79 3 17s1.79 4 4.01 4S11 19.21 11 17V7h4V3H9zm12 9.43L17.57 9h-0.6v4.55l-2.75-2.75-0.85 0.85 L16.73 15l-3.35 3.35 0.85 0.85 2.75-2.75V21h0.6L21 17.57 18.42 15 21 12.43zm-2.83-1.13l1.13 1.13-1.13 1.13V11.3zm1.13 6.27l-1.13 1.13v-2.26l1.13 1.13z" />
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 2469ddc..f01e49f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -18,7 +18,7 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal">
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="@android:color/white"
         android:pathData="M9 6.17V3h6v4h-4v1.17l-2-2zM19.42 15L22 17.57l-0.8 0.8 -6.78-6.78 0.8 -0.8 2.75 2.75V9h0.6L22 12.43 19.42 15zm-0.25-1.45l1.13-1.13-1.13-1.13v2.26zm-1.96 3.66l3.98 3.98-1.41 1.41-3.98-3.98-0.58 0.58 -0.85-0.85 0.58 -0.58L11 13.83V17c0 2.21-1.78 4-3.99 4S3 19.21 3 17s1.79-4 4.01-4c0.73 0 1.41 0.21 2 0.55v-1.72L1.39 4.22 2.8 2.81l13.56 13.56 0.85 0.84z" />
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index 3a495963..63dfe8f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
index 719b702..946c137 100644
--- a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
@@ -17,7 +17,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="#FF000000"
         android:pathData="M20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,6h16v12zM6,10h2v2L6,12zM6,14h8v2L6,16zM16,14h2v2h-2zM10,10h8v2h-8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
index 953d4fe..5af38e4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
@@ -17,7 +17,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/textColorPrimary">
     <path
         android:fillColor="#FF000000"
         android:pathData="M18,10l-5.18,0l2,2l3.18,0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index 42eb7b7..998344f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -18,7 +18,7 @@
     android:width="24dp"
     android:viewportHeight="24"
     android:viewportWidth="24"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index 9cb7ca3..064e239 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24"
     android:viewportWidth="24"
     android:width="24dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index 314e06c..b18e0a7 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -17,7 +17,8 @@
     android:height="19dp"
     android:width="19dp"
     android:viewportHeight="24.0"
-    android:viewportWidth="24.0">
+    android:viewportWidth="24.0"
+    android:tint="?android:attr/textColorPrimary">
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_system.xml b/packages/SystemUI/res/drawable/ic_volume_system.xml
index 71eed34..ad3d881 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
index baad92a..c68f587 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
index 7dc3dac..3e7748a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_voice.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_voice.xml
@@ -18,7 +18,7 @@
     android:viewportHeight="48.0"
     android:viewportWidth="48.0"
     android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:tint="?android:attr/textColorPrimary" >
 
     <path
         android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/people_space_activity_card.xml b/packages/SystemUI/res/drawable/people_space_activity_card.xml
new file mode 100644
index 0000000..81162d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_activity_card.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorAccent" />
+    <corners android:radius="@dimen/people_space_widget_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_content_background.xml b/packages/SystemUI/res/drawable/people_space_content_background.xml
new file mode 100644
index 0000000..53108409
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_content_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+    <solid android:color="?android:attr/colorControlHighlight" />
+    <corners android:radius="@dimen/people_space_widget_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml
new file mode 100644
index 0000000..59af775
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_round_tile_view_card.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorBackground" />
+    <corners android:radius="@dimen/people_space_widget_round_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_rounded_border.xml b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
new file mode 100644
index 0000000..9956bc2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_rounded_border.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="?android:attr/colorBackground" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
index 4772ae7..8fd4388 100644
--- a/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
+++ b/packages/SystemUI/res/drawable/people_space_tile_view_card.xml
@@ -14,6 +14,6 @@
   ~ limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@android:color/white" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners android:radius="@dimen/people_space_widget_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/people_space_widget_background.xml b/packages/SystemUI/res/drawable/people_space_widget_background.xml
index b929359..fa45718 100644
--- a/packages/SystemUI/res/drawable/people_space_widget_background.xml
+++ b/packages/SystemUI/res/drawable/people_space_widget_background.xml
@@ -18,7 +18,7 @@
     android:shape="rectangle" >
     <solid
         android:color="?android:attr/colorControlNormal" />
-    <corners android:radius="@dimen/people_space_widget_radius" />
+    <corners android:radius="@dimen/people_space_widget_background_padding" />
     <padding
         android:left="@dimen/people_space_widget_background_padding"
         android:top="@dimen/people_space_widget_background_padding"
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
deleted file mode 100644
index dd74cadd..0000000
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
-    <shape>
-        <solid android:color="@color/qs_background_dark"/>
-        <corners android:radius="?android:attr/dialogCornerRadius" />
-    </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
index 215dee4..c2d0841 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
@@ -15,7 +15,7 @@
 -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android">
     <shape>
-        <solid android:color="@color/qs_customize_background"/>
+        <solid android:color="?android:attr/colorBackgroundFloating"/>
         <corners android:radius="?android:attr/dialogCornerRadius" />
     </shape>
 </inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
index 648d45b..7cb44b3 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
@@ -15,7 +15,7 @@
 -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android">
     <shape>
-        <solid android:color="@color/qs_customize_background"/>
+        <solid android:color="?android:attr/colorBackgroundFloating"/>
         <corners
             android:topLeftRadius="?android:attr/dialogCornerRadius"
             android:topRightRadius="?android:attr/dialogCornerRadius" />
diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml
index 672abf1..76045e4 100644
--- a/packages/SystemUI/res/drawable/qs_detail_background.xml
+++ b/packages/SystemUI/res/drawable/qs_detail_background.xml
@@ -25,7 +25,7 @@
     <item>
         <inset>
             <shape>
-                <solid android:color="?android:attr/colorPrimary"/>
+                <solid android:color="?android:attr/colorBackgroundFloating"/>
                 <corners android:radius="?android:attr/dialogCornerRadius" />
             </shape>
         </inset>
diff --git a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
index 509cd1f..59dad0e 100644
--- a/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
+++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
@@ -17,6 +17,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle" >
     <solid
-        android:color="#e5e5e5" />
+        android:color="?android:attr/textColorPrimary" />
     <corners android:radius="2dp" />
 </shape>
diff --git a/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml
new file mode 100644
index 0000000..953a29e
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/global_actions_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+  <LinearLayout
+      android:layout_weight="1"
+      android:layout_height="match_parent"
+      android:layout_width="0dp"
+      android:clipChildren="false"
+      android:orientation="vertical"
+      android:clipToPadding="false"
+      android:id="@+id/controls_pane"
+      >
+        <LinearLayout
+            android:id="@+id/global_actions_controls"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"/>
+  </LinearLayout>
+
+  <LinearLayout
+      android:layout_weight="1"
+      android:layout_height="match_parent"
+      android:layout_width="0dp"
+      android:orientation="vertical"
+      android:id="@+id/nfc_pane"
+      >
+    <include layout="@layout/global_actions_view" />
+
+    <include layout="@layout/global_actions_lock_view" />
+
+      <LinearLayout
+          android:id="@+id/global_actions_grid_root"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:clipChildren="false"
+          android:orientation="vertical"
+          android:clipToPadding="false">
+
+        <FrameLayout
+            android:id="@+id/global_actions_wallet"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+
+      </LinearLayout>
+
+  </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml
new file mode 100644
index 0000000..ef49b9c
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.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.
+  -->
+
+<com.android.systemui.globalactions.MinHeightScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:scrollbars="none">
+  <LinearLayout
+      android:id="@+id/global_actions_controls_list"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:orientation="vertical"
+      android:layout_marginLeft="@dimen/global_actions_side_margin"
+      android:layout_marginRight="@dimen/global_actions_side_margin" />
+</com.android.systemui.globalactions.MinHeightScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml
new file mode 100644
index 0000000..6ffcef7
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/global_actions_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+  <LinearLayout
+      android:layout_weight="1"
+      android:layout_height="0dp"
+      android:layout_width="match_parent"
+      android:orientation="vertical"
+      android:id="@+id/nfc_pane"
+      >
+
+    <include layout="@layout/global_actions_view" />
+
+    <include layout="@layout/global_actions_lock_view" />
+
+
+    <com.android.systemui.globalactions.MinHeightScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:scrollbars="none">
+
+      <LinearLayout
+          android:id="@+id/global_actions_grid_root"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:clipChildren="false"
+          android:orientation="vertical"
+          android:clipToPadding="false">
+
+        <FrameLayout
+            android:id="@+id/global_actions_wallet"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+
+      </LinearLayout>
+    </com.android.systemui.globalactions.MinHeightScrollView>
+
+  </LinearLayout>
+
+  <LinearLayout
+      android:layout_weight="1"
+      android:layout_height="0dp"
+      android:layout_width="match_parent"
+      android:orientation="vertical"
+      android:id="@+id/controls_pane"
+      android:clipToPadding="false"
+      android:clipChildren="false">
+        <LinearLayout
+            android:id="@+id/global_actions_controls"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"/>
+  </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index 065ff68..b060afd 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -58,11 +58,5 @@
         android:background="?android:attr/selectableItemBackgroundBorderless" />
   </LinearLayout>
 
-  <LinearLayout
-      android:id="@+id/global_actions_controls_list"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:orientation="vertical"
-      android:layout_marginLeft="@dimen/global_actions_side_margin"
-      android:layout_marginRight="@dimen/global_actions_side_margin" />
+  <include layout="@layout/global_actions_controls_list_view" />
 </merge>
diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml
index 7047c1b..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"
@@ -109,24 +108,4 @@
             style="@style/TextAppearance.NotificationInfo.Button"/>
     </LinearLayout>
 
-    <!-- Done button -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/notification_guts_button_spacing"
-        android:layout_marginBottom="@dimen/notification_guts_button_spacing"
-        android:gravity="end"
-        android:orientation="horizontal">
-
-        <TextView
-            android:id="@+id/ok"
-            android:text="@string/feedback_ok"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:background="@drawable/ripple_drawable"
-            android:minWidth="48dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="-8dp"
-            style="@style/TextAppearance.NotificationInfo.Button"/>
-    </LinearLayout>
 </com.android.systemui.statusbar.notification.row.FeedbackInfo>
diff --git a/packages/SystemUI/res/layout/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml
new file mode 100644
index 0000000..e1c2611
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/global_actions_controls_list"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:layout_marginLeft="@dimen/global_actions_side_margin"
+    android:layout_marginRight="@dimen/global_actions_side_margin" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
index 99b9ced..14a5e58 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
@@ -18,7 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="0dp"
     android:layout_weight="1"
-    android:layout_height="98dp"
+    android:layout_height="@dimen/global_actions_grid_item_layout_height"
     android:gravity="bottom|center_horizontal"
     android:orientation="vertical"
     android:paddingTop="12dp"
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_activity.xml b/packages/SystemUI/res/layout/people_space_activity.xml
index 67ecdaa..07af01b 100644
--- a/packages/SystemUI/res/layout/people_space_activity.xml
+++ b/packages/SystemUI/res/layout/people_space_activity.xml
@@ -17,8 +17,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/scroll"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@android:color/holo_blue_light">
+    android:layout_height="match_parent">
 
     <LinearLayout
         android:id="@+id/people_space_layout"
@@ -30,16 +29,15 @@
         android:clipChildren="false"
         android:clipToPadding="false">
 
-        <ImageView
-            android:id="@+id/people_space_cloud"
-            android:layout_width="67dp"
-            android:layout_height="67dp"
+        <TextView
+            android:id="@+id/select_conversation"
+            android:text="@string/select_conversation_text"
+            android:layout_width="match_parent"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+            android:textSize="24sp"
+            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            android:scaleType="fitCenter"
-            android:focusable="false"
-            android:paddingBottom="16dp"
-            android:tint="?android:attr/colorControlNormal"
-            android:src="@drawable/cloud" />
+            android:paddingBottom="16dp" />
 
     </LinearLayout>
 </androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml
new file mode 100644
index 0000000..e9f3424
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_large_avatar_tile.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <LinearLayout
+        android:background="@drawable/people_space_round_tile_view_card"
+        android:id="@+id/item"
+        android:paddingVertical="6dp"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:paddingStart="12dp"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+                <ImageView
+                    android:id="@+id/person_icon"
+                    android:layout_width="60dp"
+                    android:layout_height="60dp" />
+
+                <LinearLayout
+                    android:background="@drawable/people_space_rounded_border"
+                    android:layout_marginStart="-12dp"
+                    android:layout_marginTop="28dp"
+                    android:layout_marginBottom="14dp"
+                    android:layout_width="16dp"
+                    android:layout_height="16dp">
+
+                    <ImageView
+                        android:id="@+id/package_icon"
+                        android:layout_width="12dp"
+                        android:layout_marginStart="2dp"
+                        android:layout_marginEnd="2dp"
+                        android:layout_marginBottom="2dp"
+                        android:layout_marginTop="2dp"
+                        android:layout_height="12dp" />
+                </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:paddingStart="8dp"
+                android:paddingEnd="12dp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:ellipsize="end"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/status"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="3dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLines="3"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
new file mode 100644
index 0000000..5aa0533
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <RelativeLayout
+        android:background="@drawable/people_space_tile_view_card"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="start">
+            <TextView
+                android:id="@+id/punctuation1"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="5dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="350" />
+            <TextView
+                android:id="@+id/punctuation2"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="25dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="5" />
+            <TextView
+                android:id="@+id/punctuation3"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="5dp"
+                android:layout_marginStart="25dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="355"/>
+            <TextView
+                android:id="@+id/punctuation4"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-5dp"
+                android:layout_marginStart="25dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="10" />
+            <TextView
+                android:id="@+id/punctuation5"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="5dp"
+                android:layout_marginStart="25dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="15" />
+            <TextView
+                android:id="@+id/punctuation6"
+                android:textColor="?android:attr/textColorSecondary"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="36sp"
+                android:textStyle="bold"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-5dp"
+                android:layout_marginStart="25dp"
+                android:maxLines="1"
+                android:alpha="0.2"
+                android:rotation="345" />
+        </LinearLayout>
+        <LinearLayout
+            android:id="@+id/item"
+            android:orientation="vertical"
+            android:paddingTop="6dp"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <LinearLayout
+                android:orientation="horizontal"
+                android:paddingHorizontal="12dp"
+                android:paddingBottom="4dp"
+                android:gravity="top"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:id="@+id/person_icon"
+                    android:layout_width="34dp"
+                    android:layout_height="34dp" />
+
+                <LinearLayout
+                    android:background="@drawable/people_space_rounded_border"
+                    android:layout_marginStart="-5dp"
+                    android:layout_marginTop="18dp"
+                    android:layout_width="8dp"
+                    android:layout_height="8dp">
+
+                    <ImageView
+                        android:id="@+id/package_icon"
+                        android:layout_width="6dp"
+                        android:layout_marginEnd="1dp"
+                        android:layout_marginStart="1dp"
+                        android:layout_marginBottom="1dp"
+                        android:layout_marginTop="1dp"
+                        android:layout_height="6dp" />
+                </LinearLayout>
+
+                <LinearLayout
+                    android:orientation="vertical"
+                    android:paddingStart="6dp"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <TextView
+                        android:id="@+id/name"
+                        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                        android:textColor="?android:attr/textColorPrimary"
+                        android:textSize="14sp"
+                        android:maxLines="1"
+                        android:ellipsize="end"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content" />
+
+                    <TextView
+                        android:id="@+id/time"
+                        android:textColor="?android:attr/textColorSecondary"
+                        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                        android:textSize="10sp"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:maxLines="1"
+                        android:ellipsize="end" />
+                </LinearLayout>
+            </LinearLayout>
+            <LinearLayout
+                android:background="@drawable/people_space_content_background"
+                android:layout_gravity="center"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+                <TextView
+                    android:id="@+id/content"
+                    android:paddingVertical="3dp"
+                    android:paddingHorizontal="12dp"
+                    android:gravity="center"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textSize="16sp"
+                    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>
+    </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_tile_view.xml b/packages/SystemUI/res/layout/people_space_tile_view.xml
index 80bb070..c751e7d 100644
--- a/packages/SystemUI/res/layout/people_space_tile_view.xml
+++ b/packages/SystemUI/res/layout/people_space_tile_view.xml
@@ -20,46 +20,53 @@
     android:orientation="vertical">
 
     <LinearLayout
-        android:background="@drawable/people_space_tile_view_card"
         android:orientation="vertical"
-        android:padding="16dp"
-        android:layout_marginBottom="24dp"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:background="@drawable/people_space_activity_card"
+        android:padding="12dp"
         android:elevation="4dp"
-        android:gravity="start">
+        android:layout_marginBottom="12dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
 
-        <ImageView
-            android:id="@+id/tile_view_package_icon"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:layout_gravity="end" />
-
-        <ImageView
-            android:id="@+id/tile_view_person_icon"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:layout_gravity="start" />
-
-        <TextView
-            android:id="@+id/tile_view_name"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="4dp"
-            android:textSize="22sp"
-            android:textColor="?android:attr/textColorPrimary"
-            android:layout_width="wrap_content"
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="start" />
+            android:gravity="start">
 
-        <TextView
-            android:id="@+id/tile_view_status"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="4dp"
-            android:textSize="16sp"
-            android:textColor="?android:attr/textColorSecondary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:layout_gravity="start" />
+            <ImageView
+                android:id="@+id/tile_view_person_icon"
+                android:layout_width="48dp"
+                android:layout_height="48dp" />
+
+            <ImageView
+                android:id="@+id/tile_view_package_icon"
+                android:layout_width="16dp"
+                android:layout_marginStart="-8dp"
+                android:layout_height="16dp" />
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/tile_view_name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingHorizontal="16dp"
+                    android:textSize="22sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/tile_view_status"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="4dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget.xml b/packages/SystemUI/res/layout/people_space_widget.xml
index b417fcf..f4db321 100644
--- a/packages/SystemUI/res/layout/people_space_widget.xml
+++ b/packages/SystemUI/res/layout/people_space_widget.xml
@@ -22,6 +22,6 @@
     android:background="@drawable/people_space_widget_background"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:padding="5dp"
+    android:padding="2dp"
     android:divider="@null"
     android:dividerHeight="0dp"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml
index e4de6f9..170386f 100644
--- a/packages/SystemUI/res/layout/people_space_widget_item.xml
+++ b/packages/SystemUI/res/layout/people_space_widget_item.xml
@@ -16,44 +16,77 @@
   -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
+    android:padding="4dp"
     android:layout_height="wrap_content"
     android:orientation="vertical">
     <LinearLayout
         android:background="@drawable/people_space_tile_view_card"
         android:id="@+id/item"
         android:orientation="vertical"
-        android:padding="6dp"
-        android:layout_marginBottom="6dp"
+        android:padding="4dp"
+        android:layout_marginBottom="2dp"
         android:elevation="4dp"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="start">
-        <ImageView
-            android:id="@+id/package_icon"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
-            android:layout_gravity="end" />
-        <ImageView
-            android:id="@+id/person_icon"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
-            android:layout_gravity="start" />
-        <TextView
-            android:id="@+id/name"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:textSize="18sp"
-            android:textColor="?android:attr/textColorPrimary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start" />
-        <TextView
-            android:id="@+id/status"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
-            android:paddingVertical="2dp"
-            android:textSize="14sp"
-            android:textColor="?android:attr/textColorSecondary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start" />
+        android:layout_height="wrap_content">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:paddingStart="12dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="60dp"
+                android:layout_height="60dp" />
+
+            <LinearLayout
+                android:background="@drawable/people_space_rounded_border"
+                android:layout_marginStart="-12dp"
+                android:layout_marginTop="28dp"
+                android:layout_marginBottom="14dp"
+                android:layout_width="16dp"
+                android:layout_height="16dp">
+
+                <ImageView
+                    android:id="@+id/package_icon"
+                    android:layout_width="12dp"
+                    android:layout_marginStart="2dp"
+                    android:layout_marginEnd="2dp"
+                    android:layout_marginBottom="2dp"
+                    android:layout_marginTop="2dp"
+                    android:layout_height="12dp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:paddingStart="8dp"
+                android:paddingEnd="12dp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <TextView
+                    android:id="@+id/name"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:ellipsize="end"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/status"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                    android:paddingVertical="2dp"
+                    android:textSize="12sp"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:maxLines="3"
+                    android:ellipsize="end" />
+            </LinearLayout>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 89bf12d..387f2f2 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -25,9 +25,7 @@
     <View
         android:id="@+id/quick_settings_background"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:elevation="4dp"
-        android:background="@drawable/qs_background_primary" />
+        android:layout_height="0dp" />
 
     <com.android.systemui.qs.NonInterceptingScrollView
         android:id="@+id/expanded_qs_scroll_view"
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
index e08b44a..4f4b2af 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_height="wrap_content"
-             android:layout_width="match_parent"
-             android:layout_gravity="center"
-             style="@style/BrightnessDialogContainer">
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_gravity="center"
+    style="@style/BrightnessDialogContainer">
 
     <com.android.systemui.settings.brightness.BrightnessSliderView
         android:id="@+id/brightness_slider"
@@ -38,16 +38,5 @@
             android:progressDrawable="@drawable/brightness_progress_drawable_thick"
             android:splitTrack="false"
         />
-
-        <ImageView
-            android:id="@+id/image"
-            android:layout_width="24dp"
-            android:layout_height="24dp"
-            android:layout_marginLeft="48dp"
-            android:layout_gravity="center_vertical"
-            android:src="@drawable/ic_brightness"
-            android:tint="?android:attr/textColorTertiary"
-            android:visibility="visible"
-        />
     </com.android.systemui.settings.brightness.BrightnessSliderView>
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
index 69beffe..6f9d745 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
@@ -25,5 +25,4 @@
     android:layout_marginTop="@dimen/notification_side_paddings"
     android:layout_marginLeft="@dimen/notification_side_paddings"
     android:layout_marginRight="@dimen/notification_side_paddings"
-    android:visibility="gone"
-    android:background="@drawable/qs_background_primary"/>
+    android:visibility="gone"/>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index a90b1eb..1810c19 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -58,7 +58,7 @@
                 android:layout_height="match_parent"
                 android:scaleType="fitCenter"
                 android:padding="@dimen/volume_dialog_ringer_icon_padding"
-                android:tint="@color/accent_tint_color_selector"
+                android:tint="?android:attr/textColorPrimary"
                 android:layout_gravity="center"
                 android:soundEffectsEnabled="false" />
 
@@ -105,7 +105,7 @@
                     android:layout_gravity="center"
                     android:contentDescription="@string/accessibility_volume_settings"
                     android:background="@drawable/ripple_drawable_20dp"
-                    android:tint="?android:attr/textColorSecondary"
+                    android:tint="?android:attr/textColorPrimary"
                     android:soundEffectsEnabled="false" />
             </FrameLayout>
         </LinearLayout>
@@ -127,7 +127,7 @@
                 android:background="@drawable/rounded_ripple"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:tint="@color/caption_tint_color_selector"
+                android:tint="?android:attr/textColorPrimary"
                 android:layout_gravity="center"
                 android:soundEffectsEnabled="false"
                 sysui:optedOut="false"/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1fab478..da91f27 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om jou skermkiekie te bekyk"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kon nie skermkiekie stoor nie"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Toestel moet ontsluit word voordat skermkiekie gestoor kan word"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer weer skermkiekie neem"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery, drie stawe."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Battery vol."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterypersentasie is onbekend."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Geen foon nie."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Foon, een staaf."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Foon, twee stawe."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Foon, drie stawe."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Foonsein is vol."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Geen data nie."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data, een staaf."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data, twee stawe."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data, drie stawe."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasein vol."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Gekoppel aan <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Gekoppel aan <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Gekoppel aan <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX twee strepies."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX drie strepies."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-sein vol."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet is ontkoppel."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet gekoppel."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Geen sein nie."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nie gekoppel nie."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Geen stawe."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Af"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Gekoppel."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Koppel tans."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Swerwing"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Geen SIM nie."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiele data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiele data is aan"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiele data is af"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie gestel om data te gebruik nie"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Af"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-verbinding."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aan."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Geen SIM-kaart nie."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Diensverskaffernetwerk verander tans"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Maak batterybesonderhede oop"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> persent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> persent, ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor gegrond op jou gebruik"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan lui of vibreer op grond van fooninstellings. Gesprekke van <xliff:g id="APP_NAME">%1$s</xliff:g> af verskyn by verstek in \'n borrel."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hou jou aandag met \'n swewende kortpad na hierdie inhoud toe."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laat die stelsel bepaal of hierdie kennisgewing \'n klank moet maak of vibreer"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wys boaan die gespreksafdeling, verskyn as \'n swewende borrel, wys profielfoto op sluitskerm"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Hierdie program wys tans bo-oor ander programme op jou skerm en gebruik die mikrofoon en kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Instellings"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Die stelsel het hierdie kennisgewing stilgemaak."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Die stelsel het hierdie kennisgewing bevorder."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Die stelsel het hierdie kennisgewing gedegradeer."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Is dit korrek?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dankie vir jou terugvoer!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index eb63165..2e9400e 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is gekoppel"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is ontkoppel"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Kennisgewings"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen kennisgewings nie"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 5153904..d098079 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት መታ ያድርጉ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አልተቻለም"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ቅጽበታዊ ገጽ እይታ ከመቀመጡ በፊት መሳሪያ መከፈት አለበት"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ቅጽበታዊ ገጽ ዕይታን እንደገና ማንሳት ይሞክሩ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ባትሪ ሦስት አሞሌዎች።"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ባትሪ ሙሉ ነው።"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"የባትሪ መቶኛ አይታወቅም።"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ምንም ስልክ የለም።"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"የስልክ አንድ አሞሌ"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"የስልክ ሁለት አሞሌ"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"የስልክ ሦስት አሞሌ"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"የስልክ አመልካች ሙሉ ነው።"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ምንም ውሂብ የለም።"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"የውሂብ አንድ አሞሌ"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"የውሂብ ሁለት አሞሌዎች።"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"የውሂብ ሦስት አሞሌዎች።"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"የውሂብ አመልካች ሙሉ ነው።"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"ከ<xliff:g id="WIFI">%s</xliff:g> ጋር ተገናኝቷል።"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ከ<xliff:g id="BLUETOOTH">%s</xliff:g> ጋር ተገናኝቷል።"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"ከ<xliff:g id="CAST">%s</xliff:g> ጋር ተገናኝቷል።"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ሁለት አሞሌዎች።"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ሦስት አሞሌዎች።"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX አመልካች ሙሉ ነው።"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ኤተርኔት ተነቅሏል።"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ኤተርኔት ተገናኝቷል።"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ምንም ምልክት የለም።"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"አልተገናኘም።"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ዜሮ አሞሌዎች።"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ጠፍቷል።"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ተገናኝቷል።"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"በማገናኘት ላይ።"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"ጂፒአርኤስ"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"ኤችኤስፒኤ"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3ጂ"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"ሰ"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"ሰ+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4ጂ"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"በማዛወር ላይ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"ኤጅ"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ምንም SIM የለም።"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"የተንቀሳቃሽ ስልክ ውሂብ በርቷል"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ጠፍቷል"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ብሉቱዝ ማያያዝ።"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"የአውሮፕላን ሁነታ።"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ቪፒኤን በርቷል።"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"ምንም SIM ካርድ የለም።"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"የአገልግሎት አቅራቢ አውታረ መረብን በመቀየር ላይ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"የባትሪ ዝርዝሮችን ክፈት"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ባትሪ <xliff:g id="PERCENTAGE">%1$s</xliff:g> በመቶ፣ በአጠቃቀምዎ ላይ በመመስረት <xliff:g id="TIME">%2$s</xliff:g> ገደማ ይቀራል"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል። የ<xliff:g id="APP_NAME">%1$s</xliff:g> አረፋ ውይይቶች በነባሪነት።"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ለዚህ ይዞታ ከተንሳፋፊ አቋራጭ ጋር የእርስዎን ትኩረት ያቆያል።"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ይህ ማሳወቂያ ድምጽ ወይም ንዝረት መደረግ ካለበት ስርዓቱ እንዲወሰን ያድርጉት"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"በውይይት ክፍል አናት ላይ ያሳያል፣ እንደ ተንሳፋፊ አረፋ ብቅ ይላል፣ በቆልፍ ማያ ገጽ ላይ የመገለጫ ሥዕልን ያሳያል"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ቅንብሮች"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ቅድሚያ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ይህ መተግበሪያ በማያ ገጽዎ ላይ በሌሎች መተግበሪያዎች ላይ እያሳየ እና ማይክሮፎኑንና ካሜራውን እየተጠቀመ ነው።"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ቅንብሮች"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"እሺ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ይህ ማስታወቂያ በስርዓቱ ጸጥ እንዲል ተደርጓል።"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ይህ ማስታወቂያ በስርዓቱ ከፍ ተደርጓል።"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ይህ ማስታወቂያ በስርዓቱ ዝቅ ተደርጓል።"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ይህ ትክክል ነበር?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ለግብረመልስዎ እናመሰግናለን!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"እሺ"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 3ba5a62..71d887d 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ተያይዟል"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ተቋርቷል"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ማሳወቂያዎች"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ምንም ማሳወቂያዎች የሉም"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f6a1cf5..2fa6b27 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"انقر لعرض لقطة الشاشة."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"تعذّر حفظ لقطة الشاشة"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"يجب أن يتم فتح قفل الجهاز قبل حفظ لقطة الشاشة."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"جرّب أخذ لقطة الشاشة مرة أخرى"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"إشارة البطارية تتكون من ثلاثة أشرطة."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"إشارة البطارية كاملة."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"نسبة شحن البطارية غير معروفة."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ليست هناك إشارة بالهاتف."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"إشارة الهاتف تتكون من شريط واحد."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"إشارة الهاتف تتكون من شريطين."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"إشارة الهاتف تتكون من ثلاثة أشرطة."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"إشارة الهاتف كاملة."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"لا تتوفر بيانات."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"إشارة البيانات تتكون من شريط واحد."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"إشارة البيانات تتكون من شريطين."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"إشارة البيانات تتكون من ثلاثة أشرطة."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"إشارة البيانات كاملة."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"متصل بـ <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"متصل بـ <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"تم الاتصال بـ <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‏شريطا WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"‏أشرطة WiMAX الثلاثة."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"‏إشارة WiMAX كاملة."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"‏تم قطع اتصال Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"‏تم إنشاء اتصال Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ليست هناك إشارة."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"غير متصل."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ليست هناك أشرطة."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"تم الإيقاف."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"متصل."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"جارٍ الاتصال."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"‏شبكة GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"شبكة الجيل الثالث"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+‎"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"شبكة الجيل الرابع"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"شبكة الجيل الرابع أو أحدث"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+‎"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"التجوال"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"‏شبكة EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"‏ليست هناك شريحة SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"بيانات الجوّال"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"تفعيل بيانات الجوال"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"تم إيقاف بيانات الجوال"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"لم يتم الضبط على استخدام البيانات"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"غير مفعّلة"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"التوصيل عبر البلوتوث"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"‏ليس هناك شريحة SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"فتح تفاصيل البطارية"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"مستوى البطارية <xliff:g id="NUMBER">%d</xliff:g> في المائة."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"نسبة الشحن بالبطارية <xliff:g id="PERCENTAGE">%1$s</xliff:g> بالمائة، ويتبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا بناءً على استخدامك."</string>
@@ -734,6 +710,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"يمكن إصدار رنين أو اهتزاز بناءً على إعدادات الهاتف. تظهر المحادثات من <xliff:g id="APP_NAME">%1$s</xliff:g> كفقاعات تلقائيًا."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"يلفِت هذا الإشعار انتباهك لهذا المحتوى باستخدام اختصار عائم."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"السماح للنظام بتحديد ما إذا يجب اهتزاز الجهاز أو إصدار رنين عند تلقّي هذا الإشعار"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"تظهر في أعلى قسم المحادثات وتظهر كفقاعة عائمة وتعرض صورة الملف الشخصي على شاشة القفل"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"الإعدادات"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"الأولوية"</string>
@@ -752,9 +736,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"يتم عرض هذا التطبيق فوق التطبيقات الأخرى على شاشتك ويستخدم الميكروفون والكاميرا."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"الإعدادات"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"حسنًا"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"كتم النظام صوت هذا الإشعار."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"رفع النظام ترتيب هذا الإشعار."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"خفض النظام ترتيب هذا الإشعار."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"هل كان هذا صحيحًا؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"شكرًا على تعليقك"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"حسنًا"</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 15ccb94..7297c89 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏الشبكة الافتراضية الخاصة (VPN) متصلة."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏الشبكة الافتراضية الخاصة (VPN) غير متصلة."</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b84f409..85bd4a7 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"আপোনাৰ স্ক্ৰীণশ্বট চাবলৈ টিপক"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্ৰীনশ্বট ছেভ কৰিবলৈ ডিভাইচটো আনলক কৰিবই লাগিব"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰিৰ তিনিডাল দণ্ড।"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰি পূৰাকৈ চ্চাৰ্জ হৈছে।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ফ\'নত ছিগনেল নাই৷"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ফ\'নৰ ছিগনেলৰ তিনিডাল দণ্ড আছে।"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ফ\'নৰ ছিগনেল পূৰা আছে৷"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"কোনো ডেটা নাই।"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ডেটা ছিগনেলৰ এডাল দণ্ড।"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ডেটা ছংনেলৰ তিনিডাল দণ্ড।"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ডেটা ছিংগনেলত তিনিডাল দণ্ড আছে।"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ডেটা ছিগনেল পূৰা আছে।"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>ত সংযোগ হ’ল।"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAXৰ দুডাল দণ্ড আছে।"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAXৰ তিনিডাল দণ্ড আছে।"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAXৰ ছিগনেল পূৰা আছে৷"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ইথাৰনেট সংযোগ হৈছে।"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"কোনো ছিগনেল নাই।"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"সংযোগ হৈ থকা নাই।"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"এডালো দণ্ড নাই।"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"অফ।"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"সংযোগ কৰা হ’ল।"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"সংযোগ কৰি থকা হৈছে।"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"জিপিআৰএছ"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"এলটিই"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"এলটিই+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ৰ\'মিং"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ৱাই-ফাই"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ছিম নাই।"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ম’বাইল ডেটা"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ম’বাইল ডেটা অন অৱস্থাত আছে"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"অফ অৱস্থাত আছে"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ব্লুটুথ টেডাৰিং।"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"এয়াৰপ্লেইন ম\'ড।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ভিপিএন অন অৱস্থাত আছে।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো ছিম কাৰ্ড নাই"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"বাহক নেটৱৰ্কৰ পৰিৱৰ্তন"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰিৰ বিৱৰণসমূহ খোলক"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰি।"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰী <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফ’নৰ ছেটিঙৰ ওপৰত নিৰ্ভৰ কৰি ৰিং কৰিব অথবা কম্পন হ’ব পাৰে। <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাৰ্তালাপ ডিফ’ল্ট হিচাপে বাবল হয়।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"উপঙি থকা এটা শ্বৰ্টকাটৰ জৰিয়তে এই সমলখিনিৰ প্ৰতি আপোনাক মনোযোগী কৰি ৰাখে।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"এই জাননীটোৱে ধ্বনি নে কম্পন সৃষ্টি কৰিব সেয়া ছিষ্টেমটোক নিৰ্ধাৰণ কৰিবলৈ দিয়ক"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"বাৰ্তালাপ শাখাটোৰ শীৰ্ষত দেখুৱায়, ওপঙা বাবল হিচাপে দেখা পোৱা যায়, লক স্ক্ৰীনত প্ৰ’ফাইলৰ চিত্ৰ প্ৰদৰ্শন কৰে"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ছেটিংসমূহ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"অগ্ৰাধিকাৰ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ছেটিংসমূহ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ছিষ্টেমটোৱে এই জাননীক নীৰৱ কৰিছে।"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ছিষ্টেমটোৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া গুৰুত্ব বৃদ্ধি কৰিছে।"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ছিষ্টেমটোৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া গুৰুত্ব হ্ৰাস কৰিছে।"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"এইটো শুদ্ধ আছিলনে?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"আপোনাৰ মতামতৰ বাবে ধন্যবাদ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ঠিক আছে"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"সঞ্চয়াগাৰ"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"ইংগিতবোৰ"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"তাৎক্ষণিক এপসমূহ"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে।"</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string>
diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml
index f7afcfa..859ea2c 100644
--- a/packages/SystemUI/res/values-as/strings_tv.xml
+++ b/packages/SystemUI/res/values-as/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"ভিপিএন সংযোগ হৈ আছে"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ভিপিএনৰ সংযোগ বিচ্ছিন্ন হৈছে"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"জাননী"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনো জাননী নাই"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index a329288..84f9560 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinşotunuza baxmaq üçün klikləyin"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinşotu yadda saxlamaq alınmadı"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinşotu saxlamazdan əvvəl cihaz kiliddən çıxarılmalıdır"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skrinşotu yenidən çəkin"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya üç xətdir."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya doludur"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareyanın faizi naməlumdur."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon yoxdur."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Şəbəkə bir xətdir."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Şəbəkə iki xətdir."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Şəbəkə üç xətdir."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Tam şəbəkə."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Məlumat yoxdur."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data bir xətdir."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data iki xətdir."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data üç xətdir."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data siqnalı tamdır."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> üzərindən qoşuldu."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> üzərindən qoşuldu."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> cihazına qoşulub."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX iki xətdir."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX üç xətdir."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX siqnalı tamdır."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bağlantısı kəsilib."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet qoşuludur."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Siqnal yoxdur."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Qoşulu deyil."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Sıfır xətt."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Deaktiv"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Qoşuludur."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Birləşdirilir."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Rominq"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM yoxdur"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobil Data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil Data Aktivdir"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil data deaktivdir"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Data istifadə etmək üçün ayarlanmayıb"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Deaktiv"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tezering."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçuş rejimi"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktivdir."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM kart yoxdur."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator şəbəkəsinin dəyişilməsi"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Batareya detallarını açın"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> faizdir."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya <xliff:g id="PERCENTAGE">%1$s</xliff:g> faizdir, istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına əsasən zəng çala və ya vibrasiya edə bilər. <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqindən söhbətlərdə defolt olaraq qabarcıq çıxır."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu məzmuna üzən qısayol ilə diqqətinizi cəlb edir."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirişin səs çıxarması və ya vibrasiya etməsi sistem tərəfindən təyin edilsin"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Söhbət bölməsinin yuxarısında göstərilir, üzən qabarcıq kimi görünür, kilid ekranında profil şəkli göstərir"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu tətbiq ekranda digər tətbiqlərin üzərində göstərilir və mikrofon ilə kameradan istifadə edir."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ayarlar"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildiriş sistem tərəfindən səssiz edilib."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildiriş sistem tərəfindən irəli çəkilib."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildiriş sistem tərəfindən geri çəkilib."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Bu, doğru oldu?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Rəyiniz üçün təşəkkür edirik!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml
index cd9935f..1f1b649 100644
--- a/packages/SystemUI/res/values-az/strings_tv.xml
+++ b/packages/SystemUI/res/values-az/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN qoşulub"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ayrılıb"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirişlər"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildiriş yoxdur"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index d800e8d..7c0e652 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste videli snimak ekrana"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Čuvanje snimka ekrana nije uspelo"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora da bude otključan da bi snimak ekrana mogao da se sačuva"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probajte da ponovo napravite snimak ekrana"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija od tri crte."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procenat napunjenosti baterije nije poznat."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal telefona ima jednu crtu."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal telefona od dve crte."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal telefona od tri crte."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal telefona je pun."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal za podatke ima jednu crtu."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal za podatke od dve crte."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal za podatke od tri crte."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal za podatke je najjači."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezani ste sa <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezani ste sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Povezani smo sa uređajem <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX signal ima dve crte."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX signal ima tri crte."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal je najjači."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Veza sa eternetom je prekinuta."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Eternet je povezan."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nijedna crta."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano je."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilni podaci"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilni podaci su uključeni"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilni podaci su isključeni"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije podešeno za korišćenje podataka"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth privezivanje."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim rada u avionu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je uključen."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promena mreže mobilnog operatera"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Otvori detalje o bateriji"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija je na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, preostalo vreme na osnovu korišćenja je <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može da zvoni ili vibrira u zavisnosti od podešavanja telefona. Konverzacije iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> se podrazumevano prikazuju u oblačićima."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vam pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sistem utvrdi da li ovo obaveštenje treba da emituje zvuk ili da vibrira"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se u vrhu odeljka za konverzacije kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Podešavanja"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova aplikacija se prikazuje preko drugih aplikacija na ekranu i koristi mikrofon i kameru."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Podešavanja"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Potvrdi"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je isključio ovo obaveštenje."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je promovisao ovo obaveštenje."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je postavio ovo obaveštenje na dno."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Da li je to tačno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala vam na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Potvrdi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 8122e4d..2eaa499 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza sa VPN-om je prekinuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obaveštenja"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obaveštenja"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 9fd9a5e..65d45b9 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Дакраніцеся, каб прагледзець здымак экрана"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не атрымалася зрабіць здымак экрана"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Перад захаваннем здымка экрана трэба разблакіраваць прыладу"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Тры планкі акумулятара."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятар поўны."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Працэнт зараду акумулятара невядомы."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Няма тэлефона."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Адна планка на тэлефоне."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"2 планкі тэлефона."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"3 планкі тэлефона."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Поўны сігнал тэлефона."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Няма дадзеных."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Адна планка дадзеных."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"2 планкі дадзеных."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"3 планкі дадзеных."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Поўны сігнал перадачы дадзеных."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Падключаны да <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Падлучаны да <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Ёсць падключэнне да <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Два слупкi сiгналу WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Тры слупкi сiгналу WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Моцны сiгнал WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet адлучаны."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet падлучаны."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Няма сігналу."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Няма падключэння."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Няма."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Выключана."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Падключана."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Падлучэнне."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роўмінг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Няма SIM-карты."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мабільная перадача даных"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мабільная перадача даных уключана"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мабільная перадача даных выключана"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Не зададзена для выкарыстання даных"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Выключана"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Сувязь па Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Рэжым палёту."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN уключана."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Няма SIM-карты."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Змяненне аператара сеткі"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Паказаць падрабязную інфармацыю пра акумулятар"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Працэнт зараду акумулятара: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Зарад акумулятара ў працэнтах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Пры такім выкарыстанні яго хопіць прыблізна на <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя. Размовы ў праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" стандартна паяўляюцца ў выглядзе ўсплывальных апавяшчэнняў."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Прыцягвае ўвагу да гэтага змесціва ўсплывальнай кнопкай."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Сістэма сама будзе вызначаць, ці трэба для гэтага апавяшчэння ўключаць гук або вібрацыю"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Паказваецца ўверсе раздзела размоў, як усплывальнае апавяшчэнне, паказвае фота профілю на экране блакіроўкі"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Налады"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Гэта праграма паказваецца на экране паверх іншых праграм. Яна выкарыстоўвае мікрафон і камеру."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Налады"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Гук гэтага апавяшчэння выключаны сістэмай."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Прыярытэт гэтага апавяшчэння павышаны сістэмай."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Прыярытэт гэтага апавяшчэння паніжаны сістэмай."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Усё правільна?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Дзякуй за водгук!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 1016b8c..21a2e6e 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN падключаны"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN адключаны"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Апавяшчэнні"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Апавяшчэнняў няма"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 78a826b..6f90c2a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Докоснете, за да видите екранната снимка"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не можа да се запази екранна снимка"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"За да бъде запазена екранната снимка, устройството трябва да бъде отключено"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Опитайте да направите екранна снимка отново"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерията е с три чертички."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батерията е пълна."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентът на батерията е неизвестен."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Няма телефон."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефонът е с една чертичка."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефонът е с две чертички."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефонът е с три чертички."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигналът за телефона е пълен."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Няма данни."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Данните са с една чертичка."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Данните са с две чертички."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Данните са с три чертички."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигналът за данни е пълен."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Има връзка с <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Има връзка с <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Установена е връзка с/ъс <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX е с две чертички."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX е с три чертички."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Сигналът за WiMAX е пълен."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Връзката с Ethernet е прекратена."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Установена е връзка с Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Няма сигнал."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Няма връзка."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Нула чертички."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Изкл."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Има връзка."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Установява се връзка."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Няма SIM карта."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобилни данни"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилните данни са включени"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилните данни са изключени"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Не е зададено да използва данни"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Изключени"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Тетъринг през Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Самолетен режим."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Функцията за виртуална частна мрежа (VPN) е включена."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Няма SIM карта."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Промяна на мрежата на оператора"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Отваряне на подробностите за батерията"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> процента батерия."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерията е на <xliff:g id="PERCENTAGE">%1$s</xliff:g> процента. Още около <xliff:g id="TIME">%2$s</xliff:g> въз основа на използването"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звъни или да вибрира въз основа на настройките за телефона. Разговорите от <xliff:g id="APP_NAME">%1$s</xliff:g> се показват като балончета по подразбиране."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Задържа вниманието ви посредством плаващ пряк път към това съдържание."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Нека системата да определя дали дадено известие да се придружава от звук, или вибриране"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Показва се като плаващо балонче в горната част на секцията с разговори, показва снимката на потр. профил на заключения екран"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Това приложение се показва върху други приложения на екрана и използва микрофона и камерата."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Настройки"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Това известие бе заглушено от системата."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Това известие бе повишено от системата."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Това известие бе понижено от системата."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Правилно ли е това?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Благодарим ви за отзивите!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index 6f6b824..b7af7cb 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е свързана"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Връзката с VPN е прекратена"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известия"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Няма известия"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 92e0c1d..6b23edc 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"স্ক্রিনশটটি দেখতে ট্যাপ করুন"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্রিনশট সেভ করা যায়নি"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্রিনশট সেভ করার আগে ডিভাইসটি অবশ্যই আনলক করতে হবে"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"তিন দন্ড ব্যাটারি রয়েছে৷"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ব্যাটারি পূর্ণ রয়েছে৷"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"কোনো ফোনের সংকেত নেই৷"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"তিন দন্ড ফোনের সংকেত রয়েছে৷"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ফোনের সংকেত পূর্ণ রয়েছে৷"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"কোনো ডেটা নেই৷"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"এক দন্ড ডেটার সংকেত৷"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"দুই দন্ড ডেটার সংকেত রয়েছে৷"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"তিন দন্ড ডেটার সংকেত৷"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"পূর্ণ ডেটার সংকেত রয়েছে৷"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> এর সাথে সংযুক্ত।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>এ সংযুক্ত হয়ে আছে।"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> এর সাথে সংযুক্ত৷"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX এ দুইটি দণ্ড৷"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX এ তিনটি দণ্ড৷"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX এ সম্পূর্ণ সিগন্যাল৷"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ইথারনেট সংযুক্ত হয়েছে৷"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"কোনো সিগন্যাল নেই৷"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"সংযুক্ত নয়৷"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"কোনো দণ্ড নেই৷"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"বন্ধ৷"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"সংযুক্ত৷"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"সংযুক্ত হচ্ছে৷"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"রোমিং"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ওয়াই-ফাই"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"কোনো সিম নেই৷"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"মোবাইল ডেটা"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"মোবাইল ডেটা চালু আছে"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"বন্ধ"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ব্লুটুথ টিথারিং৷"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"বিমান মোড৷"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN চালু আছে।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো সিম কার্ড নেই।"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তন করা হচ্ছে"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ব্যাটারির বিশদ বিবরণ খুলুন"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ব্যাটারি <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, বর্তমান ব্যবহারের উপর ভিত্তি করে আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফোনের সেটিংস অনুযায়ী ফোন রিং বা ভাইব্রেট হতে পারে। <xliff:g id="APP_NAME">%1$s</xliff:g>-এর কথোপকথন সাধারণত বাবলের মতো দেখাবে।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ফ্লোটিং শর্টকাট ব্যবহার করে এই কন্টেন্টে আপনার দৃষ্টি আকর্ষণ করে রাখে।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"এই বিজ্ঞপ্তি এলে ডিভাইস আওয়াজ করবে না ভাইব্রেট করবে তা সিস্টেমকে সেট করতে দিন"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"কথোপকথন বিভাগের উপরে ভাসমান বাবলের মতো দেখা যাবে, লক স্ক্রিনে প্রোফাইল ছবি দেখাবে"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"সেটিংস"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"অগ্রাধিকার"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই অ্যাপটি স্ক্রিনে অন্যান্য অ্যাপের উপরে দেখানো হচ্ছে এবং মাইক্রোফোন ও ক্যামেরা ব্যবহার করছে।"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"সেটিংস"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"সিস্টেম এই বিজ্ঞপ্তি মিউট করে রেখেছিল।"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"সিস্টেম এই বিজ্ঞপ্তি দেখাতে চেয়েছে।"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"সিস্টেম এই বিজ্ঞপ্তি বন্ধ রেখেছে।"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"এটি কি সঠিক ছিল?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"মতামতের জন্য ধন্যবাদ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"বুঝেছি"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"সাধারণ বার্তাগুলি"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"স্টোরেজ"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"হিন্ট"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ইনস্ট্যান্ট অ্যাপ"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলছে"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে। আরও জানতে ট্যাপ করুন।"</string>
diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml
index 1c26840..38c24ac 100644
--- a/packages/SystemUI/res/values-bn/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN কানেক্ট করা হয়েছে"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ডিসকানেক্ট করা হয়েছে"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"বিজ্ঞপ্তি"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনও বিজ্ঞপ্তি নেই"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 1179a92..bb2bd8b 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite za prikaz snimka ekrana"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nije moguće sačuvati snimak ekrana"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Morate otključati uređaj da možete sačuvati snimak ekrana"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo snimiti ekran"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija na tri crtice."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak napunjenosti baterije nije poznat"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefonskog signala."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal na jednoj crtici."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal na dvije crtice."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonski signal na tri crtice."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonski signal pun."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Prijenos podataka na jednoj crtici."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Prijenos podataka na dvije crtice."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Prijenos podataka na tri crtice."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal za prijenos podataka pun."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezan na <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezan na <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Povezan na <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX signal na dvije crtice."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX signal na tri crtice."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal pun."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Veza sa Ethernetom je prekinuta."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet je spojen."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nema crtica."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Prijenos podataka na mobilnoj mreži"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Prijenos podataka na mobilnoj mreži je uključen"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Prijenos podataka na mobilnoj mreži je isključen"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije postavljeno za korištenje podataka"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Dijeljenje Bluetooth veze."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u avionu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promjena mreže mobilnog operatera"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Otvori detalje o potrošnji baterije"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto. Na osnovu vaše potrošnje preostalo vam je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može zvoniti ili vibrirati na osnovu postavki vašeg telefona. Razgovori iz oblačića u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> kao zadana opcija."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vašu pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sistem odluči treba li se ovo obavještenje oglasiti zvukom ili vibracijom"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se na vrhu odjeljka za razgovor, pojavljuje se kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetni"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova aplikacija prekriva druge aplikacije na ekranu i koristi mikrofon i kameru."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Postavke"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Uredu"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je utišao ovo obavještenje."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je pomovirao ovo obavještenje."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je umanjio značaj ovog obavještenja."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Je li ovo bilo tačno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"UREDU"</string>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 7507746..01916a1 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza s VPN-om je prekinuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavještenja"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavještenja"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ca63162..bb7bdd4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca per veure la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No s\'ha pogut desar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositiu ha d\'estar desbloquejat abans que la captura de pantalla es pugui desar"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: tres barres."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Es desconeix el percentatge de bateria."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"No hi ha senyal de telèfon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Senyal de telèfon: una barra"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Senyal de telèfon: dues barres."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Senyal de telèfon: tres barres."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Senyal de telèfon: complet."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Senyal de dades: no n\'hi ha"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Senyal de dades: una barra."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Senyal de dades: dues barres."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Senyal de dades: tres barres."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Senyal de dades: complet."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"S\'ha connectat a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"S\'ha connectat a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Està connectat amb <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dues barres de WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barres de WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Senyal de WiMAX plena."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"S\'ha desconnectat l\'Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connectada"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sense senyal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Sense connexió."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Cap barra."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivat."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connectat"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"S’està connectant."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Itinerància"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"No hi ha cap SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dades mòbils"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dades mòbils activades"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"S\'han desactivat les dades mòbils"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"No s\'ha definit per utilitzar dades"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desactivades"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Compartició de xarxa per Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode d\'avió."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No hi ha cap SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Obre els detalls de la bateria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> per cent de bateria."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> per cent de bateria amb aproximadament <xliff:g id="TIME">%2$s</xliff:g> de temps restant segons l\'ús que en fas"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pot sonar o vibrar en funció de la configuració del telèfon. Les converses de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g> es mostren com a bombolles de manera predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Atrau la teva atenció amb una drecera flotant a aquest contingut."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fes que el sistema determini si aquesta notificació ha d\'emetre un so o una vibració"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Es mostra com a bombolla flotant a la part superior de la secció de converses i mostra la foto de perfil a la pantalla de bloqueig"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuració"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritat"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aquesta aplicació es mostra sobre altres aplicacions a la pantalla i utilitza el micròfon i la càmera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Configuració"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"D\'acord"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"El sistema ha silenciat aquesta notificació."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ha augmentat el nivell d\'aquesta notificació."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"El sistema ha disminuït el nivell d\'aquesta notificació."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"La informació ha estat correcta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gràcies pels suggeriments."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"D\'acord"</string>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index 14bc947..a060785 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN està connectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN està desconnectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacions"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Cap notificació"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index aa6459e..7cfe95c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím snímek obrazovky zobrazíte"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímek obrazovky se nepodařilo uložit"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Aby bylo možné uložit screenshot, zařízení musí být odemknuto"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zkuste snímek pořídit znovu"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tři čárky baterie."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie je nabitá."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procento baterie není známé."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Žádná telefonní síť."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jedna čárka signálu telefonní sítě."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvě čárky signálu telefonní sítě."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tři čárky signálu telefonní sítě."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Plný signál telefonní sítě."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Žádné datové připojení."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Jedna čárka signálu datové sítě."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dvě čárky signálu datové sítě."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tři čárky signálu datové sítě."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Plný signál datové sítě."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Připojeno k zařízení <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Připojeno k zařízení <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Jste připojeni k zařízení <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dvě čárky signálu sítě WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tři čárky signálu sítě WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Plný signál sítě WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Síť ethernet je odpojena."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Síť ethernet je připojena."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Není signál."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nepřipojeno."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Žádná čárka."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Vypnuto."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Připojeno."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Připojování."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Žádná SIM karta."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilní data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilní data jsou zapnuta"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilní data jsou vypnuta"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nenastaveno k využití dat"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Vypnuto"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Sdílené připojení přes Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim Letadlo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuto."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Chybí SIM karta"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Probíhá změna sítě operátora"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Otevřít podrobnosti o baterii"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterie je nabitá na <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, při vašem používání vydrží ještě <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve výchozím nastavení bublají."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Přitahuje pozornost pomocí plovoucí zkratky k tomuto obsahu."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nechat systém rozhodnout, zda má toto oznámení vydat zvuk či zavibrovat"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Zobrazuje se v horní části sekce konverzací a má podobu plovoucí bubliny, zobrazuje profilovou fotku na obrazovce uzamčení"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavení"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Tato aplikace se zobrazuje přes ostatní aplikace na obrazovce a využívá mikrofon a fotoaparát."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Nastavení"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Toto oznámení systém ztlumil."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"U tohoto oznámení systém zvýšil prioritu."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"U tohoto oznámení systém snížil prioritu."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Udělal to správně?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Děkujeme za zpětnou vazbu."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index ad869b1..0a9850c 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Síť VPN je připojena"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Síť VPN je odpojena"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prostřednictvím aplikace <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Oznámení"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žádná oznámení"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d20fc0c..5bde4d8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tryk for at se dit screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshottet kunne ikke gemmes"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheden skal være låst op, før du kan gemme screenshots"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv at tage et screenshot igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri tre bjælker."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batteri fuldt."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon en bjælke."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon to bjælker."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon tre bjælker."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignal fuldt."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ingen data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data en bjælke."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data to bjælker."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tre bjælker."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignal fuldt."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Tilsluttet <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tilsluttet <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Forbundet til <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX to bjælker."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tre bjælker."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signal er fuldt."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet er ikke tilsluttet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet er tilsluttet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Intet signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ikke tilsluttet."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nul bjælker."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Fra."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Forbundet."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Opretter forbindelse..."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Intet SIM-kort."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata er aktiveret"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata er deaktiveret"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ikke indstillet til at anvende data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Fra"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-netdeling."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flytilstand."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN er slået til."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Der er ikke noget SIM-kort."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Skift af mobilnetværk"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Åbn oplysninger om batteri"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteriniveauet er på <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, så du har ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere baseret på telefonens indstillinger. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> vises som standard i bobler."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fastholder din opmærksomhed med en svævende genvej til indholdet."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Få systemet til at afgøre, om denne notifikation skal vibrere eller afspille en lyd"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtalesektionen som en svævende boble og med profilbillede på låseskærmen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Indstillinger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Denne app vises over andre apps på din skærm og anvender mikrofonen og kameraet."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Indstillinger"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Denne notifikation blev sat på lydløs af systemet."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Denne notifikation blev rykket op af systemet."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Denne notifikation blev rykket ned af systemet."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Var dette korrekt?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Tak for din feedback"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index 84926e0c..fb0bc2d 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilsluttet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er afbrudt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikationer"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen notifikationer"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index dcd6a53..14e7e16 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tippe, um deinen Screenshot anzusehen"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshot konnte nicht gespeichert werden"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Damit Screenshots gespeichert werden können, muss das Gerät entsperrt sein"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Versuche noch einmal, den Screenshot zu erstellen"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akku - drei Balken"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Akku voll"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akkustand unbekannt."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Kein Telefon"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonsignal - ein Balken"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonsignal - zwei Balken"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonsignal - drei Balken"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Volle Telefonsignalstärke"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Keine Daten"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datensignal - ein Balken"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datensignal - zwei Balken"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datensignal - drei Balken"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Volle Datensignalstärke"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Mit <xliff:g id="WIFI">%s</xliff:g> verbunden"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Mit <xliff:g id="BLUETOOTH">%s</xliff:g> verbunden"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Verbunden mit <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX - zwei Balken"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX - drei Balken"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Volle WiMAX-Signalstärke"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet nicht verbunden"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet verbunden"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Kein Signal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nicht verbunden"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Kein Balken"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Aus"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Verbunden"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Verbindung wird hergestellt."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Keine SIM-Karte"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile Daten"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile Datennutzung aktiviert"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile Daten deaktiviert"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nicht für Datennutzung konfiguriert"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Aus"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-Tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugmodus"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN an."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Keine SIM-Karte"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobilfunknetzwerk wird gewechselt"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Akkudetails öffnen"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akku bei <xliff:g id="NUMBER">%d</xliff:g> Prozent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akku bei <xliff:g id="PERCENTAGE">%1$s</xliff:g> Prozent. Bei deinem Nutzungsmuster hast du noch Strom für etwa <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kann klingeln oder vibrieren, je nach Telefoneinstellungen. Unterhaltungen von <xliff:g id="APP_NAME">%1$s</xliff:g> werden standardmäßig als Bubble angezeigt."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Du wirst mit einer unverankerten Verknüpfung darauf aufmerksam gemacht."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Das System entscheiden lassen, ob bei dieser Benachrichtigung ein Ton oder eine Vibration ausgegeben wird"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wird oben im Bereich \"Unterhaltungen\" als unverankerte Bubble mit einem Profilbild auf dem Sperrbildschirm angezeigt"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Einstellungen"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorität"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Diese App wird über anderen Apps auf dem Bildschirm angezeigt und verwendet das Mikrofon und die Kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Einstellungen"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Ok"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Diese Benachrichtigung wurde vom System stummgeschaltet."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Diese Benachrichtigung wurde vom System hochgestuft."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Diese Benachrichtigung wurde vom System heruntergestuft."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"War das richtig?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Vielen Dank für dein Feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index 34fc6aa..0345c80 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ist verbunden"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ist nicht verbunden"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Benachrichtigungen"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Keine Benachrichtigungen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 197cd17..1e65310 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Πατήστε για να δείτε το στιγμιότυπο οθόνης που δημιουργήσατε"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Μη δυνατή αποθήκευση του στιγμιότυπου οθόνης"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Η συσκευή πρέπει να ξεκλειδωθεί για να αποθηκευτεί το στιγμιότυπο οθόνης."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Τρεις γραμμές μπαταρίας."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Πλήρης μπαταρία."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Άγνωστο ποσοστό μπαταρίας."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Δεν υπάρχει τηλέφωνο."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Μία γραμμή τηλεφώνου."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Δύο γραμμές τηλεφώνου."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Τρεις γραμμές μπαταρίας."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Πλήρες σήμα τηλεφώνου."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Δεν υπάρχουν δεδομένα."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Μία γραμμή δεδομένων."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Δύο γραμμές δεδομένων."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Τρεις γραμμές δεδομένων."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Πλήρες σήμα δεδομένων."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Συνδέθηκε στο <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Συνδέθηκε στο <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Συνδέθηκε σε <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Σήμα WiMAX δύο γραμμές."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Σήμα WiMAX τρεις γραμμές."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Πλήρες σήμα WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Το Ethernet αποσυνδέθηκε."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Το Ethernet συνδέθηκε."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Δεν υπάρχει σήμα."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Μη συνδεδεμένο"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Μηδέν γραμμές."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Ανενεργό."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Έχει συνδεθεί."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Σύνδεση."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Περιαγωγή"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Δεν υπάρχει SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Τα δεδομένα κινητής τηλεφωνίας ενεργοποιήθηκαν"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Ανενεργά"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Σύνδεση με Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Λειτουργία πτήσης."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ενεργό."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Δεν υπάρχει κάρτα SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Αλλαγή δικτύου εταιρείας κινητής τηλεφωνίας"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Άνοιγμα λεπτομερειών μπαταρίας"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Μπαταρία <xliff:g id="NUMBER">%d</xliff:g> τοις εκατό."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Μπαταρία στο <xliff:g id="PERCENTAGE">%1$s</xliff:g> τοις εκατό. Περίπου <xliff:g id="TIME">%2$s</xliff:g> ακόμη, βάσει της χρήσης σας"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου. Οι συζητήσεις από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εμφανίζονται σε συννεφάκι από προεπιλογή."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Κρατάει την προσοχή σας με μια κινούμενη συντόμευση προς αυτό το περιεχόμενο."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Επιτρέψτε στο σύστημα να αποφασίσει αν αυτή η ειδοποίηση θα αναπαράγει έναν ήχο ή θα ενεργοποιήσει τη δόνηση της συσκευής"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Εμφανίζεται επάνω στις συζητήσεις, προβάλλεται ως κιν. συννεφάκι, εμφανίζει τη φωτ. προφίλ στην οθ. κλειδ."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ρυθμίσεις"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Προτεραιότητα"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Αυτή η εφαρμογή εμφανίζεται πάνω σε άλλες εφαρμογές στην οθόνη σας και χρησιμοποιεί το μικρόφωνο και την κάμερα."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ρυθμίσεις"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ΟΚ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Αυτή η ειδοποίηση τέθηκε σε σίγαση από το σύστημα."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Αυτή η ειδοποίηση προωθήθηκε από το σύστημα."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Αυτή η ειδοποίηση υποβιβάστηκε από το σύστημα."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Ήταν σωστό αυτό;"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Σας ευχαριστούμε για τα σχόλιά σας!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ΟΚ"</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index 21badf7..cd92772 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Το VPN συνδέθηκε"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Το VPN αποσυνδέθηκε"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ειδοποιήσεις"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Δεν υπάρχουν ειδοποιήσεις."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 85d6276..0779fba 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index ab370b1..3b3e2d6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 5db104c..3d93f9f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Airplane mode."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index ab370b1..3b3e2d6 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 85d6276..0779fba 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index ab370b1..3b3e2d6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 85d6276..0779fba 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index ab370b1..3b3e2d6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 3719aa7..7d7e4b9 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎Screenshot saved‎‏‎‎‏‎"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎Tap to view your screenshot‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎Couldn\'t save screenshot‎‏‎‎‏‎"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎Device must be unlocked before screenshot can be saved‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎Try taking screenshot again‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎Can\'t save screenshot due to limited storage space‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎Taking screenshots isn\'t allowed by the app or your organization‎‏‎‎‏‎"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎Battery three bars.‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎Battery full.‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎Battery percentage unknown.‎‏‎‎‏‎"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎No phone.‎‏‎‎‏‎"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎Phone one bar.‎‏‎‎‏‎"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎Phone two bars.‎‏‎‎‏‎"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎Phone three bars.‎‏‎‎‏‎"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎Phone signal full.‎‏‎‎‏‎"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎No data.‎‏‎‎‏‎"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎Data one bar.‎‏‎‎‏‎"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎Data two bars.‎‏‎‎‏‎"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎Data three bars.‎‏‎‎‏‎"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎Data signal full.‎‏‎‎‏‎"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎Connected to ‎‏‎‎‏‏‎<xliff:g id="WIFI">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎Connected to ‎‏‎‎‏‏‎<xliff:g id="BLUETOOTH">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎Connected to ‎‏‎‎‏‏‎<xliff:g id="CAST">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎WiMAX two bars.‎‏‎‎‏‎"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎WiMAX three bars.‎‏‎‎‏‎"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎WiMAX signal full.‎‏‎‎‏‎"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎Ethernet disconnected.‎‏‎‎‏‎"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎Ethernet connected.‎‏‎‎‏‎"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎No signal.‎‏‎‎‏‎"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎Not connected.‎‏‎‎‏‎"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎Zero bars.‎‏‎‎‏‎"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎Off.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎Connected.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎Connecting.‎‏‎‎‏‎"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎GPRS‎‏‎‎‏‎"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎HSPA‎‏‎‎‏‎"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎3G‎‏‎‎‏‎"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎H‎‏‎‎‏‎"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎H+‎‏‎‎‏‎"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎4G‎‏‎‎‏‎"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎4G+‎‏‎‎‏‎"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎LTE‎‏‎‎‏‎"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎LTE+‎‏‎‎‏‎"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎1X‎‏‎‎‏‎"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎Roaming‎‏‎‎‏‎"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎EDGE‎‏‎‎‏‎"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎Wi-Fi‎‏‎‎‏‎"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎No SIM.‎‏‎‎‏‎"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎Mobile Data‎‏‎‎‏‎"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‎‎Mobile Data On‎‏‎‎‏‎"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎Mobile data off‎‏‎‎‏‎"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎Not set to use data‎‏‎‎‏‎"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‎Off‎‏‎‎‏‎"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎Bluetooth tethering.‎‏‎‎‏‎"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎Airplane mode.‎‏‎‎‏‎"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎VPN on.‎‏‎‎‏‎"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎No SIM card.‎‏‎‎‏‎"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‎Carrier network changing‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎Open battery details‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ percent.‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ percent, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
@@ -722,6 +698,10 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎May ring or vibrate based on phone settings. Conversations from ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ bubble by default.‎‏‎‎‏‎"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎Keeps your attention with a floating shortcut to this content.‎‏‎‎‏‎"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎Have the system determine if this notification should make sound or vibration‎‏‎‎‏‎"</string>
+    <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎&lt;b&gt;Status:&lt;/b&gt; Promoted to Default‎‏‎‎‏‎"</string>
+    <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎&lt;b&gt;Status:&lt;/b&gt; Demoted to Silent‎‏‎‎‏‎"</string>
+    <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎&lt;b&gt;Status:&lt;/b&gt; Ranked Higher‎‏‎‎‏‎"</string>
+    <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎&lt;b&gt;Status:&lt;/b&gt; Ranked Lower‎‏‎‎‏‎"</string>
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen‎‏‎‎‏‎"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎Settings‎‏‎‎‏‎"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎Priority‎‏‎‎‏‎"</string>
@@ -740,9 +720,10 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎This app is displaying over other apps on your screen and using the microphone and camera.‎‏‎‎‏‎"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎Settings‎‏‎‎‏‎"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎OK‎‏‎‎‏‎"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‎This notification was silenced by the system.‎‏‎‎‏‎"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎This notification was promoted by the system.‎‏‎‎‏‎"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎This notification was demoted by the system.‎‏‎‎‏‎"</string>
+    <string name="feedback_alerted" msgid="5192459808484271208">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎This notification was automatically &lt;b&gt;promoted to Default&lt;/b&gt; by the system.‎‏‎‎‏‎"</string>
+    <string name="feedback_silenced" msgid="9116540317466126457">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎This notification was automatically &lt;b&gt;demoted to Silent&lt;/b&gt; by the system.‎‏‎‎‏‎"</string>
+    <string name="feedback_promoted" msgid="2125562787759780807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade.‎‏‎‎‏‎"</string>
+    <string name="feedback_demoted" msgid="951884763467110604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade.‎‏‎‎‏‎"</string>
     <string name="feedback_prompt" msgid="2278631214125128281">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎Was this correct?‎‏‎‎‏‎"</string>
     <string name="feedback_response" msgid="4671729244976641339">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎Thanks for your feedback!‎‏‎‎‏‎"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎OK‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
index 9fb2610..34882b3 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎VPN is connected‎‏‎‎‏‎"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎VPN is disconnected‎‏‎‎‏‎"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎Via ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎Notifications‎‏‎‎‏‎"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎No Notifications‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bd64950..5940767 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Presiona para ver la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No se pudo guardar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe estar desbloqueado para poder guardar la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a hacer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Se desconoce el porcentaje de la batería."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de teléfono"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de teléfono"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de teléfono"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Señal de teléfono completa"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"No hay datos."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Una barra de datos"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dos barras de datos"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de datos"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Señal de datos completa"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dos barras de WiMAX"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Señal de WiMAX al máximo"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sin señal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"No conectado"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Cero barras"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivado"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sin tarjeta SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Datos móviles"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Activar datos móviles"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Datos móviles desactivados"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"No se configuró para usar datos"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desactivados"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conexión Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Sin tarjeta SIM"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio de proveedor de red"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalles de la batería"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batería <xliff:g id="NUMBER">%d</xliff:g> por ciento"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento; tiempo restante: aproximadamente <xliff:g id="TIME">%2$s</xliff:g> en función del uso"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puede sonar o vibrar en función de la configuración del teléfono. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Retiene tu atención con un acceso directo flotante a este contenido."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Dejar que el sistema determine si esta notificación debe emitir un sonido o una vibración"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece en la parte superior de la sección de conversaciones, en forma de burbuja flotante, y muestra la foto de perfil en la pantalla de bloqueo."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaria"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta app se muestra sobre otras apps en la pantalla y está usando el micrófono y la cámara."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Configuración"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"El sistema silenció la notificación."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ascendió el nivel de esta notificación."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"El sistema descendió el nivel de esta notificación."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"¿Te parece bien?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index 7aa9927..a0a355b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No hay notificaciones"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 2ce2718..1f6a153 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No se ha podido guardar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe desbloquearse para que se pueda guardar la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a intentar hacer la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentaje de batería desconocido."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de cobertura"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de cobertura"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de cobertura"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Cobertura al máximo"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Sin datos"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Una barra de datos"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dos barras de datos"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de datos"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Señal de datos al máximo"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dos barras de WiMAX"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Señal de WiMAX al máximo"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Conexión Ethernet desconectada."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Conexión Ethernet conectada."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"No hay señal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"No conectado"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Ninguna barra"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivado"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Itinerancia"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sin tarjeta SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Datos móviles"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Datos móviles activados"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Datos desactiv."</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"No está establecido para usar los datos"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desactivados"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Compartir conexión por Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"La red VPN está activada."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"No hay tarjeta SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambiando la red del operador"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalles de la batería"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> por ciento de batería"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento de batería (<xliff:g id="TIME">%2$s</xliff:g> aproximadamente según tu uso)"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Es posible que suene o vibre según los ajustes del teléfono. Las conversaciones de <xliff:g id="APP_NAME">%1$s</xliff:g> aparecen como burbujas de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Llama tu atención con un acceso directo flotante a este contenido."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Haz que el sistema determine si con esta notificación el dispositivo debe sonar o vibrar"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se muestra arriba en la sección de conversaciones, como burbuja flotante, y la imagen de perfil aparece en la pantalla de bloqueo"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ajustes"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta aplicación se está mostrando sobre otras aplicaciones en tu pantalla y está usando el micrófono y la cámara."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ajustes"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"El sistema ha silenciado esta notificación."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ha promocionado esta notificación."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"El sistema ha disminuido el nivel de esta notificación."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"¿Estuvo bien?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index f3bab28..4607ad5 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sin notificaciones"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index c11f21c..3e454f2 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Puudutage ekraanipildi vaatamiseks"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekraanipilti ei õnnestunud salvestada"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enne ekraanipildi salvestamist tuleb seade avada"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Proovige ekraanipilt uuesti jäädvustada"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Aku: kolm pulka."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Aku täis."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Aku laetuse protsent on teadmata."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefonisignaal puudub"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonisignaal: üks pulk."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonisignaal: kaks pulka."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonisignaal: kolm pulka."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonisignaal on tugev."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Andmed puuduvad."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Andmesignaal: üks pulk."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Andmeside: kaks pulka."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Andmeside: kolm pulka."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Andmesignaal on tugev."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Ühendatud: <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ühendatud: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Ühendatud ülekandega <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-i on kaks riba."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-i on kolm riba."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-i signaal on tugev."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Etherneti-ühendus on katkestatud."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Etherneti-ühendus on loodud."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Signaal puudub."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ühendus puudub."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Null pulka."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Väljas."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Ühendatud."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ühenduse loomine."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Rändlus"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM-kaarti pole."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiilne andmeside"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiilne andmeside on sees"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiilne andmeside on väljas"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ei ole andmeside kasutamiseks seadistatud"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Väljas"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Jagamine Bluetoothiga."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lennukirežiim."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on sees."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM-kaarti pole."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operaatori võrku muudetakse"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Aku üksikasjade avamine"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Aku: <xliff:g id="NUMBER">%d</xliff:g> protsenti."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Aku protsent <xliff:g id="PERCENTAGE">%1$s</xliff:g>, teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Võib telefoni seadete põhjal heliseda või vibreerida. Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> vestlused kuvatakse vaikimisi mullis."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hoiab teie tähelepanu hõljuva otseteega selle sisu juurde."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laske süsteemil määrata, kas selle märguande puhul peaks esitama heli või vibreerima"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Kuvatakse vestluste jaotise ülaosas hõljuva mullina ja lukustuskuval kuvatakse profiilipilt"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Seaded"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteetne"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"See rakendus kuvatakse teie ekraanil muude rakenduste peal ning see kasutab mikrofoni ja kaamerat."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Seaded"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Selle märguande vaigistas süsteem."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Selle märguande ülendas süsteem."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Selle märguande alandas süsteem."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Kas see oli õige?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Täname tagasiside eest!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml
index c59b5bc..b7039e3 100644
--- a/packages/SystemUI/res/values-et/strings_tv.xml
+++ b/packages/SystemUI/res/values-et/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on ühendatud"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-i ühendus on katkestatud"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"VPN-i <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Märguanded"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Märguandeid pole"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 835449f..5dcfa7f 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Sakatu pantaila-argazkia ikusteko"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ezin izan da gorde pantaila-argazkia"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pantaila-argazkia gordetzeko, gailuak desblokeatuta egon beharko du"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Saiatu berriro pantaila-argazkia ateratzen"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateriak hiru barra ditu."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria beteta dago."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Bateriaren ehunekoa ezezaguna da."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ez dago telefono-zenbakirik."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono-seinaleak barra bat du."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono-seinaleak bi barra ditu."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefono-seinaleak hiru barra ditu."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefono-seinale osoa."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ez dago daturik."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datu-seinaleak barra bat du."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datu-seinaleak bi barra ditu."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datu-seinaleak hiru barra ditu."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datu-seinale osoa."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> sarera konektatuta."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> gailura konektatuta."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Hona konektatuta: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX sarearen bi barra."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX sarearen hiru barra."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX sarearen seinalea osoa."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bidezko konexioa eten da."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet bidez konektatu da."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ez dago seinalerik."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Konektatu gabe."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Barrarik ez."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desaktibatuta."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Konektatuta."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Konektatzen."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Ibiltaritza"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wifia"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Ez dago SIM txartelik."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Datu-konexioa"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Datu-konexioa aktibatuta"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Desaktibatuta dago datu-konexioa"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ez dago ezarrita datuak erabiltzeko"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desaktibatuta"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Konexioa partekatzea (Bluetooth)"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hegaldi-modua"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN eginbidea aktibatuta."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Ez dago SIM txartelik."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operadorearen sarea aldatzen"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Ireki bateriaren xehetasunak"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateriaren karga: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateriak ehuneko <xliff:g id="PERCENTAGE">%1$s</xliff:g> dauka kargatuta. Zure erabilera kontuan izanda, <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen zaizkio."</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera. Modu lehenetsian, <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko elkarrizketak burbuila gisa agertzen dira."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Eduki honetarako lasterbide gainerakor bat eskaintzen dizu, arretarik gal ez dezazun."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ezarri sistemak zehaztu dezala jakinarazpen honek soinua edo dardara egin behar duen ala ez"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Burbuila gisa agertzen da elkarrizketen atalaren goialdean, eta profileko argazkia bistaratzen du pantaila blokeatuta dagoenean"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ezarpenak"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Lehentasuna"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aplikazioa pantailako beste aplikazioen gainean agertzen da, eta mikrofonoa eta kamera erabiltzen ari da."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ezarpenak"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Ados"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Sistemak isilarazi egin du jakinarazpen hau."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Sistemak mailaz igo du jakinarazpen hau."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Sistemak mailaz jaitsi du jakinarazpen hau."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Zuzena al da hau?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Mila esker iritzia emateagatik!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Ados"</string>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index 67cb078..e1c4fcc 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN sarera konektatuta dago"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ez dago sarera konektatuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Jakinarazpenak"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ez dago jakinarazpenik"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 55ca0f3..85a89b3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"نماگرفت ذخیره شد"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"برای مشاهده عکس صفحه‌نمایشتان ضربه بزنید"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"نماگرفت ذخیره نشد"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"برای ذخیره کردن نماگرفت، قفل دستگاه باید باز باشد"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توان نماگرفت را ذخیره کرد"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمی‌دهند نماگرفت بگیرید."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"سه نوار برای باتری."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"باتری پر است."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"درصد شارژ باتری مشخص نیست."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"بدون تلفن."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"یک نوار برای تلفن."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"دو نوار برای تلفن."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"سه نوار برای تلفن."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"قدرت امواج تلفن همراه کامل است."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"داده‌ای وجود ندارد."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"یک نوار برای داده."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"دو نوار برای داده."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"سه نوار برای داده."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"قدرت سیگنال داده کامل است."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"به <xliff:g id="WIFI">%s</xliff:g> متصل شد."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"به <xliff:g id="BLUETOOTH">%s</xliff:g> متصل شد."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"به <xliff:g id="CAST">%s</xliff:g> متصل شد."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‏WiMAX دو نوار دارد."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"‏WiMAX سه نوار دارد."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"‏قدرت سیگنال WiMAX کامل است."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"اترنت قطع شد."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"اترنت متصل شد."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"فاقد سیگنال."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"متصل نیست."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"بدون میله."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"خاموش."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"متصل."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"در حال مرتبط‌ شدن."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+‎"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+‎"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+‎"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"فراگردی"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"بدون سیم کارت."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"داده‌ تلفن همراه"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"داده تلفن همراه روشن"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"داده تلفن همراه خاموش است"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"برای استفاده از داده تنظیم نشده است"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"خاموش"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"اشتراک‌گذاری اینترنت با بلوتوث."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"حالت هواپیما."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN روشن است."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"سیم‌کارتی موجود نیست."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"تغییر شبکه شرکت مخابراتی"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"باز کردن جزئیات باتری"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"باتری <xliff:g id="NUMBER">%d</xliff:g> درصد."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"باتری <xliff:g id="PERCENTAGE">%1$s</xliff:g> درصد شارژ دارد، براساس مصرفتان تقریباً <xliff:g id="TIME">%2$s</xliff:g> شارژ باقی‌مانده است"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"بسته به تنظیمات ممکن است تلفن زنگ بزند یا لرزش داشته باشد. مکالمه‌های <xliff:g id="APP_NAME">%1$s</xliff:g> به‌طور پیش‌فرض در حبابک نشان داده می‌شوند."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"با میان‌بری شناور به این محتوا، توجه‌تان را جلب می‌کند."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"سیستم را تنظیم کنید که تشخیص دهد اعلان صدا و لرزش داشته باشد یا نه"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"در بالای بخش مکالمه به‌صورت حبابک شناور نشان داده می‌شود و تصویر نمایه را در صفحه قفل نمایش می‌دهد"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"تنظیمات"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"این برنامه روی برنامه‌های دیگر در صفحه‌نمایش نشان داده می‌شود و از میکروفون و دوربین استفاده می‌کند."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"تنظیمات"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"تأیید"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"سیستم این اعلان را بی‌صدا کرده است."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"سیستمْ این اعلان را ارتقا داده است."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"سیستمْ این اعلان را تنزل داده است."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"این مورد درست بود؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"از بازخوردتان سپاس‌گزاریم!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"تأیید"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 37aaa64..5ad12df 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏VPN متصل است"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏VPN قطع است"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"اعلان‌ها"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"اعلانی ندارید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index f5441a2..bb17d32 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Napauta katsoaksesi kuvakaappausta"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kuvakaappauksen tallennus epäonnistui"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Laitteen lukitus täytyy avata ennen kuin kuvakaappaus voidaan tallentaa"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Yritä ottaa kuvakaappaus uudelleen."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akun virta - kolme palkkia."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Akku täynnä."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akun varaustaso ei tiedossa."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ei puhelinverkkoyhteyttä."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Puhelinverkkosignaali - yksi palkki."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Puhelinverkkosignaali - kaksi palkkia."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Puhelinverkkosignaali - kolme palkkia."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Vahva puhelinverkkosignaali."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ei datasignaalia."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datasignaali - yksi palkki."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datasignaali - kaksi palkkia."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datasignaali - kolme palkkia"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Vahva kuuluvuus."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Yhteys: <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Yhteys: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Yhdistetty kohteeseen <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: kaksi palkkia."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: kolme palkkia."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Vahva WiMAX-signaali."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet on irrotettu."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet on yhdistetty."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ei signaalia."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ei yhteyttä."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nolla palkkia."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Pois käytöstä."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Yhdistetty."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Yhdistetään."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Ei SIM-korttia."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiilidata"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiilidata käytössä"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiilidata poistettu käytöstä"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ei käytä dataa"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Pois käytöstä"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internetin jakaminen Bluetoothin kautta."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lentokonetila."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN päällä"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Ei SIM-korttia."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operaattorin verkko muuttuu"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Avaa akun tiedot."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akun virta <xliff:g id="NUMBER">%d</xliff:g> prosenttia."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akkua jäljellä <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosenttia eli noin <xliff:g id="TIME">%2$s</xliff:g> käyttösi perusteella"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Voi soida tai väristä puhelimen asetuksista riippuen. Näistä keskusteluista (<xliff:g id="APP_NAME">%1$s</xliff:g>) syntyy oletuksena kuplia."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kelluva sisällön pikakuvake säilyttää huomiosi"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Järjestelmä valitsee, kuuluuko tästä ilmoituksesta ääntä tai väriseekö se"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Näkyy keskusteluosion yläosassa kelluvana kuplana, profiilikuva näkyy lukitusnäytöllä"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Asetukset"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Tärkeä"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Tämä sovellus näkyy näytöllä muiden sovellusten päällä ja käyttää mikrofonia sekä kameraa."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Asetukset"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Järjestelmä hiljensi tämän ilmoituksen."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Järjestelmä nosti tämän ilmoituksen tasoa."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Järjestelmä laski tämän ilmoituksen tasoa."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Oliko tämä oikein?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Kiitos palautteesta!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 295780b..61cd5ab 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on yhdistetty"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ei ole yhdistettynä"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ilmoitukset"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ei ilmoituksia"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6b598da..897a475 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Touchez pour afficher votre capture d\'écran"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"L\'appareil doit être déverrouillé avant qu\'une capture d\'écran puisse être enregistrée"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de faire une autre capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la pile inconnu."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal : bon"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal excellent"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Aucun signal"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal faible"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal moyen"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal bon"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal excellent"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connecté à : <xliff:g id="WIFI">%s</xliff:g>"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connecté à <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX : moyen"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX : bon"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX : excellent"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet déconnecté."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connecté."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Aucun signal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Non connecté"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Aucun signal"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Désactivé"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connecté"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connexion."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Itinérance"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Aucune carte SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Données cellulaires"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Données cellulaires activées"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Désactivées"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Non configuré pour l\'utilisation des données cellulaires"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Désactivé"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Partage de connexion Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"RPV activé."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Aucune carte SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Changer de réseau de fournisseur de services"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Ouvrir les détails de la pile"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Pile : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pile chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent (environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie en fonction de votre usage)"</string>
@@ -329,7 +305,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>
@@ -405,7 +380,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>
@@ -498,7 +472,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>
@@ -725,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer, selon les paramètres du téléphone. Conversations des bulles de <xliff:g id="APP_NAME">%1$s</xliff:g> par défaut."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Garde votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faire en sorte que le système détermine si cette notification devrait émettre un son ou vibrer"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations sous forme de bulle flottante et affiche la photo du profil sur l\'écran de verrouillage"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
@@ -743,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Cette application superpose du contenu par-dessus d\'autres applications à l\'écran et utilise le microphone et l\'appareil photo."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Paramètres"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Cette notification a été désactivée par le système."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Cette notification a été promue par le système."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Cette notification a été rétrogradée par le système."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Était-ce correct?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Merci de vos commentaires!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
@@ -773,12 +759,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>
@@ -1020,7 +1004,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-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index 696e959..a667d76 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"RPV connecté"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"RPV déconnecté"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b9fa28c..d756991 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Appuyez pour voir la capture d\'écran"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Vous devez déverrouiller l\'appareil pour que la capture d\'écran soit enregistrée"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la batterie inconnu."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal : bon"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal excellent"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Aucun signal"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal faible"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal moyen"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal bon"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal excellent"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connecté à : <xliff:g id="WIFI">%s</xliff:g>"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connecté à <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX : moyen"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX : bon"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX : excellent"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet déconnecté"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connecté"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Aucun signal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Non connecté"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Aucun signal"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Désactivé"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connecté"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connexion en cours…"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Itinérance"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Aucune carte SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Données mobiles"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Données mobiles activées"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Désactivées"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Non configuré pour utiliser les données"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Désactivées"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Partage de connexion Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Le VPN est activé."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Aucune carte SIM"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Modification du réseau de l\'opérateur"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Ouvrir les détails de la batterie"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batterie : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterie chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent : il reste environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie, selon votre utilisation"</string>
@@ -329,7 +305,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>
@@ -405,7 +380,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>
@@ -498,7 +472,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>
@@ -725,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer en fonction des paramètres du téléphone. Les conversations provenant de <xliff:g id="APP_NAME">%1$s</xliff:g> s\'affichent sous forme de bulles par défaut."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Attire votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laisser le système déterminer si cette notification doit être accompagnée d\'un son ou d\'une vibration"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations, apparaît sous forme de bulle flottante, affiche la photo de profil sur l\'écran de verrouillage"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
@@ -743,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Cette application se superpose aux autres applications sur l\'écran, et utilise le micro et la caméra."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Paramètres"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Le son de cette notification a été coupé par le système."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Cette notification a été mise en avant par le système."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Cette notification a été rétrogradée par le système."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Est-ce que c\'était correct ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Merci de nous avoir envoyé vos commentaires."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
@@ -773,12 +759,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>
@@ -1020,7 +1004,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-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index f2c5d97..25fab4e 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connecté"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN déconnecté"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 6cf18b8..abfdf6b 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver a captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Non se puido gardar a captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que se poida gardar a captura de pantalla, o dispositivo debe estar desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Volve tentar crear unha captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batería cargada"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Descoñécese a porcentaxe da batería."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sen teléfono"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Unha barra de cobertura"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dúas barras de cobertura"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de cobertura"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Cobertura ao máximo"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Sen datos"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Unha barra de sinal de datos"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Sinal de datos: dúas barras"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de sinal de datos"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de datos: completo"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Dispositivo conectado: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dúas barras de WiMAX"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal completo de WiMAX"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Desconectouse a Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Conectouse a Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sen sinal"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Non conectada"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Ningunha barra"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivada"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Itinerancia"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sen SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Datos móbiles"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Os datos móbiles están activados"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Os datos móbiles están desactivados"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Non se configurou para utilizar datos"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desactivado"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conexión compartida por Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"A VPN está activada."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Non hai tarxeta SIM"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio de rede do operador"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir os detalles da batería"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Carga da batería: <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, durará <xliff:g id="TIME">%2$s</xliff:g> co uso que adoitas darlle"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Podería soar ou vibrar en función da configuración do teléfono. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantén a túa atención cun atallo flotante a este contido."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai que o sistema determine se a notificación debe emitir un son ou unha vibración"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Móstranse na parte superior da sección de conversas en forma de burbulla flotante e aparece a imaxe do perfil na pantalla de bloqueo"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta aplicación móstrase sobre outras aplicacións da pantalla e está utilizando o micrófono e a cámara."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Configuración"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"O sistema silenciou esta notificación."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"O sistema subiu o nivel desta notificación."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"O sistema diminuíu o nivel desta notificación."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"A información era correcta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Grazas polo teu comentario"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index 095386b..cd12b94 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacións"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Non hai notificacións"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 35d4e1a..a4562aa 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"સ્ક્રીનશૉટ સાચવી શક્યાં નથી"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"સ્ક્રીનશૉટ સાચવવામાં આવે તે પહેલાં ડિવાઇસને અનલૉક કરવું જરૂરી છે"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"બૅટરી ત્રણ બાર."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"બૅટરી પૂર્ણ."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"બૅટરીની ટકાવારી અજાણ છે."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"કોઈ ફોન નથી."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ફોન એક બાર."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ફોન બે બાર."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ફોન ત્રણ બાર."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"પૂર્ણ ફોન સિગ્નલ."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"કોઈ ડેટા નથી."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ડેટા એક બાર."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ડેટા બે બાર."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ડેટા ત્રણ બાર."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ડેટા સિગ્નલ પૂર્ણ."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> થી કનેક્ટ થયેલું છે."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> થી કનેક્ટ થયાં."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> થી કનેક્ટ કરેલ."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX બે બાર."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ત્રણ બાર."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"પૂર્ણ WiMAX સિગ્નલ."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ઇથરનેટ કનેક્ટ થયું."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"કોઈ સિગ્નલ નથી."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"કનેક્ટ થયેલ નથી."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"શૂન્ય બાર."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"બંધ."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"કનેક્ટ કરી"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"કનેક્ટ થઈ રહ્યું છે."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"રોમિંગ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"વાઇ-ફાઇ"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"સિમ નથી."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"મોબાઇલ ડેટા"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"મોબાઇલ ડેટા ચાલુ છે"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"મોબાઇલ ડેટા બંધ છે"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"બંધ કરો"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"બ્લૂટૂથ ટિથરિંગ."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"એરપ્લેન મોડ."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ચાલુ છે."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"કોઈ સિમ કાર્ડ નથી."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"કૅરીઅર નેટવર્કમાં ફેરફાર થઈ રહ્યો છે"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"બૅટરીની વિગતો ખોલો"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"બૅટરી <xliff:g id="NUMBER">%d</xliff:g> ટકા."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"તમારા વપરાશના આધારે બૅટરી <xliff:g id="PERCENTAGE">%1$s</xliff:g> ટકા, જે લગભગ <xliff:g id="TIME">%2$s</xliff:g> સુધી ચાલે તેટલી બચી છે"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ફોન સેટિંગના આધારે રિંગ અથવા વાઇબ્રેટ થઈ શકે છે. ડિફૉલ્ટ તરીકે <xliff:g id="APP_NAME">%1$s</xliff:g> બબલની વાતચીત."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ફ્લોટિંગ શૉર્ટકટથી આ કન્ટેન્ટ પર તમારું ધ્યાન દોરી રાખે છે."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"આ નોટિફિકેશન સાઉન્ડ અથવા વાઇબ્રેટ કરી શકશે કે નહીં તે સિસ્ટમને નક્કી કરવા દો"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"એને વાતચીત વિભાગની ટોચ પર બતાવે છે, તરતા બબલ તરીકે દેખાય છે, લૉક સ્ક્રીન પર પ્રોફાઇલ ફોટા તરીકે બતાવે છે"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"સેટિંગ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"પ્રાધાન્યતા"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"આ ઍપ તમારી સ્ક્રીન પરની અન્ય ઍપની ઉપર પ્રદર્શિત થઈ રહી છે અને માઇક્રોફોન અને કૅમેરાનો ઉપયોગ કરી રહી છે."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"સેટિંગ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ઓકે"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા સાઇલન્ટ કરવામાં આવ્યું હતું."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા બઢતી આપવામાં આવી હતી."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા ડિમોટ કરવામાં આવ્યું હતું."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"શું આ યોગ્ય હતું?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"તમારા પ્રતિસાદ બદલ આભાર!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ઓકે"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"સામાન્ય સંદેશા"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"સ્ટોરેજ"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"હિન્ટ"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ઝટપટ ઍપ્લિકેશન"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ચાલી રહી છે"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે. વધુ જાણવા માટે ટૅપ કરો."</string>
diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml
index 297b6e1a..a53e983 100644
--- a/packages/SystemUI/res/values-gu/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN કનેક્ટ કરેલું છે"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ડિસ્કનેક્ટ કરેલું છે"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"નોટિફિકેશન"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"કોઈ નોટિફિકેશન નથી"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1d02fd0..6cde262 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"अपना स्क्रीनशॉट देखने के लिए टैप करें"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव नहीं किया जा सका"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव करने के लिए डिवाइस का अनलॉक होना ज़रूरी है"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"बैटरी तीन बार."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"बैटरी पूरी है."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"कोई फ़ोन नहीं."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फ़ोन एक बार."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फ़ोन दो बार."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तीन बार."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फ़ोन सि‍ग्‍नल पूरा."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"कोई डेटा नहीं."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटा एक बार."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दो बार."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तीन बार."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा सि‍ग्‍नल पूरा."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> से कनेक्ट किया गया."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> से कनेक्ट किया गया."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> से कनेक्ट है."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX दो बार."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX तीन बार."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX सि‍ग्‍नल पूरा है."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ईथरनेट डिस्‍कनेक्‍ट किया गया."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ईथरनेट कनेक्‍ट किया गया."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"कोई सिग्नल नहीं."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"कनेक्ट नहीं है."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य बार."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"बंद."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"कनेक्ट है."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"कनेक्ट हो रहा है."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3जी"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"एलटीई"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"रोमिंग"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"वाई-फ़ाई"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"कोई सिम नहीं."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा चालू है"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा बंद है"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"बंद है"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लूटूथ से टेदरिंग."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाई जहाज़ मोड."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN चालू."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"कोई सिम कार्ड नहीं है."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का नेटवर्क बदल रहा है"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"बैटरी का विवरण खोलें"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> प्रति‍शत बैटरी."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत बैटरी बची है और आपके इस्तेमाल के हिसाब से यह <xliff:g id="TIME">%2$s</xliff:g> में खत्म हो जाएगी"</string>
@@ -724,6 +700,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है. <xliff:g id="APP_NAME">%1$s</xliff:g> में होने वाली बातचीत, डिफ़ॉल्ट रूप से बबल के तौर पर दिखती है."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ़्लोट करने वाले शॉर्टकट की मदद से इस सामग्री पर आपका ध्यान बना रहता है."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"सिस्टम को यह तय करने की अनुमति दें कि इस सूचना के मिलने पर आवाज़ हो या वाइब्रेशन हो"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"इससे बातचीत, सेक्शन में सबसे ऊपर और फ़्लोटिंग बबल के तौर पर दिखती है. साथ ही, लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखती है"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिंग"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
@@ -742,9 +726,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यह ऐप्लिकेशन आपकी स्क्रीन पर इस्तेमाल हो रहे दूसरे ऐप्लिकेशन के ऊपर दिखाया जा रहा है. इसके साथ ही यह माइक्रोफ़ोन और कैमरे का भी इस्तेमाल कर रहा है."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"सेटिंग"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ठीक है"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर, इस सूचना के मिलने पर होने वाली आवाज़ बंद कर दी है."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर यह तय किया है कि कोई सूचना, खोज के क्रम में एकदम नीचे दिखेगी या फिर बिना आवाज़ किए मिलेगी."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर यह तय किया है कि कोई सूचना, खोज के क्रम में एकदम नीचे दिखेगी या फिर बिना आवाज़ किए मिलेगी."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"आपको यह सुविधा कैसी लगी?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"सुझाव या शिकायत के लिए धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ठीक है"</string>
@@ -937,7 +926,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"सामान्य संदेश"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"जगह"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"संकेत"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"झटपट ऐप्लिकेशन"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चल रहा है"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है. ज़्यादा जानने के लिए टैप करें."</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index d2ce7a9..fedaae3 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"वीपीएन कनेक्ट हो गया है"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"वीपीएन डिसकनेक्ट हो गया है"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाएं"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कोई सूचना नहीं है"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9c4939c..3b25e38 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste vidjeli snimku zaslona"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snimka zaslona nije spremljena"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora biti otključan da bi se snimka zaslona mogla spremiti"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo napraviti snimku zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija tri stupca."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak baterije nije poznat."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal jedan stupac."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal dva stupca."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonski signal tri stupca."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonski signal pun."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Podatkovni signal jedan stupac."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Podatkovni signal dva stupca."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Podatkovni signal tri stupca."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Podatkovni signal pun."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Spojen na <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Spojen na <xliff:g id="BLUETOOTH">%s</xliff:g> ."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Povezani ste sa sljedećim uređajem: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX s dva stupca."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX s tri stupca."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX potpun je."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Prekinuta je veza s ethernetom."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Uspostavljena je veza s ethernetom."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nijedan stupac."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G i više"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilni podaci"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilni su podaci uključeni"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilni su podaci isključeni"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije postavljeno za upotrebu podataka"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Posredno povezivanje Bluetootha."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u zrakoplovu"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promjena mreže mobilnog operatera"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Otvaranje pojedinosti o bateriji"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Možda će zvoniti ili vibrirati, ovisno o postavkama telefona. Razgovori iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> prikazuju se u oblačiću prema zadanim postavkama."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Održava vam pozornost pomoću plutajućeg prečaca ovom sadržaju."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sustav odredi treba li obavijest najaviti zvukom ili vibracijom"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se pri vrhu odjeljka razgovora kao pomični oblačić i prikazuje profilnu sliku na zaključanom zaslonu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova se aplikacija prikazuje preko drugih aplikacija na zaslonu i upotrebljava mikrofon i kameru."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Postavke"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"U redu"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Ovu obavijest utišao je sustav."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Ovu obavijest promovirao je sustav."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Ovu obavijest degradirao je sustav."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Je li to bilo točno?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Zahvaljujemo na povratnim informacijama!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"U redu"</string>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index ee29a6c..3bfdf70 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je spojen"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN je isključen"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavijesti"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavijesti"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2feb1b2..e7ee331 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Koppintson a képernyőkép megtekintéséhez"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nem sikerült a képernyőkép mentése"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Az eszközt fel kell oldani a képernyőkép mentése előtt"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Próbálja meg újra elkészíteni a képernyőképet"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nem menthet képernyőképet, mert kevés a tárhely"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akkumulátor három sáv."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Akkumulátor feltöltve."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Az akkumulátor töltöttségi szintje ismeretlen."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nincs telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon egy sáv."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon két sáv."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon három sáv."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonjel megtelt."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nincsenek adatok."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Adat egy sáv."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Adat két sáv."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Adat három sáv."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Adatjel teljes."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Csatlakoztatva a következőhöz: <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Csatlakoztatva a következőhöz: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Csatlakozva a következőhöz: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-jel: két sáv."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-jel: három sáv."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-jel: teljes."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet leválasztva."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet csatlakoztatva."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nincs jel."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nincs csatlakozva."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nincs sáv."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Kikapcsolva."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Csatlakoztatva."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Csatlakozás."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nincs SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiladatok"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiladatok bekapcsolva"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiladatok kikapcsolva"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nincs beállítva az adathasználat"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Ki"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth megosztása."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Repülőgép üzemmód."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN bekapcsolva."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nincs SIM-kártya."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Szolgáltatói hálózat váltása"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Az akkumulátorral kapcsolatos részletek megnyitása"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akkumulátor <xliff:g id="NUMBER">%d</xliff:g> százalék."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Az akkumulátor <xliff:g id="PERCENTAGE">%1$s</xliff:g> százalékon áll, a használati adatok alapján körülbelül <xliff:g id="TIME">%2$s</xliff:g> múlva merül le"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"A telefonbeállítások alapján csöröghet és rezeghet. A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásban lévő beszélgetések alapértelmezés szerint buborékban jelennek meg."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"A tartalomra mutató lebegő parancsikon segítségével tartja fenn az Ön figyelmét."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"A rendszer határozza meg, hogy ez az értesítés adjon-e ki hangot, illetve rezegjen-e"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"A beszélgetések szakaszának tetején, lebegő buborékként látható, megjeleníti a profilképet a lezárási képernyőn"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Beállítások"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritás"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ez az alkalmazás a képernyőn lévő egyéb alkalmazások előtt jelenik meg, és használja a mikrofont és a kamerát."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Beállítások"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Ezt az értesítést lenémította a rendszer."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Ezt az értesítést magasabb prioritásra állította a rendszer."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Ezt az értesítést alacsonyabb prioritásra állította a rendszer."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Megfelelő ez így?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Köszönjük a visszajelzést!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index cbbebb0..78d6099 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN-kapcsolat létrejött"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN-kapcsolat megszakadt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A következő szolgáltatás használatával: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Értesítések"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nincs értesítés"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 0258e44..af300ea 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Հպեք՝ սքրինշոթը տեսնելու համար"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Չհաջողվեց պահել սքրինշոթը"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Սքրինշոթը պահելու համար ապակողպեք սարքը։"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Փորձեք նորից"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Մարտկոցի երեք գիծ:"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Մարտկոցը լիքն է:"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Մարտկոցի լիցքի մակարդակն անհայտ է։"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Հեռախոս չկա:"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Հեռախոսի մեկ գիծ:"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Հեռախոսի երկու գիծ:"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Հեռախոսի երեք գիծ:"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Հեռախոսի ազդանշանը լիքն է:"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Տվյալներ չկան:"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Տվյալների մեկ գիծ:"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Տվյալների երկու գիծ:"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Տվյալների երեք գիծ:"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Տվյալների ազդանշանը լրիվ է:"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Միացված է <xliff:g id="WIFI">%s</xliff:g>-ին:"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Միացված է <xliff:g id="BLUETOOTH">%s</xliff:g>-ին:"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Միացված է <xliff:g id="CAST">%s</xliff:g>-ին:"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-ի երկու գիծ:"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-ի երեք գիծ:"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-ի ազդանշանը լիքն է:"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet-ը անջատված է:"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet-ը կապակցված է:"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ազդանշան չկա:"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Միացված չէ:"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Զրո գիծ:"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Անջատված է:"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Միացված է:"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Միանում է:"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Ռոումինգ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM չկա:"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Բջջային ինտերնետ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Բջջային տվյալները միացված են"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Բջջային ինտերնետն անջատված է"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Անջատված է"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth մոդեմ"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ավիառեժիմ"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Միացնել VPN-ը։"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM քարտ չկա:"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Օպերատորի ցանցի փոփոխություն"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Բացել մարտկոցի տվյալները"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$s</xliff:g> տոկոս է և կբավարարի մոտ <xliff:g id="TIME">%2$s</xliff:g>՝ կախված օգտագործման եղանակից:"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Կարող է զնգալ կամ թրթռալ (հեռախոսի կարգավորումներից կախված)։ <xliff:g id="APP_NAME">%1$s</xliff:g>-ի զրույցներն ըստ կանխադրման հայտնվում են ամպիկների տեսքով։"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Լողացող դյուրանցման միջոցով ձեր ուշադրությունն է գրավում բովանդակության նկատմամբ"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Թող համակարգն ավտոմատ որոշի՝ արդյոք այս ծանուցումը ձայնով, թե թրթռոցով է պետք մատուցել"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ցուցադրվում է զրույցների ցանկի վերևում, հայտնվում է լողացող ամպիկի տեսքով, ցուցադրում է պրոֆիլի նկարը կողպէկրանին"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Կարգավորումներ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Կարևոր"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Այս հավելվածը ցուցադրվում է մյուս հավելվածների վրայից և օգտագործում է խոսափողն ու տեսախցիկը:"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Կարգավորումներ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Եղավ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Այս ծանուցման ձայնն անջատվել է համակարգի կողմից։"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Այս ծանուցման կարևորության մակարդակը բարձրացվել է համակարգի կողմից։"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Այս ծանուցման կարևորության մակարդակը իջեցվել է համակարգի կողմից։"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Սա ճի՞շտ էր"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Շնորհակալություն արձագանքելու համար"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Եղավ"</string>
diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml
index 58c5149..cf4eb90 100644
--- a/packages/SystemUI/res/values-hy/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ը միացված է"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ն անջատված է"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ծանուցումներ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ծանուցումներ չկան"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index bea37ae..0038463 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketuk untuk melihat screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Perangkat harus dibuka kuncinya agar screenshot dapat disimpan"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Coba ambil screenshot lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterai tiga batang."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterai penuh."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Tidak dapat melakukan panggilan."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ponsel satu batang."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Ponsel dua batang."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Ponsel tiga batang."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinyal ponsel penuh."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Tidak ada data yang diterima."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data satu batang."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data dua batang."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tiga batang."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinyal data penuh."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Terhubung ke <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Terhubung ke <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Terhubung ke <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX dua batang."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tiga batang."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinyal WiMAX penuh."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet terputus."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet tersambung."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Tidak ada sinyal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Tidak terhubung."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"0 baris."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Nonaktif."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Tersambung."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Tidak ada SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Data Seluler"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Data Seluler Aktif"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Kuota nonaktif"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Tidak disetel untuk menggunakan data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Nonaktif"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode pesawat."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktif."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Tidak ada kartu SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Jaringan operator berubah"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Membuka detail baterai"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterai <xliff:g id="NUMBER">%d</xliff:g> persen."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterai <xliff:g id="PERCENTAGE">%1$s</xliff:g> persen, sekitar <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Dapat berdering atau bergetar berdasarkan setelan ponsel. Percakapan dari balon <xliff:g id="APP_NAME">%1$s</xliff:g> secara default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Menjaga perhatian dengan pintasan floating ke konten ini."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Biarkan sistem menentukan apakah notifikasi ini akan berbunyi atau bergetar"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Muncul di atas bagian percakapan, ditampilkan sebagai balon yang mengambang, menampilkan gambar profil di layar kunci"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setelan"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritas"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aplikasi ini ditampilkan di atas aplikasi lain di layar serta sedang menggunakan mikrofon dan kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Setelan"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Ya"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Notifikasi ini disenyapkan oleh sistem."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Notifikasi ini dipromosikan oleh sistem."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Notifikasi ini didemosikan oleh sistem."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Sudah benar?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas masukan Anda"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Oke"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index bdd6742..3b446ad 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN tersambung"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tidak Ada Notifikasi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7c7902f..25b907f 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Ýttu til skoða skjámyndina"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekki var hægt að vista skjámynd"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Taka verður tækið úr lás áður en hægt er að vista skjámynd"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prófaðu að taka skjámynd aftur"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Þrjú strik á rafhlöðu."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Rafhlaða fullhlaðin."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Staða rafhlöðu óþekkt."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ekkert símasamband."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Styrkur símasambands er eitt strik."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Styrkur símasambands er tvö strik."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Styrkur símasambands er þrjú strik."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Fullur styrkur símasambands."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Engin gögn."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Sendistyrkur gagnatengingar er eitt strik."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Sendistyrkur gagnatengingar tvö strik."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Sendistyrkur gagnatengingar er þrjú strik."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Fullur sendistyrkur gagnatengingar."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Tengt við <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tengt við <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Tengt við <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: Tvö strik."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: Þrjú strik."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Fullur WiMAX-sendistyrkur."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet aftengt."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet tengt."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ekkert merki."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Engin tenging."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Engin strik."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Slökkt."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Tenging virk."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Tengist."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Reiki"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Ekkert SIM-kort."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Farsímagögn"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Kveikt á farsímagögnum"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Slökkt á farsímagögnum"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ekki stillt á að nota gögn"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Slökkt"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tjóðrun með Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugstilling"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Kveikt á VPN."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Ekkert SIM-kort."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Skiptir um farsímakerfi"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Opna upplýsingar um rafhlöðu"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> prósent á rafhlöðu."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Rafhlaða í <xliff:g id="PERCENTAGE">%1$s</xliff:g> prósentum, um það bil <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun þína"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gæti hringt eða titrað eftir stillingum símans. Samtöl á <xliff:g id="APP_NAME">%1$s</xliff:g> birtast sjálfkrafa í blöðru."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fangar athygli þína með fljótandi flýtileið á þetta efni."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Láta kerfið ákvarða hvort hljóð eða titringur fylgir þessari tilkynningu"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Birtist efst í samtalshluta, birtist sem fljótandi blaðra, birtir prófílmynd á lásskjánum"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Áfram"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Forgangur"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Þetta forrit er að birta efni yfir öðrum forritum á skjánum þínum og er að nota hljóðnemann og myndavélina."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Stillingar"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Í lagi"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Kerfið þaggaði þessa tilkynningu."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Kerfið hækkaði þessa tilkynningu."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Kerfið lækkaði þessa tilkynningu."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Var þetta rétt?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Takk fyrir að segja þína skoðun!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Í lagi"</string>
diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml
index 88a4315..7c23e62 100644
--- a/packages/SystemUI/res/values-is/strings_tv.xml
+++ b/packages/SystemUI/res/values-is/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tengt"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er ekki tengt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Tilkynningar"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Engar tilkynningar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 026b5a9..e393cea 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tocca per visualizzare lo screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossibile salvare lo screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"È necessario sbloccare il dispositivo per poter salvare lo screenshot"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Riprova ad acquisire lo screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteria: tre barre."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batteria carica."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nessun telefono."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono: una barra."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono: due barre."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefono: tre barre."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Massimo segnale telefonico."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nessun dato."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dati: una barra."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dati: due barre."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dati: tre barre."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Massimo segnale dati."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Connesso a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connesso a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Connesso a: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: due barre."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: tre barre."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Massimo segnale WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Connessione Ethernet annullata."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Connessione Ethernet stabilita."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nessun segnale."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Non connesso."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nessuna barra."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Off"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Connesso."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connessione in corso."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nessuna SIM presente."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dati mobili"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dati mobili attivati"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dati mobili disattivati"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Non impostato per l\'utilizzo dei dati"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modalità aereo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN attiva."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nessuna SIM presente."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio della rete dell\'operatore"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Visualizza i dettagli relativi alla batteria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteria: <xliff:g id="NUMBER">%d</xliff:g> percento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Livello della batteria: <xliff:g id="PERCENTAGE">%1$s</xliff:g> percento. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Può suonare o vibrare in base alle impostazioni del telefono. Conversazioni dalla bolla <xliff:g id="APP_NAME">%1$s</xliff:g> per impostazione predefinita."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantiene la tua attenzione con una scorciatoia mobile a questi contenuti."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai stabilire al sistema se questa notifica deve emettere suoni o vibrazioni"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Appare in cima alla sezione delle conversazioni e sotto forma di bolla mobile, mostra l\'immagine del profilo nella schermata di blocco"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Impostazioni"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Questa app è visualizzata sopra altre app sullo schermo e sta utilizzando il microfono e la fotocamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Impostazioni"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Ok"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Questa notifica è stata silenziata dal sistema."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Questa notifica è stata promossa dal sistema."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Questa notifica è stata retrocessa dal sistema."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Era corretto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Grazie per il feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 97badc1..57931b0 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connessa"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN disconnessa"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifiche"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nessuna notifica"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b4df62b..4f30f1f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"אפשר להקיש כדי להציג את צילום המסך"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"לא ניתן היה לשמור צילום מסך"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"כדי שצילום המסך יישמר, צריך לבטל את הנעילה של המכשיר"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"יש לנסות שוב לבצע צילום מסך"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"לא היה מספיק מקום לשמור את צילום המסך"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"שלושה פסים של סוללה."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"סוללה מלאה."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"אחוז טעינת הסוללה לא ידוע."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"אין טלפון."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"פס אחד של טלפון."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"שני פסים של טלפון."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"שלושה פסים של טלפון."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"אות הטלפון מלא."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"אין נתונים."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"פס אחד של נתונים."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"שני פסים של נתונים."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"שלושה פסים של נתונים."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"אות הנתונים מלא."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"מחובר אל <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"מחובר אל <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"מחובר אל <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‏שני פסים של WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"‏שלושה פסים של WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"‏אות ה-WiMAX מלא."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"אתרנט מנותק."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"אתרנט מחובר."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"אין אות."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"אין חיבור."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"אפס פסים."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"כבוי."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"מחובר."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"מתחבר."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"+H"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"+4G"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"+LTE"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"נדידה"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"‏אין כרטיס SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"חבילת גלישה"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"חבילת הגלישה פועלת"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"חבילת הגלישה כבויה"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"לא מוגדרת לשימוש בנתונים"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"כבוי"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"‏שיתוף אינטרנט דרך Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"מצב טיסה"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN פועל."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"‏אין כרטיס SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"רשת ספק משתנה"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"פתיחת פרטי סוללה"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> אחוזים של סוללה."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"רמת הטעינה בסוללה: <xliff:g id="PERCENTAGE">%1$s</xliff:g> אחוזים, הזמן הנותר המשוער על סמך השימוש שלך:<xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ייתכן שיופעל צלצול או רטט בהתאם להגדרות הטלפון. שיחות מהאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מופיעות בבועות כברירת מחדל."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"מעוררת תשומת לב באמצעות קיצור דרך צף לתוכן הזה."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"אפשר לתת למערכת לקבוע אם ההתראה הזאת צריכה להיות מלווה בצליל או ברטט"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"מוצגת בחלק העליון של קטע התראות השיחה, מופיעה בבועה צפה, תוצג תמונת פרופיל במסך הנעילה"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"הגדרות"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"עדיפות"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"האפליקציה הזו מוצגת מעל אפליקציות אחרות במסך, ומשתמשת במיקרופון ובמצלמה."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"הגדרות"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"אישור"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ההתראה הזאת הושתקה על-ידי המערכת."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ההתראה הזאת קודמה על-ידי המערכת."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ההתראה הזאת הורדה בדרגה על-ידי המערכת."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"האם פעולה זו הייתה נכונה?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"תודה על המשוב!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"אישור"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index 45d744a..7483116 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏VPN מחובר"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏VPN מנותק"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"באמצעות <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"התראות"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"אין התראות"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index be6f491..baca136 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"タップしてスクリーンショットを表示します"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"スクリーンショット保存エラー"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"スクリーンショットを保存するには、デバイスのロックを解除する必要があります"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"空き容量が足りないため、スクリーンショットを保存できません"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池残量:レベル3"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"電池残量:満"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池残量は不明です。"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"電波状態:なし"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電波状態:レベル1"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電波状態:レベル2"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電波状態:レベル3"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電波状態:フル"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"データ信号:なし"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"データ信号:レベル1"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"データ信号:レベル2"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"データ信号:レベル3"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"データ信号:フル"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>に接続しました。"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>に接続しました。"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>に接続されています。"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX電波状態:レベル2"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX電波状態:レベル3"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX電波状態:フル"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"イーサネット接続を解除しました。"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"イーサネットに接続しました。"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"圏外です。"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"接続されていません。"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"レベル0"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"OFF"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"接続済みです。"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"接続しています。"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ローミング"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIMがありません。"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"モバイルデータ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"モバイルデータ ON"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"モバイルデータ OFF"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"データを使用するように設定されていません"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"OFF"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetoothテザリング。"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"機内モード。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN は ON です。"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIMカードが挿入されていません。"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"携帯通信会社のネットワークを変更します"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"電池の詳細情報を開きます"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"電池残量: <xliff:g id="NUMBER">%d</xliff:g>パーセント"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"電池残量: <xliff:g id="PERCENTAGE">%1$s</xliff:g>、およそ <xliff:g id="TIME">%2$s</xliff:g> に電池切れ(使用状況に基づく)"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります。デフォルトでは <xliff:g id="APP_NAME">%1$s</xliff:g> からの会話がバブルとして表示されます。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"このコンテンツのフローティング ショートカットで通知をお知らせします。"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"この通知を音またはバイブレーションで知らせるかどうかの自動判断"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"会話セクションの一番上にバブルとして表示され、プロフィール写真がロック画面に表示されます"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"このアプリは画面上で他のアプリの上に重ねて表示されます。また、マイクとカメラを使用しています。"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"この通知はシステムによってサイレントに設定されました。"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"この通知はシステムによって順位が上げられました。"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"この通知はシステムによって順位が下げられました。"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"間違いありませんか?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"フィードバックをお寄せいただきありがとうございます。"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 9d7a36a..7f676b5 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN に接続しました"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN に接続していません"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"通知はありません"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 6fdb8b8..d11c302 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"შეეხეთ ეკრანის ანაბეჭდის სანახავად"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"მოწყობილობა უნდა განიბლოკოს ეკრანის ანაბეჭდის შენახვა რომ შეძლოთ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ბატარეა სამ ზოლზე."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ბატარეა სავსეა."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ბატარეის პროცენტული მაჩვენებელი უცნობია."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ტელეფონი არ არის."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ტელეფონის სიგნალი სრულია."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"მონაცემები არ არის."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"თარიღი ზოლზე."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"მონაცემების გადაცემა: ორი ზოლი"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"მონაცემების გადაცემა: სამი ზოლი"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"დაკავშირებულია <xliff:g id="WIFI">%s</xliff:g>-თან."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"დაკავშირებულია <xliff:g id="BLUETOOTH">%s</xliff:g>-თან."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"დაკავშირებულია მოწყობილობასთან: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-ის ორი ზოლი."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-ის სამი ზოლი."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX სიგნალი სრულია."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet კავშირი შეწყვეტილია."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet დაკავშირებულია."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"სიგნალი არ არის."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"არ არის დაკავშირებული."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"სიგნალი ნულ ზოლზეა."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"გამორთულია."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"დაკავშირებულია."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"უკავშირდება."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"როუმინგი"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM არ არის."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"მობილური ინტერნეტი"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"მობილური ინტერნეტი ჩართულია"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"მობილური ინტერნეტი გამორთულია"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"გამორთული"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth ტეტერინგის ჩართვა"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"თვითმფრინავის რეჟიმი"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ჩართულია."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM ბარათი არ არის."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"ოპერატორის ქსელის შეცვლა"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ბატარეის დეტალების გახსნა"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ბატარეა: <xliff:g id="NUMBER">%d</xliff:g> პროცენტი."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ბატარეა <xliff:g id="PERCENTAGE">%1$s</xliff:g> პროცენტზეა, მოხმარების გათვალისწინებით დარჩა დაახლოებით <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით. მიმოწერები <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ბუშტიდან, ნაგულისხმევად."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"იპყრობს თქვენს ყურადღებას ამ კონტენტის მოლივლივე მალსახმობით."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"სისტემისთვის ისეთი უფლების მინიჭება, რომ მან განსაზღვროს, ამ შეტყობინებამ ხმოვანი სიგნალი უნდა აამოქმედოს თუ ვიბრაცია"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"გამოჩნდება მიმოწერების ზედა ნაწილში ბუშტის სახით, აჩვენებს პროფილის სურათს ჩაკეტილ ეკრანზე"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"პარამეტრები"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"პრიორიტეტი"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ეს აპი თქვენს ეკრანზე ფარავს სხვა აპებს და იყენებს მიკროფონსა და კამერას."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"პარამეტრები"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"კარგი"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ეს შეტყობინება სისტემის მიერ არის ჩაჩუმებული."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ამ შეტყობინების მნიშვნელობა სისტემის მიერ არის აწეული."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ამ შეტყობინების მნიშვნელობა სისტემის მიერ არის დაწეული."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"სწორია ეს?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"გმადლობთ გამოხმაურებისთვის!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"კარგი"</string>
diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml
index 0dc1e10..0819781 100644
--- a/packages/SystemUI/res/values-ka/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN დაკავშირებულია"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN გათიშულია"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"შეტყობინებები"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"შეტყობინებები არ არის"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index df86e8a..55552e9 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотты көру үшін түртіңіз"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сақталмады"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншот сақталуы үшін, құрылғы құлпын ашу керек."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Қайта скриншот жасап көріңіз"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батарея үш баған."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея толы."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея зарядының мөлшері белгісіз."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон жоқ."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон бір баған."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон екі баған."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон үш баған."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Телефон сигналы толық."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Дерекқор жоқ."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Дерекқор бір баған."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дерекқор екі баған."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Дерекқор үш баған."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Дерекқор сигналы толы."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> қосылған."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> қосылған."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> трансляциясына қосылды."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX екі жолақ."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX үш жолақ."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигналы толық."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet ажыратылған."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet қосылған."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Сигнал жоқ."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Жалғанбаған."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Нөл жолақ."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Өшірулі."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Жалғанған."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Қосылуда."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM жоқ."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобильдік дерекқор"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобильдік деректер қосулы"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобильдік деректер өшірулі"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Деректерді пайдалануға реттелмеген."</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Өшірулі"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth тетеринг."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ұшақ режимі."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN қосулы."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM картасы жоқ."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Оператор желісін өзгерту"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Батарея мәліметтерін ашу"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарея заряды: <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз. Пайдалануға байланысты шамамен <xliff:g id="TIME">%2$s</xliff:g> уақытқа жетеді."</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін. <xliff:g id="APP_NAME">%1$s</xliff:g> чаттары әдепкісінше қалқымалы етіп көрсетіледі."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Осы мазмұнға бекітілген қалқымалы таңбашамен назарыңызды өзіне тартады."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Хабарландыру дыбысының немесе дірілдің қосылуын жүйе анықтайтын болады"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Әңгімелер бөлімінің жоғарғы жағында тұрады, қалқыма хабар түрінде шығады, құлыптаулы экранда профиль суретін көрсетеді"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Параметрлер"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Бұл қолданба экранда басқа қолданбалардың үстінен көрсетіліп тұр және ол микрофон мен камераны пайдалануда."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Параметрлер"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Жарайды"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Хабарландырудың дыбысы жүйе арқылы өшірілген."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Хабарландырудың күйі жүйе арқылы көтерілген."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Хабарландырудың күйі жүйе арқылы түсірілген."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Барлығы дұрыс па?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Пікіріңіз үшін рақмет!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Жарайды"</string>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index cc15978..768e3ac 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN қосылған"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылған"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Хабарландырулар"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Хабарландырулар жоқ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index e559c19..5885383 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ចុច​ដើម្បីមើល​រូបថតអេក្រង់​របស់អ្នក"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់បានទេ"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ត្រូវតែ​ដោះសោ​ឧបករណ៍​ជាមុនសិន ទើបអាច​រក្សាទុក​រូបថតអេក្រង់​បាន"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"សាកល្បង​ថតរូបថត​អេក្រង់​ម្តងទៀត"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"មិនអាច​រក្សាទុក​រូបថតអេក្រង់​បានទេ ​ដោយសារ​ទំហំផ្ទុក​មានកម្រិតទាប"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថត​រូបអេក្រង់​មិនត្រូវ​បាន​អនុញ្ញាត​ដោយ​កម្មវិធី​នេះ ឬ​ស្ថាប័ន​របស់អ្នក"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ថ្ម​ទាំង​បី​​កាំ​។"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ថ្ម​ពេញ​ហើយ។"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"មិនដឹងអំពី​ភាគរយថ្មទេ។"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"គ្មាន​ទូរស័ព្ទ។"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"សេវា​ទូរស័ព្ទ​មួយ​កាំ។"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"សេវា​ទូរស័ព្ទ​ពីរ​កាំ។"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"សេវា​ទូរស័ព្ទ​បី​កាំ​។"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"សេវា​ទូរស័ព្ទ​ពេញ។"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"គ្មាន​ទិន្នន័យ​។"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ទិន្នន័យ​មួយ​​កាំ។"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ទិន្នន័យ​ពីរ​​កាំ។"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ទិន្នន័យ​បី​កាំ។"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"សញ្ញា​ទិន្នន័យ​ពេញ។"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"បាន​ភ្ជាប់​ទៅ <xliff:g id="WIFI">%s</xliff:g> ។"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"បាន​ភ្ជាប់​ទៅ <xliff:g id="BLUETOOTH">%s</xliff:g> ។"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"បានភ្ជាប់ទៅ <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ពីរ​កាំ។"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX បី​កាំ។"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"សញ្ញា WiMAX ពេញ។"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"បានភ្ជាប់អ៊ីសឺរណិត។"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"គ្មាន​សញ្ញា។"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"មិន​បាន​តភ្ជាប់​។"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"សូន្យ​កាំ។"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"បិទ"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"បាន​តភ្ជាប់។"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ការ​ភ្ជាប់​។"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"រ៉ូ​មីង"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"គ្មាន​ស៊ីម​កាត។"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ទិន្នន័យទូរសព្ទចល័តបានបើក"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ទិន្នន័យ​ទូរសព្ទចល័ត​បានបិទ"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"មិនបានកំណត់​ឱ្យប្រើ​ទិន្នន័យ​ទេ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"បិទ"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ការ​ភ្ជាប់​តាមប៊្លូធូស"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"បើក VPN ។"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"គ្មានស៊ីមកាតទេ។"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"បណ្តាញ​ក្រុមហ៊ុនសេវាទូរសព្ទ​កំពុងផ្លាស់ប្តូរ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"បើកព័ត៌មានលម្អិតអំពីថ្ម"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ថ្ម <xliff:g id="NUMBER">%d</xliff:g> ភាគរយ។"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ថ្ម <xliff:g id="PERCENTAGE">%1$s</xliff:g> ភាគរយ អាចប្រើបាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត ផ្អែក​លើការ​ប្រើប្រាស់​របស់អ្នក"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"អាចរោទ៍ ឬញ័រ ដោយផ្អែកលើ​ការកំណត់​ទូរសព្ទ។ ការសន្ទនា​ពី​ពពុះ <xliff:g id="APP_NAME">%1$s</xliff:g> តាម​លំនាំដើម​។"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ធ្វើឱ្យអ្នក​ចាប់អារម្មណ៍​ដោយប្រើ​ផ្លូវកាត់​អណ្ដែត​សម្រាប់ខ្លឹមសារនេះ។"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ឱ្យប្រព័ន្ធកំណត់ថាតើ​ការជូនដំណឹងនេះ​គួរតែបន្លឺសំឡេង ឬញ័រ"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"បង្ហាញនៅខាងលើ​ផ្នែកសន្ទនា បង្ហាញជា​ពពុះអណ្ដែត បង្ហាញ​រូបភាព​កម្រងព័ត៌មាន​នៅលើ​អេក្រង់ចាក់សោ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ការកំណត់"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"អាទិភាព"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"កម្មវិធីនេះ​កំពុងបង្ហាញ​ពីលើកម្មវិធី​ផ្សេងទៀត​នៅលើអេក្រង់​របស់អ្នក និងកំពុងប្រើ​មីក្រូហ្វូន ក៏​ដូចជា​​កាមេរ៉ា។"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ការកំណត់"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"យល់ព្រម"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ការជូនដំណឹងនេះ​ត្រូវបានបិទសំឡេង​ដោយប្រព័ន្ធ។"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ការជូនដំណឹងនេះ​ត្រូវបាន​ដំឡើងតំណែង​ដោយប្រព័ន្ធ។"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ការជូនដំណឹងនេះ​ត្រូវបានបន្ទាបតំណែងដោយប្រព័ន្ធ។"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"តើវា​ត្រឹមត្រូវទេ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"សូមអរគុណចំពោះ​មតិកែលម្អ​របស់អ្នក!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"យល់ព្រម"</string>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index f415a66..0dec2d6 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ត្រូវបានភ្ជាប់"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ត្រូវបានផ្ដាច់"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាម​រយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ការ​ជូនដំណឹង"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"គ្មាន​ការជូនដំណឹងទេ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index f121080..0b3c4e3 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸುವ ಮೊದಲು ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಬೇಕು"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ಬ್ಯಾಟರಿ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ಬ್ಯಾಟರಿ ಭರ್ತಿಯಾಗಿದೆ."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ಫೋನ್ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ಫೋನ್ ಸಂಕೇತ ಪೂರ್ತಿ ಇದೆ."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ಯಾವುದೇ ಡೇಟಾ ಇಲ್ಲ."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ಡೇಟಾ ಒಂದು ಪಟ್ಟಿ."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ಡೇಟಾ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ಡೇಟಾ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ಡೇಟಾ ಸಂಕೇತ ತುಂಬಿದೆ."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ಎರಡು ಪಟ್ಟಿಗಳು."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ಮೂರು ಪಟ್ಟಿಗಳು."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ಸಿಗ್ನಲ್‌ ಪೂರ್ತಿ ಇದೆ."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ಸಂಕೇತವಿಲ್ಲ."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ಶೂನ್ಯ ಪಟ್ಟಿಗಳು."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ಆಫ್."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ಸಂಪರ್ಕಗೊಳ್ಳುತ್ತಿದೆ."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ರೋಮಿಂಗ್"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ವೈ-ಫೈ"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ಯಾವುದೇ ಸಿಮ್‌ ಇಲ್ಲ."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ಮೊಬೈಲ್ ಡೇಟಾ ಆನ್"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ಆಫ್"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ಬ್ಲೂಟೂತ್‌‌ ಟೆಥರಿಂಗ್."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ಏರೋಪ್ಲೇನ್‌ ಮೋಡ್‌"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ನಲ್ಲಿ VPN"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"ಯಾವುದೇ ಸಿಮ್‌ ಇಲ್ಲ."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"ವಾಹಕ ನೆಟ್‌ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ಬ್ಯಾಟರಿ ವಿವರಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ಬ್ಯಾಟರಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರತಿಶತ."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಬ್ಯಾಟರಿಯು ಪ್ರತಿಶತ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ರಷ್ಟು ಮತ್ತು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಆಧರಿಸಿ ಫೋನ್ ರಿಂಗ್ ಅಥವಾ ವೈಬ್ರೇಟ್ ಆಗುತ್ತದೆ. ಡಿಫಾಲ್ಟ್ ಆಗಿ, <xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಬಬಲ್ ಸಂಭಾಷಣೆಗಳು."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ಈ ವಿಷಯಕ್ಕೆ ಲಿಂಕ್ ಮಾಡಿ ಕೊಂಡೊಯ್ಯುವ ಶಾರ್ಟ್‌ಕಟ್‌ ಕಡೆಗೆ ಗಮನ ಇರಿಸಿ."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ಈ ಅಧಿಸೂಚನೆಯು ಶಬ್ದ ಮಾಡಬೇಕೇ ಅಥವಾ ವೈಬ್ರೇಟ್ ಮಾಡಬೇಕೇ ಎಂಬುದನ್ನು ನಿರ್ಧರಿಸುವ ಅವಕಾಶವನ್ನು ಸಿಸ್ಟಂಗೆ ನೀಡಿ"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೇಲುವ ಬಬಲ್‌ ಆಗಿ ಗೋಚರಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಲಾಕ್‌ಸ್ಕ್ರೀನ್‌ ಮೇಲೆ‌ ಗೋಚರಿಸುತ್ತದೆ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ಆದ್ಯತೆ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೇಲಿಂದ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ಸರಿ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಮೌನಗೊಳಿಸಿದೆ."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಮೇಲ್ದರ್ಜೆಗೆ ಏರಿಸಿದೆ."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಕೆಳದರ್ಜೆಗೆ ಇಳಿಸಿದೆ."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ಇದು ಸರಿಯಾಗಿತ್ತೇ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಗೆ ಧನ್ಯವಾದಗಳು!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ಸರಿ"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"ಸಂಗ್ರಹಣೆ"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"ಸುಳಿವುಗಳು"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ಇನ್‌ಸ್ಟಂಟ್ ಆ್ಯಪ್‌ಗಳು"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index a935963..ef10e3a 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 6db40c1..e39ffaa 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"스크린샷을 확인하려면 탭하세요"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"스크린샷을 저장할 수 없음"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"스크린샷을 저장하려면 기기를 잠금 해제해야 합니다."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"스크린샷을 다시 찍어 보세요."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"배터리 막대가 세 개입니다."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"배터리 충전이 완료되었습니다."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"배터리 잔량을 알 수 없습니다."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"휴대전화의 신호가 없습니다."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"휴대전화 신호 막대가 하나입니다."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"휴대전화 신호 막대가 두 개입니다."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"휴대전화 신호 막대가 세 개입니다."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"휴대전화의 신호가 강합니다."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"데이터가 없습니다."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"데이터 신호 막대가 하나입니다."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"데이터 신호 막대가 두 개입니다."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"데이터 신호 막대가 세 개입니다."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"데이터 신호가 강합니다."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>에 연결되었습니다."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>에 연결되었습니다."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>에 연결됨"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 신호 막대가 두 개입니다."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 신호 막대가 세 개입니다."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 신호가 강합니다."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"이더넷에서 연결 해제되었습니다."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"이더넷에 연결되었습니다."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"신호가 없습니다."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"연결되지 않았습니다."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"신호 막대가 없습니다."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"사용 안함"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"연결됨"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"연결 중..."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G 이상"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"로밍"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM이 없습니다."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"모바일 데이터"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"모바일 데이터 사용"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"모바일 데이터 꺼짐"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"데이터를 사용하도록 설정되지 않음"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"사용 안함"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"블루투스 테더링입니다."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"비행기 모드입니다."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 켜짐"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM 카드가 없습니다."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"이동통신사 네트워크 변경"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"배터리 세부정보 열기"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"배터리 <xliff:g id="NUMBER">%d</xliff:g>퍼센트"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"배터리 <xliff:g id="PERCENTAGE">%1$s</xliff:g>퍼센트, 평소 사용량 기준 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있습니다. 기본적으로 <xliff:g id="APP_NAME">%1$s</xliff:g>의 대화는 대화창으로 표시됩니다."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"이 콘텐츠로 연결되는 플로팅 바로가기로 사용자의 주의를 끕니다."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"시스템에서 알림 시 소리 또는 진동을 사용할지 결정하도록 허용합니다."</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"대화 섹션 상단에 표시, 플로팅 대화창으로 표시, 그리고 잠금 화면에 프로필 사진이 표시됨"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"설정"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"앱이 화면의 다른 앱 위에 표시되고 있으며, 마이크와 카메라를 사용 중입니다.."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"설정"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"확인"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"시스템에서 이 알림을 숨겼습니다."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"시스템에서 이 알림의 순위를 올렸습니다."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"시스템에서 이 알림의 순위를 내렸습니다."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"맞나요?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"의견을 보내 주셔서 감사합니다."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"확인"</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index 8c3a8ea..f9c723a 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN에 연결됨"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 연결이 해제됨"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"알림"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"알림 없음"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 8a06ed6..99cc3d5 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотуңузду көрүү үчүн таптап коюңуз"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сакталган жок"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншотту сактоо үчүн түзмөктүн кулпусун ачуу керек"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Скриншотту кайра тартып көрүңүз"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сактагычта бош орун аз болгондуктан, скриншот сакталбай жатат"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string>
@@ -188,16 +189,6 @@
     <!-- String.format failed for translation -->
     <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
     <skip />
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон сигналы жок."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон сигналы бир таякча."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон сигналы эки таякча."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон сигналы үч таякча."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Телефон сигналы толук."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Сигнал жок."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Мобилдик интернеттин сигналы бир таякча."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Мобилдик интернеттин сигналы эки таякча."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Мобилдик интернеттин сигналы үч таякча."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Мобилдик интернеттин сигналы толук."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> менен туташкан."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> менен туташты."</string>
@@ -206,8 +197,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX эки таякча."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX үч таякча."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигналы толук."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet ажырады."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet туташты."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Сигнал жок."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Интернет жок."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Таякча жок."</string>
@@ -219,30 +208,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Өчүк."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Туташтып турат."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Туташууда."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM карта жок."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобилдик Интернет"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилдик Интернет күйгүзүлгөн"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилдик Интернет өчүрүлгөн"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Өчүк"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth аркылуу интернет бөлүшүү."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Учак тартиби."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN күйүк."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM карта жок"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Байланыш оператору өзгөртүлүүдө"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Батареянын чоо-жайын ачуу"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батареянын деңгээли <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз, колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
@@ -724,6 +700,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн. <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы жазышуулар демейки жөндөө боюнча калкып чыкма билдирмелер түрүндө көрүнөт."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Калкыма ыкчам баскыч менен көңүлүңүздү бул мазмунга буруп турат."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Билдирменин үнүн чыгартууну же басууну тутумга тапшырыңыз"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Жазышуулар тизмесинин өйдө жагында калкып чыкма билдирме түрүндө көрүнүп, профиль сүрөтү кулпуланган экрандан чагылдырылат"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Жөндөөлөр"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Маанилүүлүгү"</string>
@@ -742,9 +726,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Бул колдонмо экрандагы башка терезелердин үстүнөн көрсөтүлүп, микрофонду жана камераны колдонууда."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Жөндөөлөр"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ЖАРАЙТ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Бул билдирменин үнү тутум тарабынан басылды."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Бул билдирменин маанилүүлүгү тутум тарабынан жогорулатылды."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Бул билдирменин маанилүүлүгү тутум тарабынан төмөндөтүлдү."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Бул туурабы?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Пикириңиз үчүн рахмат!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Жарайт"</string>
diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml
index 3be657c..1dba865 100644
--- a/packages/SystemUI/res/values-ky/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN туташтырылды"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылды"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Билдирмелер"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Билдирме жок"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index b92c2c1..a01d1a4 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ແຕະເພື່ອເບິ່ງພາບຖ່າຍໜ້າຈໍຂອງທ່ານ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ບໍ່ສາມາດບັນທຶກຮູບໜ້າຈໍໄດ້"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ຈະຕ້ອງປົດລັອກອຸປະກອນກ່ອນບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ແບັດເຕີຣີສາມຂີດ."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ແບັດເຕີຣີເຕັມ."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ບໍ່ມີໂທລະສັບ."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ສັນຍານນຶ່ງຂີດ."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ສັນຍານສອງຂີດ."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ສັນຍານສາມຂີດ."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ສັນຍານເຕັມ."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ບໍ່ມີຂໍ້ມູນ."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ຂໍ້ມູນສອງຂີດ."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ຂໍ້ມູນສາມຂີດ."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ສັນ​ຍານຂໍ້ມູນ​ເຕັມ."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"ເຊື່ອມ​ຕໍ່​ຫາ <xliff:g id="WIFI">%s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ເຊື່ອມ​ຕໍ່​ຫາ <xliff:g id="BLUETOOTH">%s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="CAST">%s</xliff:g> ແລ້ວ."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ສອງຂີດ."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ສາມຂີດ."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"ສັນ​ຍານ WiMAX ເຕັມ."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ອີ​ເທີ​ເນັດ​ຕັດ​ເຊື່ອມ​ຕໍ່​ແລ້ວ."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ອີ​ເທີ​ເນັດ​ເຊື່ອມ​ຕໍ່​ແລ້ວ."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ບໍ່ມີສັນຍານ."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ບໍ່ໄດ້ເຊື່ອມຕໍ່."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ບໍ່ມີຈັກຂີດ."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ປິດ."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ເຊື່ອມ​ຕໍ່ແລ້ວ."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ກຳ​ລັງ​ເຊື່ອມ​ຕໍ່."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ໂຣມມິງ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ບໍ່ມີຊິມ."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ອິນເຕີເນັດມືຖື"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ເປີດອິນເຕີເນັດມືຖືແລ້ວ"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ປິດ"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ການປ່ອຍສັນຍານ Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ໂໝດໃນຍົນ."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ເປີດ."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"ບໍ່ມີແຜ່ນ SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"ການປ່ຽນເຄືອຂ່າຍຜູ້ໃຫ້ບໍລິການ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ເປີດລາຍລະອຽດແບັດເຕີຣີ"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ແບັດເຕີຣີ <xliff:g id="NUMBER">%d</xliff:g> ເປີເຊັນ."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ແບັດເຕີຣີ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ເປີເຊັນ, ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ອາດສົ່ງສຽງ ຫຼື ສັ່ນເຕືອນໂດຍອ້າງອີງຈາກການຕັ້ງຄ່າໂທລະສັບ. ການສົນທະນາຈາກ <xliff:g id="APP_NAME">%1$s</xliff:g> ຈະເປັນ bubble ຕາມຄ່າເລີ່ມຕົ້ນ."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ເອົາໃຈໃສ່ທາງລັດແບບລອຍໄປຫາເນື້ອຫານີ້."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ໃຫ້ລະບົບກຳນົດວ່າການແຈ້ງເຕືອນນິ້ຄວນມີສຽງ ຫຼື ສັ່ນເຕືອນຫຼືບໍ່"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ສະແດງຢູ່ເທິງສຸດຂອງພາກສ່ວນການສົນທະນາ, ປາກົດເປັນ bubble ແບບລອຍ, ສະແດງຮູບໂປຣໄຟລ໌ຢູ່ໜ້າຈໍລັອກ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ຕັ້ງຄ່າ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ສຳຄັນ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ແອັບນີ້ກຳລັງສະແດງຜົນບັງແອັບອື່ນຢູ່ໜ້າຈໍຂອງທ່ານ ແລະ ກຳລັງໃຊ້ໄມໂຄຣໂຟນ ແລະ ກ້ອງຖ່າຍຮູບຢູ່."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ການຕັ້ງຄ່າ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ຕົກລົງ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ການແຈ້ງເຕືອນນີ້ຖືກປີດສຽງໂດຍລະບົບແລ້ວ."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ການແຈ້ງເຕືອນນີ້ຖືກຍົກລະດັບໂດຍລະບົບແລ້ວ."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ການແຈ້ງເຕືອນນີ້ຖືກຫຼຸດລະດັບໂດຍລະບົບແລ້ວ."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ສິ່ງນີ້ບໍ່ຖືກຕ້ອງບໍ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ຂອບໃຈສຳລັບຄຳເຫັນຂອງທ່ານ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ຕົກລົງ"</string>
diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml
index 445e562..a45fb45 100644
--- a/packages/SystemUI/res/values-lo/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ຕັດການເຊື່ອມຕໍ່ VPN ແລ້ວ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ການແຈ້ງເຕືອນ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index cac9cf1..7cb83b9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Palieskite, kad peržiūrėtumėte ekrano kopiją"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrano kopijos išsaugoti nepavyko"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Įrenginys turi būti atrakintas, kad būtų galima išsaugoti ekrano kopiją"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pabandykite padaryti ekrano kopiją dar kartą"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Trys akumuliatoriaus juostos."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Akumuliatorius įkrautas."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumuliatoriaus energija procentais nežinoma."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nėra telefono."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Viena telefono juosta."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvi telefono juostos."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Trys telefono juostos."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefono signalas stiprus."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Duomenų nėra."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Viena duomenų juosta."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dvi duomenų juostos."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Trys duomenų juostos."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Stiprus duomenų signalas."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Prisijungta prie „<xliff:g id="WIFI">%s</xliff:g>“."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Prisijungta prie „<xliff:g id="BLUETOOTH">%s</xliff:g>“."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Prisijungta prie <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dvi „WiMAX“ signalo juostos."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Trys „WiMAX“ signalo juostos."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"„WiMAX“ signalas stiprus."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Atsijungta nuo eterneto."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Prijungta prie eterneto."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nėra signalo."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Neprijungta."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nė vienos juostos."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Išjungta."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Prijungta."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Prisijungiama."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Tarptinklinis ryšys"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nėra SIM kortelės."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiliojo ryšio duomenys"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiliojo ryšio duomenys įjungti"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiliojo ryšio duomenys išjungti"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nenustatyta naudoti duomenis"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Išjungta"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"„Bluetooth“ įrenginio kaip modemo naudojimas."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lėktuvo režimas."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN įjungtas."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nėra SIM kortelės."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Keičiamas operatoriaus tinklas"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Atidaryti išsamią akumuliatoriaus informaciją"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akumuliatorius: <xliff:g id="NUMBER">%d</xliff:g> proc."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> proc. akumuliatoriaus energijos – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>, atsižvelgiant į naudojimą"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gali skambėti arba vibruoti, atsižvelgiant į telefono nustatymus. Pokalbiai iš „<xliff:g id="APP_NAME">%1$s</xliff:g>“ debesėlio pagal numatytuosius nustatymus."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Naudojant slankųjį spartųjį klavišą lengviau sutelkti dėmesį į šį turinį."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nustatykite, kad sistema aptiktų, ar šis pranešimas turi skambėti, ar vibruoti"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Rodoma pokalbių skilties viršuje, rodoma kaip slankusis burbulas, pateikiama profilio nuotrauka užrakinimo ekrane"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nustatymai"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetiniai"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ši programa rodoma ekrane virš kitų programų, ji naudoja mikrofoną ir fotoaparatą."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Nustatymai"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Gerai"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Sistema nutildė šį pranešimą."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Sistema paaukštino šį pranešimą."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Sistema pažemino šį pranešimą."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Ar tai teisinga?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dėkojame už atsiliepimą!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Gerai"</string>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index c749cdf..8c329f9 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN prijungtas"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN atjungtas"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pranešimai"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nėra jokių pranešimų"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index da8adb4..2d6a509 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrānuzņēmumu neizdevās saglabāt."</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Lai varētu saglabāt ekrānuzņēmumu, ierīcei ir jābūt atbloķētai."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akumulators: trīs joslas."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Akumulators ir pilnīgi uzlādēts."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumulatora uzlādes līmenis procentos nav zināms."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nav tālruņa."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tālrunis: viena josla."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tālrunis: divas joslas."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tālrunis: trīs joslas."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Pilna piekļuve tālruņa signālam"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nav datu."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dati: viena josla"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dati: divas joslas."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dati: trīs joslas."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Pilna piekļuve datu signālam."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Ir izveidots savienojums ar <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ir izveidots savienojum ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Savienots ar ierīci <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX divas joslas."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX trīs joslas."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signāls pilns."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Pārtraukts savienojums ar tīklu Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Izveidots savienojums ar tīklu Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nav signāla."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Savienojums nav izveidots."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nulle joslu"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Izslēgts"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Savienojums ir izveidots."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Notiek savienojuma izveide..."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Viesabonēšana"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nav SIM kartes."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilie dati"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilie dati ieslēgti"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilie dati izslēgti"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nav iestatīts datu lietošanai"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Izslēgti"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth piesaiste."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lidmašīnas režīms."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ieslēgts"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nav SIM kartes."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobilo sakaru operatora tīkla mainīšana"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Atvērt akumulatora informāciju"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procenti. Ņemot vērā lietojumu, atlikušais laiks ir apmēram <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt. Sarunas no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pēc noklusējuma tiek parādītas burbulī."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Piesaista jūsu uzmanību, rādot peldošu saīsni uz šo saturu."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Iestatiet, lai sistēma noteiktu, vai šim paziņojumam būs skaņa vai vibrācija"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Parādās sarunu sadaļas augšdaļā un kā peldošs burbulis, kā arī bloķēšanas ekrānā tiek rādīts profila attēls"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Iestatījumi"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritārs"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Šī lietotne tiek rādīta ekrānā pāri citām lietotnēm, un tajā tiek izmantots mikrofons un kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Iestatījumi"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Labi"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Šim paziņojumam tika izslēgta skaņa sistēmā."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Šis paziņojums tika paaugstināts sistēmā."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Šis paziņojums tika pazemināts sistēmā."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Vai šī informācija ir pareiza?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Paldies par atsauksmēm!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Labi"</string>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index f752439..758d28c 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Savienojums ar VPN ir izveidots."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Savienojums ar VPN ir pārtraukts."</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Paziņojumi"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nav paziņojumu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 2416dbd..2168279 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Допрете за да ја видите сликата од екранот"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не може да се зачува слика од екранот"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уредот мора да биде отклучен за да може да се зачува слика од екранот"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Повторно обидете се да направите слика од екранот"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сликата од екранот не може да се зачува поради ограничена меморија"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија три цртички."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батеријата е полна."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентот на батеријата е непознат."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Нема сигнал."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон една цртичка.."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон две цртички."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон три цртички."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигналот за телефон е исполнет."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Нема податоци."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Податоци една цртичка."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигналот за податоци е на две цртички."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Податоци три цртички."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигналот за податоци е исполнет."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Поврзано со <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Поврзано со <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Поврзано со <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX две цртички."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX три цртички."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Полн сигнал на WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Етернетот е исклучен."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Етернетот е поврзан."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Нема сигнал."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Не е поврзана"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Нула цртички."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Исклучено."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Поврзано."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Се поврзува."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роаминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Нема SIM картичка."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобилен интернет"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилниот интернет е вклучен"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилниот интернет е исклучен"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Не е поставен да користи интернет"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Исклучено"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Се поврзува со Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Авионски режим."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN е вклучена."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Нема SIM-картичка"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Променување на мрежата на операторот"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Отвори ги деталите за батеријата"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија <xliff:g id="NUMBER">%d</xliff:g> проценти."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија <xliff:g id="PERCENTAGE">%1$s</xliff:g> отсто, уште околу <xliff:g id="TIME">%2$s</xliff:g> според вашето користење"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да ѕвони или вибрира во зависност од поставките на телефонот Стандардно, разговорите од <xliff:g id="APP_NAME">%1$s</xliff:g> се во балончиња."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Ви го задржува вниманието со лебдечка кратенка на содржинава."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволете системот да определи дали известувањево треба да испушти звук или да вибрира"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Се појавува на горниот дел од секцијата на разговорот во вид на лебдечко меурче, покажувајќи ја профилната слика на заклучениот екран"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Поставки"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Апликацијава се прикажува врз други апликации на вашиот екран и ги користи микрофонот и камерата."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Поставки"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Во ред"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Системот го стиши известувањево."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Системот ја зголеми приоритетноста на известувањево."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Системот ја намали приоритетноста на известувањево."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Дали ова беше точно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Фала за повратните информации!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Во ред"</string>
diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml
index 9472813..0dfbd79 100644
--- a/packages/SystemUI/res/values-mk/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е поврзана"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN е исклучена"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известувања"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема известувања"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 4d77fcd..3cbb8e7 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"സ്‌ക്രീൻഷോട്ട് കാണാൻ ടാപ്പ് ചെയ്യുക"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനായില്ല"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഉപകരണം അൺലോക്ക് ചെയ്തിരിക്കണം"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"സ്‌റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ബാറ്ററി മൂന്ന് ബാർ."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ബാറ്ററി നിറഞ്ഞു."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ഫോൺ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ഫോണിൽ ഒരു ബാർ."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ഫോണിൽ രണ്ട് ബാർ."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ഫോണിൽ മൂന്ന് ബാർ."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ഫോൺ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ഡാറ്റാ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ഡാറ്റ ഒരു ബാർ."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ഡാറ്റ രണ്ട് ബാറുകൾ."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ഡാറ്റ മൂന്ന് ബാർ."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ഡാറ്റ സിഗ്‌നൽ പൂർണ്ണമാണ്."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> എന്നതിലേക്ക് കണക്‌റ്റുചെയ്‌തു."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> എന്നതിലേക്ക് കണക്‌റ്റുചെയ്‌തു."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX രണ്ട് ബാറുകൾ."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX മൂന്ന് ബാറുകൾ."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX മികച്ച സിഗ്‌നൽ."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ഇതർനെറ്റ് കണക്റ്റുചെയ്‌തു."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"സിഗ്‌നൽ ഇല്ല."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"കണക്റ്റുചെയ്‌തിട്ടില്ല."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ബാറുകളൊന്നുമില്ല."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ഓഫാണ്."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"കണക്റ്റുചെയ്‌തു."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"കണക്റ്റുചെയ്യുന്നു."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"റോമിംഗ്"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDG"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"വൈഫൈ"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"സിം ഇല്ല."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"മൊബൈൽ ഡാറ്റ ഓണാണ്"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ഓഫ്"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ബ്ലൂടൂത്ത് ടെതറിംഗ്."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ഫ്ലൈറ്റ് മോഡ്."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ഓണാണ്."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM കാർഡൊന്നുമില്ല."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"കാരിയർ നെറ്റ്‌വർക്ക് മാറ്റൽ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ബാറ്ററി വിശദാംശങ്ങൾ തുറക്കുക"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ബാറ്ററി <xliff:g id="NUMBER">%d</xliff:g> ശതമാനം."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ബാറ്ററി <xliff:g id="PERCENTAGE">%1$s</xliff:g> ശതമാനം, നിങ്ങളുടെ ഉപയോഗത്തിൻ്റെ അടിസ്ഥാനത്തിൽ ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> സമയം കൂടി ശേഷിക്കുന്നു"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്‌തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്‌തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബ്ൾ ആവുന്നു."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ഈ അറിയിപ്പ് വരുമ്പോൾ ശബ്‌ദിക്കുകയാണോ വൈബ്രേറ്റ് ചെയ്യുകയാണോ വേണ്ടതെന്ന് നിർണ്ണയിക്കാൻ സിസ്‌റ്റത്തെ അനുവദിക്കുക"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"സംഭാഷണ വിഭാഗത്തിന് മുകളിലായി കാണിക്കുന്നു, ഫ്ലോട്ടിംഗ് ബബിളായി ദൃശ്യമാകുന്നു, ലോക്ക് സ്ക്രീനിൽ പ്രൊഫൈൽ ചിത്രം പ്രദർശിപ്പിക്കുന്നു"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ക്രമീകരണം"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"മുൻഗണന"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ഈ ആപ്പ് നിങ്ങളുടെ സ്‌ക്രീനിലെ മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു, മൈക്രോഫോണും ക്യാമറയും ഉപയോഗിക്കുകയും ചെയ്യുന്നു."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ക്രമീകരണം"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ശരി"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ഈ അറിയിപ്പ്, സിസ്റ്റം നിശബ്‌ദമാക്കിയിരിക്കുന്നു."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ഈ അറിയിപ്പ്, സിസ്റ്റം പ്രമോട്ട് ചെയ്തിരിക്കുന്നു."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ഈ അറിയിപ്പ്, സിസ്റ്റം താഴേക്ക് മാറ്റിയിരിക്കുന്നു."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ഇത് ശരിയായിരുന്നോ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"നിങ്ങളുടെ ഫീഡ്‌ബാക്കിന് നന്ദി!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ശരി"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"പൊതുവായ സന്ദേശങ്ങൾ"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"സ്റ്റോറേജ്"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"സൂചനകൾ"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> റണ്‍ ചെയ്യുന്നു"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string>
diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml
index fe79796..70cced8 100644
--- a/packages/SystemUI/res/values-ml/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN കണക്റ്റ് ചെയ്‌തു"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN വിച്ഛേദിച്ചു"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"അറിയിപ്പുകൾ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0d605c1..9ce77ef 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Дэлгэцээс дарсан зургийг харах бол товшино уу"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Дэлгэцээс дарсан зургийг хадгалж чадсангүй"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Дэлгэцийн агшныг хадгалах боломжтой болохоос өмнө төхөөрөмжийн түгжээг тайлах ёстой"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерей гурван баганатай."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батерей дүүрэн."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарейн хувь тодорхойгүй байна."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Утас байхгүй."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Утас нэг баганатай."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Утас хоёр баганатай."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Утас гурван баганатай."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Утасны дохио дүүрэн."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Дата байхгүй."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Дата нэг баганатай."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дата хоёр баганатай."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Дата гурван баганатай."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Дата дохио дүүрэн."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>-тай холбогдсон."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>-тай холбогдсон."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>-д холбогдсон."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX хоёр баганатай."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX гурван баганатай."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX дохио дүүрэн."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet саллаа."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet холбогдсон."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Дохио байхгүй."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Холбогдоогүй."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Тэг баганатай."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Унтраах"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Холбогдсон."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Холбож байна."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM байхгүй."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобайл дата"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобайл дата асаалттай байна"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобайл дата унтраалттай байна"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Дата ашиглахаар тохируулаагүй"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Идэвхгүй"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth модем болж байна."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Нислэгийн горим"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN асаалттай байна."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM карт байхгүй."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Оператор компанийн сүлжээг өөрчилж байна"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Тэжээлийн дэлгэрэнгүй мэдээллийг нээх"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батерей <xliff:g id="NUMBER">%d</xliff:g> хувьтай."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарей <xliff:g id="PERCENTAGE">%1$s</xliff:g> хувьтай байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Утасны тохиргоонд тулгуурлан хонх дуугаргах эсвэл чичирхийлж болзошгүй. <xliff:g id="APP_NAME">%1$s</xliff:g>-н харилцан яриаг өгөгдмөл тохиргооны дагуу бөмбөлөг болгоно."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Энэ контентын хөвөн гарч ирэх товчлолтойгоор таны анхаарлыг татдаг."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Энэ мэдэгдэл дуу гаргах эсвэл чичрэх эсэхийг системээр тодорхойлуулаарай"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Харилцан ярианы хэсгийн дээд талд хөвж буй бөмбөлөг хэлбэрээр харагдах бөгөөд профайлын зургийг түгжигдсэн дэлгэцэд үзүүлнэ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Тохиргоо"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Ач холбогдол"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Энэ аппыг таны дэлгэцэд бусад аппын дээр харуулж байгаа бөгөөд микрофон болон камерыг ашиглаж байна."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Тохиргоо"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Систем энэ мэдэгдлийг дуугүй болгосон."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Систем энэ мэдэгдлийн зэргийг дэвшүүлсэн."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Систем энэ мэдэгдлийн зэргийг бууруулсан."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Энэ зөв байсан уу?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Санал хүсэлтээ илгээсэнд баярлалаа!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
@@ -788,7 +777,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>
@@ -838,7 +827,7 @@
     <string name="switch_bar_on" msgid="1770868129120096114">"Идэвхтэй"</string>
     <string name="switch_bar_off" msgid="5669805115416379556">"Идэвхгүй"</string>
     <string name="tile_unavailable" msgid="3095879009136616920">"Боломжгүй"</string>
-    <string name="nav_bar" msgid="4642708685386136807">"Навигацийн самбар"</string>
+    <string name="nav_bar" msgid="4642708685386136807">"Навигацын самбар"</string>
     <string name="nav_bar_layout" msgid="4716392484772899544">"Бүдүүвч"</string>
     <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Нэмэлт зүүн товчлуураар шивэх"</string>
     <string name="right_nav_bar_button_type" msgid="4472566498647364715">"Нэмэлт баруун товчлуураар шивэх"</string>
@@ -860,7 +849,7 @@
     <string name="reset" msgid="8715144064608810383">"Шинэчлэх"</string>
     <string name="adjust_button_width" msgid="8313444823666482197">"Товчлуурын өргөнг тохируулах"</string>
     <string name="clipboard" msgid="8517342737534284617">"Түр санах ой"</string>
-    <string name="accessibility_key" msgid="3471162841552818281">"Навигацийн товчлуурыг өөрчлөх"</string>
+    <string name="accessibility_key" msgid="3471162841552818281">"Навигацын товчлуурыг өөрчлөх"</string>
     <string name="left_keycode" msgid="8211040899126637342">"Зүүн түлхүүрийн код"</string>
     <string name="right_keycode" msgid="2480715509844798438">"Баруун түлхүүрийн код"</string>
     <string name="left_icon" msgid="5036278531966897006">"Зүүн дүрс тэмдэг"</string>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index 9ec66d1..221d8ae 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN холбогдсон"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN салсан"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Мэдэгдэл"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Мэдэгдэл байхгүй байна"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a487a63..ed4b7f4 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"तुमचा स्क्रीनशॉट पाहण्यासाठी टॅप करा"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव्ह करू शकलो नाही"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव्ह करण्याआधी डिव्हाइस अनलॉक करणे आवश्यक आहे"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"अ‍ॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"बॅटरी तीन बार."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"बॅटरी पूर्ण भरली."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"कोणताही फोन नाही."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एक बार."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दोन बार."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तीन बार."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फोन सिग्नल पूर्ण."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"कोणताही डेटा नाही."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटा एक बार."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दोन बार."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तीन बार."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा सिग्नल पूर्ण."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> शी कनेक्‍ट केले."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> शी कनेक्‍ट केले."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> शी कनेक्ट केले."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX दोन बार."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX तीन बार."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX सिग्नल पूर्ण."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"इथरनेट डिस्कनेक्ट केले."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"इथरनेट कनेक्ट केले."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"सिग्नल नाही."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"कनेक्ट केले नाही."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य बार."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"बंद."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"कनेक्‍ट केले."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"कनेक्ट करत आहे."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"३G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"४G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"४G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"१X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"रोमिंग"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"वाय-फाय"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"सिम नाही."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा सुरू आहे"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा बंद आहे"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा वापरण्यासाठी सेट केलेले नाही"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"बंद"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लूटूथ टेदरिंग."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"विमान मोड."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सुरू."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"सिम कार्ड नाही."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"वाहक नेटवर्क बदलत आहे"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"बॅटरी तपशील उघडा"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"बॅटरी <xliff:g id="NUMBER">%d</xliff:g> टक्के."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"बॅटरी <xliff:g id="PERCENTAGE">%1$s</xliff:g> टक्के, तुमच्या वापराच्या आधारावर सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोन सेटिंग्जच्या आधारावर रिंग किंवा व्हायब्रेट होऊ शकतो. <xliff:g id="APP_NAME">%1$s</xliff:g> मधील संभाषणे बाय डीफॉल्ट बबल होतात."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"या आशयाच्या फ्लोटिंग शॉर्टकटसह तुमचे लक्ष केंद्रित करते."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ही सूचना मिळाल्‍यावर आवाज व्‍हावा की व्हायब्रेशन व्‍हावे ते सिस्‍टममध्ये नमूद करा"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"संभाषण विभागात सर्वात वरती फ्लोटिंग बबल म्हणून दिसते, लॉक स्क्रीनवर प्रोफाइल पिक्चर दाखवते"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिंग्ज"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राधान्य"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"हे अ‍ॅप तुमच्या स्क्रीनवरील इतर अ‍ॅप्स वर प्रदर्शित होत आहे आणि मायक्रोफोन आणि कॅमेरा वापरत आहे."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"सेटिंग्ज"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ओके"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ही सूचना सिस्‍टमने सायलंट केली होती."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ही सूचना सिस्‍टमने प्रमोट केली होती."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ही सूचना सिस्‍टमने डीमोट केली होती."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"हे बरोबर होते का?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"तुमच्‍या फीडबॅकबद्दल धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ओके"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"सर्वसाधारण मेसेज"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"स्टोरेज"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"सूचना"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"इन्सटंट अ‍ॅप्स"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> रन होत आहे"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"इंस्टॉल केल्याशिवाय अ‍ॅप उघडले."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"इंस्टॉल केल्याशिवाय अ‍ॅप उघडले. अधिक जाणून घेण्यासाठी टॅप करा."</string>
diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml
index 791a4fd..ac0cad1 100644
--- a/packages/SystemUI/res/values-mr/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्‍ट केले"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट केले"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचना"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"सूचना नाहीत"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8f426ed..e03de37 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketik untuk melihat tangkapan skrin anda"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan tangkapan skrin"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Peranti mesti dibuka kunci sebelum tangkapan skrin dapat disimpan"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Cuba ambil tangkapan skrin sekali lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateri tiga bar."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateri penuh."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Peratusan kuasa bateri tidak diketahui."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Tiada telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon satu bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon dua bar."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon tiga bar."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Isyarat telefon penuh."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Tiada data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data satu bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data dua bar."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tiga bar."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Isyarat data penuh."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Disambungkan kepada <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Disambungkan kepada <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Disambungkan ke <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX dua bar."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tiga bar."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Isyarat WiMAX penuh."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet diputuskan sambungan."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet disambungkan."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Tiada isyarat."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Tidak disambungkan."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Tiada bar."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Dimatikan."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Disambungkan."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Perayauan"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Tiada SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Data Mudah Alih"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Data Mudah Alih Dihidupkan"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Data mudah alih dimatikan"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Tidak ditetapkan untuk menggunakan data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Mati"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Penambatan Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod pesawat"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN dihidupkan."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Tiada kad SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rangkaian pembawa berubah"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Buka butiran bateri"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateri <xliff:g id="NUMBER">%d</xliff:g> peratus."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateri <xliff:g id="PERCENTAGE">%1$s</xliff:g> peratus, tinggal kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan anda"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mungkin berbunyi atau bergetar berdasarkan tetapan telefon. Perbualan daripada gelembung <xliff:g id="APP_NAME">%1$s</xliff:g> secara lalai."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Memastikan anda memberikan perhatian dengan pintasan terapung ke kandungan ini."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Minta sistem menentukan jika pemberitahuan ini patut menghasilkan bunyi atau getaran"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ditunjukkan di sebelah atas bahagian perbualan, muncul sebagai gelembung terapung, memaparkan gambar profil pada skrin kunci"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Tetapan"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Keutamaan"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Apl ini dipaparkan di atas apl lain pada skrin anda dan sedang menggunakan mikrofon dan kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Tetapan"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Pemberitahuan ini disenyapkan oleh sistem."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Pemberitahuan ini dinaik taraf oleh sistem."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Pemberitahuan ini diturun taraf oleh sistem."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Adakah ini betul?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas maklum balas anda!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml
index 65c8068..46e345e 100644
--- a/packages/SystemUI/res/values-ms/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN telah disambungkan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN diputuskan sambungan"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pemberitahuan"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tiada Pemberitahuan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 9d8ffc9..50154ba 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ဖန်သားပြင်ဓာတ်ပုံကို ကြည့်ရန် တို့ပါ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"မျက်နှာပြင်ပုံကို သိမ်း၍မရပါ"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ဖန်သားပြင်ဓာတ်ပုံကို မသိမ်းမီ စက်ပစ္စည်းကို လော့ခ်ဖွင့်ထားရမည်"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ဘတ္တရီသုံးဘား။"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ဘတ္တရီအပြည့်။"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ဖုန်းလိုင်းမရှိပါ။"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ဖုန်းလိုင်းတစ်ဘား။"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ဖုန်းလိုင်းသုံးဘား။"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ဖုန်းလိုင်းအပြည့်။"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ဒေတာမရှိပါ။"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ဒေတာတစ်ဘား။"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ဒေတာထုတ်လွှင့်မှု ၂ဘားဖမ်းမိခြင်း။"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ဒေတာသုံးဘား။"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ဒေတာထုတ်လွှင့်မှုအပြည့်ဖမ်းမိခြင်း"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>သို့ ချိတ်ဆက်ထား။"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>သို့ ချိတ်ဆက်ထား"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> သို့ချိတ်ဆက်ထားပါသည်။"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"ဝိုင်မက်စ် ၂ ဘားရှိ"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"ဝိုင်မက်စ် ၃ ဘား"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"ဝိုင်မက်စ် အပြည့်ရှိ"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet ချိတ်ဆက်ထား။"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"အချက်ပြမှု မရှိပါ"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ချိတ်ဆက်မထားပါ"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"၀ ဘား"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ပိတ်ထားသည်"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ချိတ်ဆက်ထားသည်"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ချိတ်ဆက်နေ။"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်ခြင်း"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ဆင်းကဒ်မရှိပါ။"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"မိုဘိုင်းဒေတာ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"မိုဘိုင်းဒေတာကို ဖွင့်ထားပါသည်"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ပိတ်ရန်"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ဘလူးတုသ်သုံး၍ ချိတ်ဆက်ခြင်း"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ကို ဖွင့်ထားသည်။"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM ကတ် မရှိပါ"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"ဝန်ဆောင်မှုပေးသူ ကွန်ရက် ပြောင်းလဲနေသည်။"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ဘက်ထရီ အသေးစိတ် အချက်အလက်များကို ဖွင့်ပါ"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ဘက်ထရီ <xliff:g id="NUMBER">%d</xliff:g> ရာခိုင်နှုန်း။"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ရာခိုင်နှုန်း၊ သင်၏ အသုံးပြုမှုအပေါ် မူတည်၍ <xliff:g id="TIME">%2$s</xliff:g> ခန့်ကျန်သည်"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ဖုန်းဆက်တင်များပေါ် အခြေခံပြီး အသံမြည်နိုင်သည် သို့မဟုတ် တုန်ခါနိုင်သည်။ မူရင်းသတ်မှတ်ချက်အဖြစ် <xliff:g id="APP_NAME">%1$s</xliff:g> မှ စကားဝိုင်းများကို ပူဖောင်းကွက်ဖြင့် ပြသည်။"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"အကြောင်းအရာကို floating shortcut ကိုသုံး၍ အာရုံစိုက်လာအောင်လုပ်ပါ။"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ဤအကြောင်းကြားချက်က အသံ သို့မဟုတ် တုန်ခါမှု ပေးရန် သင့်/မသင့်ကို စနစ်က ဆုံးဖြတ်ပါစေ"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"စကားဝိုင်းကဏ္ဍ၏ ထိပ်ပိုင်းတွင် ပြပြီး ပူဖောင်းကွက်အဖြစ် မြင်ရသည်၊ လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပရိုဖိုင်ပုံကို ပြသည်"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ဆက်တင်များ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ဦးစားပေး"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ဤအက်ပ်က မိုက်ခရိုဖုန်းနှင့် ကင်မရာကို အသုံးပြု၍ ဖန်သားမျက်နှာပြင်ပေါ်ရှိ အခြားအက်ပ်များ အပေါ်မှ ထပ်ပြီး ပြသနေပါသည်။"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ဆက်တင်များ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ဤအကြောင်းကြားချက်ကို စနစ်က အသံပိတ်ထားလိုက်သည်။"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ဤအကြောင်းကြားချက်ကို စနစ်က အဆင့်မြှင့်လိုက်သည်။"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ဤအကြောင်းကြားချက်ကို စနစ်က အဆင့်ချလိုက်သည်။"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ဤအရာက မှန်ပါသလား။"</string>
     <string name="feedback_response" msgid="4671729244976641339">"အကြံပြုချက်အတွက် ကျေးဇူးတင်ပါသည်"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml
index c07b9a5..268c554 100644
--- a/packages/SystemUI/res/values-my/strings_tv.xml
+++ b/packages/SystemUI/res/values-my/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ချိတ်ဆက်ထားသည်"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ချိတ်ဆက်မှုမရှိပါ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"အကြောင်းကြားချက်များ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"အကြောင်းကြားချက်များ မရှိပါ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1d30e2b..4147bc8 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Trykk for å se skjermdumpen"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kunne ikke lagre skjermdump"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheten må være låst opp før skjermdumpen kan lagres"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv å ta skjermdump på nytt"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri – tre stolper."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet er fullt."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriprosenten er ukjent."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon – én stolpe."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon – to stolper."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon – tre stolper."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignal er fullt."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ingen data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data – én stolpe"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data – to stolper."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data – tre stolper."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignal er fullt."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Koblet til <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Koblet til <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Koblet til <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX – to stolper."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX – tre stolper."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Fullt WiMAX-signal."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet er frakoblet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet er tilkoblet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ikke noe signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ikke tilkoblet."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Ingen stolper."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Av."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Tilkoblet."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Kobler til."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Uten SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata er slått på"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata er slått av"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ikke konfigurert til å bruke data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Av"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-internettdeling."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flymodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN på."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Mangler SIM-kort."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Bytting av operatørnettverk"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Åpne informasjon om batteriet"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri – <xliff:g id="NUMBER">%d</xliff:g> prosent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterinivået er <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosent – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår basert på bruken din"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere basert på telefoninnstillingene. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> lager bobler som standard."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Holder deg oppmerksom med en svevende snarvei til dette innholdet."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"La systemet velge om dette varselet skal lage lyd eller vibrere"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtaledelen, vises som en flytende boble, viser profilbildet på låseskjermen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Innstillinger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Denne appen vises over andre apper på skjermen, og bruker mikrofonen og kameraet."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Innstillinger"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Dette varselet ble dempet av systemet."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Dette varselet ble oppgradert av systemet."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Dette varselet ble nedgradert av systemet."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Var det riktig?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Takk for tilbakemeldingen!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index 6346519..c5767dd 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilkoblet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er frakoblet"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Varsler"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen varsler"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 881be66..e4fbe93 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"यन्त्र अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"उक्त एप वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ब्याट्रिका तिनवटा पट्टिहरू"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ब्याट्री पूर्ण छ।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"फोन छैन्।"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एउटा पट्टि।"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दुई पट्टि।"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तिन पट्टिहरू।"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फोन सङ्केत भरिएको।"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"डेटा छैन।"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटाको एउटा पट्टि।"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दुई बाधाहरू।"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तिन बाधाहरू।"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा संकेत पूर्ण।"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> मा जडित।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> मा जडित।"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> मा कनेक्ट गरियो।"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"वाइम्याक्स दुईवटा बारहरू।"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"वाइम्याक्स तिनवटा बारहरू।"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"वाइम्याक्स सङ्केत भरिएका।"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"इथरनेट विच्छेद भयो।"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"इथरनेट जोडियो।"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"सङ्केत छैन।"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"जडान नगरिएको।"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य पट्टि।"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"बन्द गर्नुहोस्।"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"जडान गरिएको।"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"जडान हुँदै।"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"रोमिङ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM छैन।"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा सक्रिय छ"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा निष्क्रिय छ"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"निष्क्रिय पार्नु"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लुटुथ टेदर गर्दै।"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाइजहाज मोड।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सक्रिय छ।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM कार्ड छैन।"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"सेवा प्रदायकको नेटवर्क परिवर्तन गर्ने आइकन"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ब्याट्री सम्बन्धी विवरणहरूलाई खोल्नुहोस्"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ब्याट्री <xliff:g id="NUMBER">%d</xliff:g> प्रतिशत"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ब्याट्रीको चार्ज <xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत छ, तपाईंको प्रयोगका आधारमा <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"सिस्टमलाई यो सूचना आउँदा ध्वनि बज्नु पर्छ वा कम्पन हुनु पर्छ भन्ने कुराको निधो गर्न दिनुहोस्"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"वार्तालाप खण्डको सिरानमा देखा पर्छ, तैरने बबलका रूपमा देखा पर्छ, लक स्क्रिनमा प्रोफाइल फोटो देखाइन्छ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिङ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"सेटिङहरू"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ठिक छ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"सिस्टमले यो सूचना आउँदा बज्ने ध्वनि बन्द गरेको छ।"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"सिस्टमले यो सूचनालाई दिइने दर्जा बढाएको छ।"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"सिस्टमले यो सूचनालाई दिइने दर्जा घटाएको छ।"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"के यो सही थियो?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"तपाईंको प्रतिक्रियाका लागि धन्यवाद!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ठिक छ"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index 00cc10a..925f7b76 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट गरिएको छ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट गरिएको छ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाहरू"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कुनै पनि सूचना छैन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 8cc747b..d0aef6f 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -44,11 +44,8 @@
     <color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color>
     <color name="notification_channel_dialog_separator">@color/GM2_grey_700</color>
 
-    <!-- The color of the background in the top part of QSCustomizer -->
-    <color name="qs_customize_background">@color/GM2_grey_900</color>
-
     <!-- The color of the background in the bottom part of QSCustomizer -->
-    <color name="qs_customize_decoration">@color/GM2_grey_800</color>
+    <color name="qs_customize_decoration">@color/GM2_grey_900</color>
 
     <!-- The color of the background in the separated list of the Global Actions menu -->
     <color name="global_actions_separated_background">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6bed66b..1871eef 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om je screenshot te bekijken"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kan screenshot niet opslaan"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Je moet het apparaat ontgrendelen voordat het screenshot kan worden opgeslagen"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer opnieuw een screenshot te maken"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batterij: drie streepjes."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batterij is vol."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterijpercentage onbekend."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Geen telefoonsignaal."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoon: één streepje."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoon: twee streepjes."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefoon: drie streepjes."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefoonsignaal is op volle sterkte."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Geen gegevens."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Gegevens: één streepje."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Gegevens: twee streepjes."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Gegevens: drie streepjes."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Gegevenssignaal is op volle sterkte."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Verbonden met <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Verbonden met <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Verbonden met <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: twee streepjes."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: drie streepjes."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signaal  is op volle sterkte."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernetverbinding verbroken."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet verbonden."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Geen signaal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Niet verbonden."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Geen streepjes."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Uitgeschakeld."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Verbonden."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Verbinden."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wifi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Geen simkaart."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobiele data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiele data aan"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiele data uit"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Gebruik van gegevens is niet ingesteld"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Uit"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-tethering."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ingeschakeld."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Geen simkaart."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Netwerk van provider wordt gewijzigd"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Accudetails openen"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batterij: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterij op <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> op basis van je gebruik"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels weergegeven."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Trekt de aandacht met een zwevende snelkoppeling naar deze content."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Het systeem laten bepalen of deze melding geluid moet maken of moet trillen"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wordt bovenaan het gespreksgedeelte weergegeven, verschijnt als zwevende bubbel, geeft profielfoto weer op vergrendelscherm"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellingen"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Deze app geeft andere apps op je scherm weer en gebruikt de microfoon en camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Instellingen"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Deze melding is gedempt door het systeem."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Deze melding is gepromoveerd door het systeem."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Deze melding is verlaagd door het systeem."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Is dit juist?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Bedankt voor je feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 11f70b4..22d3b88 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Verbinding met VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Geen verbinding met VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Meldingen"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen meldingen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index a809da3..601b8f4 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ସ୍କ୍ରୀନଶଟ୍‍ ଦେଖିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ସ୍କ୍ରୀନ୍‍ଶଟ୍ ସେଭ୍ କରିହେବ ନାହିଁ"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ସ୍କ୍ରିନସଟ୍ ସେଭ୍ କରିବା ପୂର୍ବରୁ ଡିଭାଇସକୁ ଅନଲକ୍ କରାଯିବା ଆବଶ୍ୟକ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍‌ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ସୀମିତ ଷ୍ଟୋରେଜ୍‍ ସ୍ପେସ୍‍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ ହୋଇପାରିବ ନାହିଁ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ଆପ୍‍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍‍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ବ୍ୟାଟେରୀର ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ବ୍ୟାଟେରୀ ପୂର୍ଣ୍ଣ‍।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ଫୋନର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ଫୋନ୍‍ରେ ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ଫୋନ୍ ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"କୌଣସି ଡାଟା ନାହିଁ।"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ଡାଟାର ଗୋଟିଏ ବାର ଅଛି।"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ଡାଟାର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ଡାଟାର ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ଡାଟା ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ସହିତ ସଂଯୁକ୍ତ।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ସହ ସଂଯୁକ୍ତ"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ସହିତ ସଂଯୁକ୍ତ।"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAXର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAXର ତିନୋଟି ବାର୍‌ ଅଛି।"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAXର ସିଗ୍ନାଲ୍ ସମ୍ପୂର୍ଣ୍ଣ ଅଛି।"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ଇଥରନେଟ୍‍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ଇଥରନେଟ୍‍ ସଂଯୁକ୍ତ ହୋଇଛି।"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"କୌଣସି ସିଗ୍ନାଲ୍‍ ନାହିଁ।"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ।"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"କୌଣସି ବାର୍‍ ନାହିଁ।"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ବନ୍ଦ।"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ସଂଯୁକ୍ତ।"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ସଂଯୋଗ କରୁଛି।"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ରୋମିଙ୍ଗ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ୱାଇ-ଫାଇ"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"କୌଣସି SIM ନାହିଁ।"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ମୋବାଇଲ୍‌ ଡାଟା ଅନ୍‍"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ମୋବାଇଲ୍‌ ଡାଟା ବନ୍ଦ ଅଛି"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ବନ୍ଦ"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ବ୍ଲୁଟୁଥ ଟିଥରିଂ।"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍‌।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ଅନ୍‍।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"କେରିଅର୍‍ ନେଟ୍‌ୱର୍କ ବଦଳୁଛି"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ବ୍ୟାଟେରୀ ବିବରଣୀ ଖୋଲନ୍ତୁ"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ବ୍ୟାଟେରୀ <xliff:g id="NUMBER">%d</xliff:g> ଶତକଡ଼ା।"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ବ୍ୟାଟେରୀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ଶତକଡା, ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ପାଖାପାଖି <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ। <xliff:g id="APP_NAME">%1$s</xliff:g>ରୁ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଡିଫଲ୍ଟ ଭାବରେ ବବଲ୍ ହୁଏ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ଭାସମାନ ସର୍ଟକଟ୍ ସହ ଆପଣଙ୍କର ଧ୍ୟାନ ଦିଅନ୍ତୁ।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ଏହି ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ ହେବା ସମୟରେ ସାଉଣ୍ଡ ହେବା ଉଚିତ ନା ଭାଇବ୍ରେସନ୍ ତାହା ସିଷ୍ଟମକୁ ସ୍ଥିର କରିବାକୁ ଦିଅନ୍ତୁ"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାଏ, ଫ୍ଲୋଟିଂ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଡିସପ୍ଲେ କରେ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ସେଟିଂସ୍"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ଏହି ଆପ୍, ଆପଣଙ୍କର ସ୍କ୍ରୀନ୍ ଉପରେ ଥିବା ଅନ୍ୟ ଆପ୍ ଉପରେ ପ୍ରଦର୍ଶିତ ହେଉଛି ଏବଂ ମାଇକ୍ରୋଫୋନ୍ ଓ କ୍ୟାମେରା ବ୍ୟବହାର କରୁଛି।"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ସେଟିଂସ୍"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ଠିକ୍ ଅଛି"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ନୀରବ କରାଯାଇଥିଲା।"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ପ୍ରମୋଟ୍ କରାଯାଇଥିଲା।"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ଡିମୋଟ୍ କରାଯାଇଥିଲା।"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ଏହା ଠିକ୍ ଥିଲା କି?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ଆପଣଙ୍କ ମତାମତ ପାଇଁ ଧନ୍ୟବାଦ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ଠିକ୍ ଅଛି"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"ସାଧାରଣ ମେସେଜ୍"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ୍‌"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"ହିଣ୍ଟ"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ଇନଷ୍ଟାଣ୍ଟ ଆପ୍‌"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି।"</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index f436bab..707c49e 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ସଂଯୋଗ କରାଯାଇଛି"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index d9a6828..b374a6e 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"ਬੈਟਰੀ ਤਿੰਨ ਬਾਰਸ।"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"ਬੈਟਰੀ ਪੂਰੀ।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ਕੋਈ  ਡਾਟਾ  ਨਹੀਂ।"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">" ਡਾਟਾ  ਇੱਕ ਬਾਰ।"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">" ਡਾਟਾ  ਦੋ ਬਾਰਸ।"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">" ਡਾਟਾ  ਤਿੰਨ ਬਾਰ।"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">" ਡਾਟਾ  ਸਿਗਨਲ ਪੂਰਾ।"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ।"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ਦੋ ਬਾਰਸ।"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ਤਿੰਨ ਬਾਰਸ।"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ਸਿਗਨਲ ਪੂਰਾ।"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ਈਥਰਨੈੱਟ ਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ਕੋਈ ਸਿਗਨਲ ਨਹੀਂ।"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ।"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ਸਿਫ਼ਰ ਬਾਰਸ।"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ਬੰਦ।"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"ਕਨੈਕਟ ਕੀਤਾ।"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ।"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ਰੋਮਿੰਗ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ਵਾਈ-ਫਾਈ"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ਕੋਈ SIM ਨਹੀਂ।"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ਮੋਬਾਈਲ ਡਾਟਾ ਚਾਲੂ"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ਡਾਟਾ ਵਰਤਣ ਲਈ ਸੈੱਟ ਨਹੀਂ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ਬੰਦ"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ।"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ਏਅਰਪਲੇਨ ਮੋਡ।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ਚਾਲੂ ਹੈ।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ।"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"ਕੈਰੀਅਰ ਨੈੱਟਵਰਕ ਦੀ ਬਦਲੀ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"ਬੈਟਰੀ ਵੇਰਵੇ ਖੋਲ੍ਹੋ"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ਬੈਟਰੀ <xliff:g id="NUMBER">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ ਹੈ।"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ਬੈਟਰੀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ਫ਼ੀਸਦ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ਫ਼ੋਨ ਸੈਟਿੰਗਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਘੰਟੀ ਵੱਜ ਸਕਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਹੋ ਸਕਦੀ ਹੈ। ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ <xliff:g id="APP_NAME">%1$s</xliff:g> ਬਬਲ ਤੋਂ ਗੱਲਾਂਬਾਤਾਂ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ਇਸ ਸਮੱਗਰੀ ਦੇ ਅਸਥਿਰ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਆਪਣਾ ਧਿਆਨ ਕੇਂਦਰਿਤ ਰੱਖੋ।"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ਸਿਸਟਮ ਨੂੰ ਨਿਰਧਾਰਤ ਕਰਨ ਦਿਓ ਕਿ ਇਸ ਸੂਚਨਾ ਲਈ ਕੋਈ ਧੁਨੀ ਵਜਾਉਣੀ ਚਾਹੀਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਕਰਨੀ ਚਾਹੀਦੀ ਹੈ"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ, ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਦਿਖਾਈ ਜਾਂਦੀ ਹੈ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ਤਰਜੀਹ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਹੋਰਾਂ ਐਪਾਂ ਉੱਪਰ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹੈ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ਠੀਕ ਹੈ"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਹ ਸੂਚਨਾ ਸ਼ਾਂਤ ਕਰ ਦਿੱਤੀ ਗਈ ਸੀ।"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਵਧਾ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਘਟਾ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ਕੀ ਇਹ ਸਹੀ ਸੀ?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ਤੁਹਾਡੇ ਵਿਚਾਰ ਲਈ ਧੰਨਵਾਦ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ਠੀਕ ਹੈ"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"ਆਮ ਸੁਨੇਹੇ"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"ਸਟੋਰੇਜ"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"ਸੰਕੇਤ"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"ਤਤਕਾਲ ਐਪਾਂ"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ਚੱਲ ਰਹੀ ਹੈ"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index d10daa8..c076194 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ਕਨੈਕਟ ਹੈ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ਡਿਸਕਨੈਕਟ ਹੈ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"ਸੂਚਨਾਵਾਂ"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3e944b5..3ff500e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Kliknij, by zobaczyć zrzut ekranu"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nie udało się zapisać zrzutu ekranu"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Przed zapisaniem zrzutu ekranu musisz odblokować urządzenie"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: trzy paski."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria naładowana."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Poziom naładowania baterii jest nieznany."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Brak sygnału telefonu."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: jeden pasek."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: dwa paski."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon: trzy paski."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon: pełna moc sygnału."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Brak danych."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dane: jeden pasek."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dane: dwa paski."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dane: trzy paski."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Dane: pełna moc sygnału."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Połączono z <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Połączono z <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Połączono z urządzeniem <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: dwa paski"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: trzy paski"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX: pełna moc sygnału"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Rozłączono z siecią Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Połączono z siecią Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Brak sygnału."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nie połączono."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero pasków."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Wył."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Połączono."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Łączę..."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Brak karty SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilna transmisja danych"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilna transmisja danych włączona"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Wyłączona"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie skonfigurowano do transmisji danych"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Wył."</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Thethering przez Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Tryb samolotowy."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Sieć VPN włączona."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Brak karty SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Zmiana sieci operatora"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Zobacz szczegóły baterii"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, jeszcze <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Może włączyć dzwonek lub wibracje w zależności od ustawień telefonu. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Przyciąga uwagę dzięki pływającym skrótom do treści."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Pozwól systemowi decydować, czy o powiadomieniu powinien informować dźwięk czy wibracja"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wyświetla się jako pływający dymek u góry sekcji rozmów, pokazuje zdjęcie profilowe na ekranie blokady"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorytet"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ta aplikacja wyświetla się nad innymi aplikacjami na ekranie i używa mikrofonu oraz aparatu."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ustawienia"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"System wyciszył to powiadomienie."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"System zmienił ważność tego powiadomienia na wyższą."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"System zmienił ważność tego powiadomienia na niższą."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Czy to było prawidłowe?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Dziękujemy za opinię"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index d83391e..e63aade 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Połączono z VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Rozłączono z VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Powiadomienia"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Brak powiadomień"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d058eddb..8529f40 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de sinal do telefone."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal do telefone cheio."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nenhum dado."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de sinal de dados."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de sinal de dados."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras do sinal de dados."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados cheio."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras do WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras do WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Sem conexão."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nenhuma barra."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desligado."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sem chip."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Sem configuração para uso de dados"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desativados"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Sem chip."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Alteração de rede da operadora"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Este app está sobreposto a outros apps na sua tela e está usando o microfone e a câmera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Configurações"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Esta notificação foi silenciada pelo sistema."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Esta notificação foi promovida pelo sistema."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Esta notificação foi rebaixada pelo sistema."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index 49b923d..2ea8152 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dcaf460..e90e105 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver a captura de ecrã."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Não foi possível guardar a captura de ecrã"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"É necessário desbloquear o dispositivo para guardar a captura de ecrã"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Experimente voltar a efetuar a captura de ecrã."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentagem da bateria desconhecida."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de telefone."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de telefone."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de telefone."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal de telefone completo."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Sem dados."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de dados."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de dados."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras de dados."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados completo."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Ligado a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ligado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Ligado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras de WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras de WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desligada."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet ligada."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Sem ligação."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero barras."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desativado."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Ligado."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"A ligar..."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sem SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Não definido para utilizar dados"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desativado"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Ligação Bluetooth via telemóvel."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo de avião"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nenhum cartão SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rede do operador em mudança."</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria a <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria a <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, resta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g> com base na sua utilização."</string>
@@ -569,9 +545,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>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode tocar ou vibrar com base nas definições do telemóvel. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém a sua atenção com um atalho flutuante para este conteúdo."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se esta notificação deve emitir um som ou uma vibração"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece no topo da secção de conversas, surge como balão flutuante e apresenta a imagem do perfil no ecrã de bloqueio."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Definições"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta app está a sobrepor-se a outras aplicações no ecrã e a utilizar o microfone e a câmara."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Definições"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"O sistema silenciou esta notificação."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"O sistema promoveu esta notificação."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"O sistema despromoveu esta notificação."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Estava correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Obrigado pelo seu feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index a36a1a92..8ce3e30 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está ligada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desligada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sem notificações"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d058eddb..8529f40 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de sinal do telefone."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal do telefone cheio."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nenhum dado."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de sinal de dados."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de sinal de dados."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras do sinal de dados."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados cheio."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras do WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras do WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Sem conexão."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nenhuma barra."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Desligado."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Sem chip."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Sem configuração para uso de dados"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Desativados"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Sem chip."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Alteração de rede da operadora"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Este app está sobreposto a outros apps na sua tela e está usando o microfone e a câmera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Configurações"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Esta notificação foi silenciada pelo sistema."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Esta notificação foi promovida pelo sistema."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Esta notificação foi rebaixada pelo sistema."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index 49b923d..2ea8152 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 81caf56..9339dec 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Atingeți pentru a vedea captura de ecran"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nu s-a putut salva captura de ecran"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pentru a salva captura de ecran, trebuie să deblocați dispozitivul"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Încercați să faceți din nou o captură de ecran"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterie: trei bare."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie: complet."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procentajul bateriei este necunoscut."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nu există semnal pentru telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Semnal pentru telefon: o bară."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Semnal pentru telefon: două bare."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Semnal pentru telefon: trei bare."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Semnal pentru telefon: complet."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nu există semnal pentru date."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Semnal pentru date: o bară."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Semnal pentru date: două bare."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Semnal pentru date: trei bare."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Semnal pentru date: complet."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectat la <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectat la <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"S-a stabilit conexiunea la <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX două bare."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX trei bare."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX semnal complet."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet deconectat."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectat."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Fără semnal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Neconectat."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nicio bară."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Dezactivat."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectat."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Se conectează."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Niciun card SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Date mobile"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Date mobile activate"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Date mobile dezactivate"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nu este setat pentru a folosi datele"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Dezactivate"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conectarea ca modem prin Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod Avion."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Rețea VPN activată"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Fără SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Se schimbă rețeaua operatorului"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Deschideți detaliile privind bateria"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterie: <xliff:g id="NUMBER">%d</xliff:g> la sută."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Procentul rămas din baterie este <xliff:g id="PERCENTAGE">%1$s</xliff:g>. În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Poate să sune sau să vibreze, în funcție de setările telefonului. Conversațiile din balonul <xliff:g id="APP_NAME">%1$s</xliff:g> în mod prestabilit."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Vă atrage atenția printr-o comandă rapidă flotantă la acest conținut."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Solicitați-i sistemului să stabilească dacă această notificare este sonoră sau cu vibrații."</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se afișează în partea de sus a secțiunii de conversație, apare ca un balon flotant, afișează fotografia de profil pe ecranul de blocare"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setări"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritate"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Această aplicație se afișează peste alte aplicații de pe ecran și folosește microfonul și camera foto."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Setări"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Notificarea a fost dezactivată de sistem."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Notificarea a fost promovată de sistem."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Notificarea a fost mutată în jos de sistem."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Este corect?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Mulțumim pentru feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index 69a3138..c64a492 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN este conectat"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN este deconectat"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificări"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nicio notificare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index bf5e604..1fa974935 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Нажмите, чтобы увидеть скриншот."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не удалось сохранить скриншот"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Чтобы сохранить скриншот, разблокируйте устройство."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Попробуйте сделать скриншот снова."</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не удалось сохранить скриншот: недостаточно места."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд батареи: три деления."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея полностью заряжена."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Уровень заряда батареи в процентах неизвестен."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Сигнал телефонной сети отсутствует."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефонной сети: одно деление."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефонной сети: два деления."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Сигнал телефонной сети: три деления."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Надежный телефонный сигнал."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Сигнал передачи данных отсутствует."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Сигнал передачи данных: одно деление."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигнал передачи данных: два деления."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Сигнал передачи данных: три деления."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Надежный сигнал передачи данных."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>: подключено."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>: подключено."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Подключено к: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Сигнал WiMAX: два деления."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Сигнал WiMAX: три деления."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Надежный сигнал WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Устройство отключено от Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Устройство подключено к Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Нет сигнала"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Не подключено"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Нет сигнала"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Отключено"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Подключено"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Соединение."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM-карта отсутствует."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобильный Интернет"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобильный Интернет включен"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобильный Интернет отключен"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Мобильный Интернет по умолчанию не используется."</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Отключен"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-модем"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим полета."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Режим VPN включен."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Нет SIM-карты."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Сменить сеть"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Сведения о расходе заряда батареи"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд батареи в процентах: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Заряд батареи в процентах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Оценка оставшегося времени работы: <xliff:g id="TIME">%2$s</xliff:g>."</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Система будет сама определять, включать ли звуковой сигнал или вибрацию для уведомления"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Появляется в верхней части списка разговоров и как всплывающий чат, фото профиля показывается на заблок. экране"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Это приложение располагается поверх других приложений, а также использует микрофон и камеру."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Настройки"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Это уведомление отключено системой."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Статус этого уведомления повышен системой."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Статус этого уведомления понижен системой."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Все верно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Спасибо!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index bd8855b..e08ade3 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-подключение установлено"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-подключение отключено"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Отправлено через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Уведомления"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Уведомлений нет."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index c855be3..d39bc52 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ඔබගේ තිර රුව බැලීමට තට්ටු කරන්න"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"තිර රුව සුරැකිය නොහැකි විය"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"තිර රුව සුරැකීමට පෙර උපාංගය අගුලු හැරිය යුතුය"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"බැටරිය තීරු තුනයි."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"බැටරිය පිරී ඇත."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"බැටරි ප්‍රතිශතය නොදනී."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"දුරකථනයක් නැත."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"දුරකථනය තීරු එකයි."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"දුරකථනය තීරු දෙකයි."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"දුරකථනය තීරු තුනයි."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"දත්ත නැත."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"දත්ත තීරු එකයි."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"දත්ත තීරු 2."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"දත්ත තීරු 3."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"දත්ත සංඥාව පිරී ඇත."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> වෙත සම්බන්ධ විය."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX තීරු දෙකයි."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX තීරු තුනයි."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX සංඥාව පිරී ඇත."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ඊතර්නෙට් සම්බන්ධ කරන ලදී."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"සංඥා නැත."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"සම්බන්ධ වී නැත."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"තීරු ශුන්‍යයි."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"අක්‍රිය කරන්න."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"සම්බන්ධිතයි."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"සම්බන්ධ වෙමින්."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"රෝමිං"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM නැත."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"ජංගම දත්ත"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"ජංගම දත්ත ක්‍රියාත්මකයි"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"ජංගම දත්ත ක්‍රියාවිරහිතයි"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ක්‍රියාවිරහිතයි"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"බ්ලූටූත් ටෙදරින්."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"අහස්යානා ආකාරය."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ක්‍රියාත්මකයි."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM කාඩ්පත නැත."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"වාහක ජාලය වෙනස් වෙමින්"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"බැටරි විස්තර විවෘත කරන්න"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"බැටරි ප්‍රතිශතය <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"බැටරි ප්‍රතිශතය <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ඔබේ භාවිතයට අනුව <xliff:g id="TIME">%2$s</xliff:g> ක් පමණ ඉතුරුයි"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"දුරකථන සැකසීම් මත පදනම්ව නාද කිරීමට හෝ කම්පනය කිරීමට හැකිය. <xliff:g id="APP_NAME">%1$s</xliff:g> වෙතින් සංවාද පෙරනිමියෙන් බුබුළු දමයි"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"පාවෙන කෙටිමගක් සමග ඔබේ අවධානය මෙම අන්තර්ගතය වෙත තබා ගන්න."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"මෙම දැනුම් දීම ශබ්දයක් හෝ කම්පනයක් ඇති කළ යුතු ද යන්න පද්ධතිය මගින් තීරණය කර තිබේද"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"සංවාද කොටසේ ඉහළම පෙන්වයි, බුබුළක් ලෙස දිස් වේ, අගුලු තිරයේ පැතිකඩ පින්තූරය සංදර්ශනය වේ"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"සැකසීම්"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ප්‍රමුඛතාව"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"මෙම යෙදුම් ඔබගේ තිරය මත අනෙකුත් යෙදුම්වලට උඩින් සංදර්ශනය වන අතර මයික්‍රෆෝනය සහ කැමරාව භාවිතා කරයි."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"සැකසීම්"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"හරි"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"මෙම දැනුම් දීම පද්ධතිය මගින් නිහඬ කරන ලදී."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"මෙම දැනුම් දීම පද්ධතිය මගින් ඉහළ දමන ලදී."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"මෙම දැනුම් දීම පද්ධතිය මගින් පහත දමන ලදී."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"මෙය නිවැරදි වුයේද?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ඔබේ ප්‍රතිපෝෂණයට ස්තූතියි!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"හරි"</string>
diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml
index a04d166..3067be3 100644
--- a/packages/SystemUI/res/values-si/strings_tv.xml
+++ b/packages/SystemUI/res/values-si/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN සම්බන්ධිතයි"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN විසන්ධි කර ඇත"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"දැනුම්දීම්"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"දැනුම්දීම් නැත"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c2a94be..a50da0e 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím zobrazíte snímku obrazovky"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímku obrazovky sa nepodarilo uložiť"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred uložením snímky obrazovky je potrebné zariadenie odomknúť"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skúste snímku urobiť znova"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tri čiarky batérie."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batéria je nabitá."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percento batérie nie je známe."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Žiadna telefónna sieť."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jeden stĺpec signálu telefónnej siete."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dve čiarky signálu telefónnej siete."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tri čiarky signálu telefónnej siete."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Plný signál telefónnej siete."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Žiadna dátová sieť."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Jedna čiarka signálu dátovej siete."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dve čiarky signálu dátovej siete."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tri čiarky signálu dátovej siete."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Plný signál dátovej siete."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Pripojené k zariadeniu <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Pripojené k zariadeniu <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Pripojené k zariadeniu <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dva stĺpce signálu siete WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tri stĺpce signálu siete WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Plný signál siete WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Sieť ethernet je odpojená"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Sieť ethernet je pripojená"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Žiadny signál."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nepripojené."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Žiadna čiarka."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Vypnuté."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Pripojené."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Pripája sa"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi‑Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Žiadna SIM karta."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobilné dáta"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilné dáta sú zapnuté"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilné dáta sú vypnuté"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie je nastavené na používanie dát"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Vypnuté"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Pripojenie cez Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim v lietadle."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuté."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Žiadna SIM karta."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mení sa sieť operátora"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Otvoriť podrobnosti o batérii"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batéria <xliff:g id="NUMBER">%d</xliff:g> percent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Percentá batérie: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Na základe vášho používania zostáva <xliff:g id="TIME">%2$s</xliff:g>."</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Môže zvoniť alebo vibrovať podľa nastavení telefónu. Predvolene sa zobrazia konverzácie z bubliny <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Upúta vás plávajúcim odkazom na tento obsah."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nechajte systém určiť, či má toto upozornenie vydávať zvuk alebo vibrovať"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Nájdete ju hore v sekcii konverzácií ako plávajúcu bublinu, zobrazuje profilovú fotku na uzamknutej obrazovke"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavenia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Táto aplikácia sa zobrazuje cez ďalšie aplikácie na obrazovke a používa mikrofón aj fotoaparát."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Nastavenia"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Zvuk tohto upozornenia bol vypnutý systémom."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Toto upozornenie bolo povýšené systémom."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Toto upozornenie bolo systémom preradené nižšie."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Bolo toto správne?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Ďakujeme za váš názor."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index 3b8fcc8..b37648d 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Sieť VPN je pripojená"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Sieť VPN je odpojená"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Upozornenia"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žiadne upozornenia"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5828d65..7d9a5d9 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Dotaknite se, če si želite ogledati posnetek zaslona"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Posnetka zaslona ni bilo mogoče shraniti"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred shranjevanjem posnetka zaslona morate odkleniti napravo"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Poskusite znova ustvariti posnetek zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija s tremi črticami."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je polna."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Neznan odstotek napolnjenosti baterije."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ni telefona."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon z eno črtico."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon z dvema črticama."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon s tremi črticami."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal telefona je poln."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ni podatkov."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Podatkovni signal z eno črtico."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Podatki z dvema črticama."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Podatki s tremi črticami."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Podatkovni signal poln."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezava vzpostavljena z: <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezava vzpostavljena z: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Vzpostavljena povezava: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX: dve črtici."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX: tri črtice."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Poln signal WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernetna povezava je prekinjena."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernetna povezava je vzpostavljena."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ni signala."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ni povezan."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Nič črtic."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Izklopljen."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezan."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezovanje."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Gostovanje"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Ni kartice SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Prenos podatkov v mobilnem omrežju"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Prenos podatkov v mobilnem omrežju je vklopljen"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Ni nastavljeno za uporabo prenosa podatkov"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Izklopljeno"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internet prek Bluetootha."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način za letalo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Omrežje VPN je vklopljeno."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Ni kartice SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Spreminjanje omrežja operaterja"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Odpiranje podrobnosti o bateriji"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> odstotkov."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Napolnjenost baterije je <xliff:g id="PERCENTAGE">%1$s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona. Pogovori v aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> so privzeto prikazani v oblačkih."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Zadrži vašo pozornost z lebdečo bližnjico do te vsebine."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Naj sistem določi, ali ob prejemu tega obvestila naprava predvaja zvok ali zavibrira"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikaz na vrhu razdelka s pogovorom in v plavajočem oblačku, prikaz profilne slike na zaklenjenem zaslonu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavitve"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prednost"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ta aplikacija prekriva druge aplikacije na zaslonu ter uporablja mikrofon in fotoaparat."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Nastavitve"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"V redu"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je utišal to obvestilo."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je zvišal prednost tega obvestila."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je znižal prednost tega obvestila."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Je bilo to prav?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Hvala za povratne informacije."</string>
     <string name="feedback_ok" msgid="6481426753298857144">"V redu"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index af5d75d..57d70c0 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Povezava z navideznim zasebnim omrežjem je prekinjena"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obvestila"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ni obvestil"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 297ebc6..a72f090 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Trokit për të parë pamjen e ekranit"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Pamja e ekranit nuk mund të ruhej"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pajisja duhet të shkyçet para se të mund të ruhet pamja e ekranit"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria ka edhe tre vija."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria u mbush."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Përqindja e baterisë e panjohur."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Nuk ka telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoni ka edhe një vijë."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoni ka dy vija."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefoni ka tre vija."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinjali i telefonit është i plotë."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Nuk ka të dhëna."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Sinjali është vetëm një vijë."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Të dhënat kanë dy vija."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Sinjali është me tre vija."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinjali i të dhënave është i plotë."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Lidhur me <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Lidhur me <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Është lidhur me <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ka dy vija."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ka tre vija."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ka sinjal të plotë."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Lidhja e eternetit u shkëput."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Lidhja e eternetit u lidh."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Nuk ka sinjal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Nuk është i lidhur."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero vija."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Çaktivizuar."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"I lidhur."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Po lidhet."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Nuk ka kartë SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Të dhënat celulare"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Të dhënat celulare janë aktive"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Të dhënat celulare janë joaktive"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Nuk është caktuar të përdorë të dhënat"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Joaktiv"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Po lidhet me \"bluetooth\"."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"modaliteti i aeroplanit"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN-ja është aktive."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Nuk ka kartë SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rrjeti i operatorit celular po ndryshohet"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Hap detajet e baterisë"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria ka edhe <xliff:g id="NUMBER">%d</xliff:g> për qind."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> përqind, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mund të bjerë zilja ose të dridhet në bazë të cilësimeve të telefonit. Bisedat nga flluska e <xliff:g id="APP_NAME">%1$s</xliff:g> si parazgjedhje."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mban vëmendjen tënde me një shkurtore pluskuese te kjo përmbajtje."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Kërkoji sistemit të përcaktojë nëse ky njoftim duhet të lëshojë tingull apo dridhje"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shfaqet në krye të seksionit të bisedës dhe shfaqet si flluskë pluskuese, shfaq fotografinë e profilit në ekranin e kyçjes"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cilësimet"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Përparësia"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ky aplikacion po shfaqet mbi aplikacionet e tjera në ekran dhe po përdor mikrofonin dhe kamerën."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Cilësimet"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Në rregull"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Ky njoftim është vendosur në heshtje nga sistemi."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Ky njoftim është rritur në nivel nga sistemi."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Ky njoftim është ulur në nivel nga sistemi."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"A ishte e saktë kjo?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Faleminderit për komentin!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Në rregull"</string>
diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml
index 713130f..fb74e38 100644
--- a/packages/SystemUI/res/values-sq/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ja është e lidhur"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ja është shkëputur"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Njoftimet"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Asnjë njoftim"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f9262b0..3cc9f20 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Додирните да бисте видели снимак екрана"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Чување снимка екрана није успело"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уређај мора да буде откључан да би снимак екрана могао да се сачува"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Пробајте да поново направите снимак екрана"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Чување снимка екрана није успело због ограниченог меморијског простора"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија од три црте."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Батерија је пуна."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Проценат напуњености батерије није познат."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Нема телефона."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефона има једну црту."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефона од две црте."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Сигнал телефона од три црте."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигнал телефона је пун."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Нема података."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Сигнал за податке има једну црту."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигнал за податке од две црте."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Сигнал за податке од три црте."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигнал за податке је најјачи."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Повезани сте са <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Повезани сте са <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Повезани смо са уређајем <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX сигнал има две црте."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX сигнал има три црте."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигнал је најјачи."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Веза са етернетом је прекинута."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Етернет је повезан."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Нема сигнала."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Није повезано."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Ниједна црта."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Искључено."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Повезано је."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Повезивање."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роминг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Нема SIM картице."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобилни подаци"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилни подаци су укључени"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилни подаци су искључени"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Није подешено за коришћење података"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Искључено"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth привезивање."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим рада у авиону."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN је укључен."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Нема SIM картице."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Промена мреже мобилног оператера"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Отвори детаље о батерији"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија је на <xliff:g id="NUMBER">%d</xliff:g> посто."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија је на <xliff:g id="PERCENTAGE">%1$s</xliff:g> посто, преостало време на основу коришћења је <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -725,6 +701,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звони или вибрира у зависности од подешавања телефона. Конверзације из апликације <xliff:g id="APP_NAME">%1$s</xliff:g> се подразумевано приказују у облачићима."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлачи вам пажњу помоћу плутајуће пречице до овог садржаја."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Нека систем утврди да ли ово обавештење треба да емитује звук или да вибрира"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Приказује се у врху одељка за конверзације као плутајући облачић, приказује слику профила на закључаном екрану"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Подешавања"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -743,9 +727,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ова апликација се приказује преко других апликација на екрану и користи микрофон и камеру."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Подешавања"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Потврди"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Систем је искључио ово обавештење."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Систем је промовисао ово обавештење."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Систем је поставио ово обавештење на дно."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Да ли је то тачно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Хвала вам на повратним информацијама!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Потврди"</string>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index 77f842c..59151da 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN је повезан"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Веза са VPN-ом је прекинута"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Обавештења"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема обавештења"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3401294..5b8a526 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Visa skärmdumpen genom att trycka här"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Det gick inte att spara skärmdumpen"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skärmdumpen kan bara sparas om enheten är upplåst"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Testa att ta en skärmdump igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri: tre staplar."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet är fulladdat."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Okänd batterinivå."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: en stapel."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: två staplar."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon: tre staplar."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignalen är full."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Inga data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data: en stapel."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data: två staplar."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data: tre staplar."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignalen är full."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Ansluten till <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ansluten till <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Ansluten till <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: två staplar."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: tre staplar."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signalen är full."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet har kopplats från."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet har anslutits."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ingen signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Inte ansluten."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Inga staplar."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Inaktiverad."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Ansluten."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ansluter."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Inget SIM-kort."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata har aktiverats"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata har inaktiverats"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Inte inställd på mobildata"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Av"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internetdelning via Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flygplansläge"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN har aktiverats."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Inget SIM-kort."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Byter leverantörsnätverk"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Visa uppgifter om batteri"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteri: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringa eller vibrera beroende på inställningarna på telefonen. Konversationer från <xliff:g id="APP_NAME">%1$s</xliff:g> visas i bubblor som standard."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Behåller din uppmärksamhet med en flytande genväg till innehållet."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Låt systemet avgöra om den här aviseringen ska låta eller vibrera"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Visas högst upp bland konversationerna som en flytande bubbla, visar profilbilden på låsskärmen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Inställningar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Appen visas över andra appar på skärmen och den använder mikrofonen och kameran."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Inställningar"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Den här aviseringen har tystats av systemet."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Den här aviseringen har flyttats upp av systemet."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Den här aviseringen har flyttats ned av systemet."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Stämmer detta?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Tack för din feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index 141aabf..d7261e6b 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN är anslutet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN är frånkopplat"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Aviseringar"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Inga aviseringar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 4cf09c7..b2b2c37 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Gusa ili utazame picha ya skrini uliyohifadhi"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Imeshindwa kuhifadhi picha ya skrini"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ni sharti ufungue kifaa kabla ya kuhifadhi picha ya skrini"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pau tatu za betri."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Betri imejaa."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Asilimia ya betri haijulikani."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Hakuna simu"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Mwambaa mmoja wa simu."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Miambaa miwili ya simu"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Miambaa mitatu ya simu."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Ishara ya simu imejaa."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Hakuna data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Upapi mmoja wa habari"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Miamba miwili ya data."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Fito tatu za habari."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Ishara ya data imejaa."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Imeunganishwa kwenye <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Imeunganishwa kwenye <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Imeunganishwa kwenye <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Pau mbili za WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Pau tatu za WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Ishara ya WiMAX imejaa."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethaneti imeondolewa."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethaneti imeunganishwa."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Hakuna mtandao"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Haijaunganishwa."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Vipima mtandao sufuri."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Imezimwa."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Imeunganishwa."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Inaunganisha."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Mitandao ya ng\'ambo"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Hakuna SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Data ya Simu"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Data ya Simu Imewashwa"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Umezima data ya mtandao wa simu"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Haijawekewa mipangilio ya kutumia data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Zima"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Shiriki intaneti kwa Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hali ya ndegeni."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN imewashwa."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Hakuna SIM kadi."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mabadiliko katika mtandao wa mtoa huduma"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Fungua maelezo ya betri"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Asilimia <xliff:g id="NUMBER">%d</xliff:g> ya betri"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Betri ina asilimia <xliff:g id="PERCENTAGE">%1$s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%2$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Huenda ikalia au kutetema kulingana na mipangilio ya simu. Mazungumzo kutoka kiputo cha <xliff:g id="APP_NAME">%1$s</xliff:g> kwa chaguomsingi."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Huweka umakinifu wako kwenye maudhui haya kwa kutumia njia ya mkato ya kuelea."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ruhusu mfumo ubainishe iwapo arifa hii inapaswa kutoa sauti au mtetemo"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Huonyeshwa kwenye sehemu ya juu ya mazungumzo, huonekana kama kiputo, huonyesha picha ya wasifu kwenye skrini iliyofungwa"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mipangilio"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Kipaumbele"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Programu hii inachomoza kwenye programu zingine zilizo katika skrini yako na inatumia maikrofoni na kamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Mipangilio"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Sawa"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Arifa hii ilizimwa na mfumo."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Arifa hii ilipandishwa hadhi na mfumo."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Arifa hii ilishushwa hadhi na mfumo."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Je, hatua hii ilikuwa sahihi?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Asante kwa maoni yako!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Sawa"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 9dd37ce..8f6880d 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN imeunganishwa"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN imeondolewa"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Arifa"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Hakuna Arifa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index be66320..d886f00 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -32,4 +32,7 @@
     <!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
     <integer name="navigation_bar_deadzone_orientation">0</integer>
 
+    <!-- Whether wallet view is shown in landscape / seascape orientations -->
+    <bool name="global_actions_show_landscape_wallet_view">true</bool>
+
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index fdf4e3b..3be73ba 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -94,4 +94,11 @@
 
     <!-- Text size for user name in user switcher -->
     <dimen name="kg_user_switcher_text_size">18sp</dimen>
+
+    <!-- TODO(himanshujaju) - add comments -->
+    <dimen name="global_actions_wallet_top_margin">5dp</dimen>
+    <dimen name="controls_header_bottom_margin">12dp</dimen>
+    <dimen name="controls_top_margin">24dp</dimen>
+
+    <dimen name="global_actions_grid_item_layout_height">80dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 5d29c91..8833153 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"ஸ்கிரீன்ஷாட்டைப் பார்க்க, தட்டவும்"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ஸ்கிரீன் ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ஸ்கிரீன்ஷாட் சேமிக்கப்படுவதற்கு முன்பு சாதனம் அன்லாக் செய்யப்பட வேண்டும்"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"பேட்டரி சக்தி மூன்று பார் அளவில் உள்ளது."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"பேட்டரி முழுமையாக உள்ளது."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"பேட்டரி சதவீதம் தெரியவில்லை."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"சிக்னல் இல்லை."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"சிக்னல் முழுமையாக உள்ளது."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"டேட்டா சிக்னல் இல்லை."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"தரவு சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"தரவின் சிக்னல் இரண்டு கோடு வரை உள்ளது."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"தரவு சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"தரவு சிக்னல் முழுமையாக உள்ளது."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> உடன் இணைக்கப்பட்டுள்ளது."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX இரண்டு கோடுகள்."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX மூன்று கோடுகள்."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX சிக்னல் முழுமையாக உள்ளது."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ஈத்தர்நெட் இணைக்கப்பட்டது."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"சிக்னல் இல்லை."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"இணைக்கப்படவில்லை."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"கோடுகள் இல்லை."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ஆஃப்."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"இணைக்கப்பட்டது."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"இணைக்கிறது."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"ரோமிங்"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"வைஃபை"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"சிம் இல்லை."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"மொபைல் டேட்டா"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"மொபைல் டேட்டா இயக்கப்பட்டது"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ஆஃப்"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"புளூடூத் டெதெரிங்."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"விமானப் பயன்முறை."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN இயக்கத்தில் உள்ளது."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"சிம் கார்டு இல்லை."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"மொபைல் நிறுவன நெட்வொர்க்கை மாற்றும்"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"பேட்டரி விவரங்களைத் திறக்கும்"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"பேட்டரி சக்தி <xliff:g id="NUMBER">%d</xliff:g> சதவிகிதம் உள்ளது."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"பேட்டரி: <xliff:g id="PERCENTAGE">%1$s</xliff:g> சதவீதம், உபயோகத்தின் அடிப்படையில் <xliff:g id="TIME">%2$s</xliff:g> மீதமுள்ளது"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"மொபைல் அமைப்புகளின் அடிப்படையில் ஒலிக்கவோ அதிரவோ செய்யும். <xliff:g id="APP_NAME">%1$s</xliff:g> இலிருந்து வரும் உரையாடல்கள் இயல்பாகவே குமிழாகத் தோன்றும்."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"இந்த உள்ளடக்கத்திற்கான மிதக்கும் ஷார்ட்கட் மூலம் உங்கள் கவனத்தைப் பெற்றிருக்கும்."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"இந்த அறிவிப்பு ஒலி எழுப்ப வேண்டுமா அதிர வேண்டுமா என்பதை சிஸ்டம் தீர்மானிக்கும்"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"உரையாடல் பிரிவின் மேற்பகுதியில் மிதக்கும் குமிழாகத் தோன்றும். பூட்டுத் திரையின் மேல் சுயவிவரப் படத்தைக் காட்டும்"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"அமைப்புகள்"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"முன்னுரிமை"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"இந்த ஆப்ஸானது, உங்கள் திரையில் பிற ஆப்ஸின் இடைமுகத்தின் மேல் தோன்றுவதுடன், மைக்ரோஃபோனையும் கேமராவையும் உபயோகிக்கிறது."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"அமைப்புகள்"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"சரி"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"இந்த அறிவிப்பு சிஸ்டத்தால் ஒலியடக்கப்பட்டது."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"இந்த அறிவிப்பு சிஸ்டத்தால் முக்கியமானது என வரையறுக்கப்பட்டது."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"இந்த அறிவிப்பு சிஸ்டத்தால் முக்கியமில்லாதது என வரையறுக்கப்பட்டது."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"இது சரியானதா?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"உங்கள் கருத்துக்கு நன்றி!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"சரி"</string>
@@ -935,7 +924,7 @@
     <string name="notification_channel_general" msgid="4384774889645929705">"பொதுச் செய்திகள்"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"சேமிப்பிடம்"</string>
     <string name="notification_channel_hints" msgid="7703783206000346876">"குறிப்புகள்"</string>
-    <string name="instant_apps" msgid="8337185853050247304">"இன்ஸ்டண்ட் ஆப்ஸ்"</string>
+    <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string>
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index 0483201..9c62d8cf 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN இணைக்கப்பட்டது"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN துண்டிக்கப்பட்டது"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"அறிவிப்புகள்"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"அறிவிப்புகள் எதுவுமில்லை"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 5fed052..ccb4fa7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్‌షాట్ సేవ్ చేయబడింది"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"మీ స్క్రీన్‌షాట్‌ను వీక్షించడానికి నొక్కండి"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"స్క్రీన్‌షాట్‌ని సేవ్ చేయడం సాధ్యం కాలేదు"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"స్క్రీన్‌షాట్ సేవ్ అవ్వకముందే పరికరం అన్‌లాక్ చేయబడాలి"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"స్క్రీన్‌షాట్ తీయడానికి మళ్లీ ప్రయత్నించండి"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"స్క్రీన్‌షాట్‌లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"బ్యాటరీ మూడు బార్లు."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"బ్యాటరీ నిండింది."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"బ్యాటరీ శాతం తెలియదు."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ఫోన్ లేదు."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ఫోన్ ఒక బారు."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ఫోన్ రెండు బార్లు."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ఫోన్ మూడు బార్లు."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ఫోన్ సిగ్నల్ పూర్తిగా ఉంది."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"డేటా లేదు."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"డేటా ఒక బారు."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"డేటా రెండు బార్‌లు."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"డేటా మూడు బార్లు."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"డేటా సిగ్నల్ సంపూర్ణంగా ఉంది."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX రెండు బార్‌లు కలిగి ఉంది."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX మూడు బార్‌లు కలిగి ఉంది."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX సిగ్నల్ పూర్తిగా ఉంది."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ఈథర్‌నెట్ డిస్‌కనెక్ట్ చేయబడింది."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ఈథర్‌నెట్ కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"సిగ్నల్ లేదు."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"కనెక్ట్ చేయబడలేదు."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"సున్నా బార్‌లు."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ఆఫ్‌లో ఉంది."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"కనెక్ట్ అవుతోంది."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"రోమింగ్"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"సిమ్ లేదు."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"మొబైల్ డేటా"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"మొబైల్ డేటా ఆన్ చేయబడింది"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"మొబైల్ డేటా ఆఫ్‌లో ఉంది"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"డేటాను ఉపయోగించే విధంగా సెట్ చేయలేదు"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ఆఫ్ చేయండి"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"బ్లూటూత్ టెథెరింగ్."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ఎయిర్‌ప్లేన్ మోడ్."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPNలో."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM కార్డ్ లేదు."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"క్యారియర్ నెట్‌వర్క్ మారుతోంది"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"బ్యాటరీ వివరాలను తెరుస్తుంది"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"బ్యాటరీ <xliff:g id="NUMBER">%d</xliff:g> శాతం."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"బ్యాటరీ <xliff:g id="PERCENTAGE">%1$s</xliff:g> శాతం ఉంది, మీ వినియోగాన్ని బట్టి <xliff:g id="TIME">%2$s</xliff:g> పని చేస్తుంది"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ఫోన్ సెట్టింగ్‌ల ఆధారంగా రింగ్ లేదా వైబ్రేట్ కావచ్చు. <xliff:g id="APP_NAME">%1$s</xliff:g> నుండి సంభాషణలు ఆటోమేటిక్‌గా బబుల్‌గా కనిపిస్తాయి."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ఫ్లోటింగ్ షార్ట్‌కట్‌తో మీ దృష్టిని ఈ కంటెంట్‌పై నిలిపి ఉంచుతుంది."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ఈ నోటిఫికేషన్ వచ్చినప్పుడు శబ్దం చేయాలా లేదా వైబ్రేట్ చేయాలా అనేది నిర్ణయించడానికి సిస్టమ్‌కు అనుమతి ఇవ్వండి"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"సంభాషణ విభాగం ఎగువన ఉంటుంది, తేలుతున్న బబుల్‌లాగా కనిపిస్తుంది, లాక్ స్క్రీన్‌పై ప్రొఫైల్ ఫోటోను ప్రదర్శిస్తుంది"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"సెట్టింగ్‌లు"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ఈ యాప్ మీ స్క్రీన్‌లోని ఇతర యాప్‌లపై ప్రదర్శించబడుతోంది మరియు మైక్రోఫోన్, కెమెరాను ఉపయోగిస్తుంది."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"సెట్టింగ్‌లు"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"సరే"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"ఈ నోటిఫికేషన్‌ను సిస్టమ్ నిశ్శబ్దంగా ఉండేలా చేసింది."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"ఈ నోటిఫికేషన్ స్థాయిని సిస్టమ్ పెంచింది."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"ఈ నోటిఫికేషన్ స్థాయిని సిస్టమ్ తగ్గించింది."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"ఇది సరైనదేనా?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"మీ ఫీడ్‌బ్యాక్‌ను అందించినందుకు ధన్యవాదాలు!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"సరే"</string>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index 67fb678..50f4b45 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN కనెక్ట్ చేయబడింది"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN డిస్‌కనెక్ట్ చేయబడింది"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"నోటిఫికేషన్‌లు"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్‌లు లేవు"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ffa84d3..9c408e1 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"แตะเพื่อดูภาพหน้าจอ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"บันทึกภาพหน้าจอไม่ได้"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ต้องปลดล็อกอุปกรณ์ก่อนจึงจะบันทึกภาพหน้าจอได้"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ลองบันทึกภาพหน้าจออีกครั้ง"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"แบตเตอรี่สามขีด"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"แบตเตอรี่เต็ม"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ไม่ทราบเปอร์เซ็นต์แบตเตอรี่"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"ไม่มีสัญญาณโทรศัพท์"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"สัญญาณโทรศัพท์สองขีด"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"สัญญาณโทรศัพท์สามขีด"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"สัญญาณโทรศัพท์เต็ม"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"ไม่มีข้อมูล"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"สัญญาณข้อมูลหนึ่งขีด"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"สัญญาณข้อมูลสองขีด"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"สัญญาณข้อมูลสามขีด"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"สัญญาณข้อมูลเต็ม"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"เชื่อมต่อ <xliff:g id="WIFI">%s</xliff:g> แล้ว"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"เชื่อมต่อกับ <xliff:g id="BLUETOOTH">%s</xliff:g> แล้ว"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"เชื่อมต่อกับ <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"สัญญาณ WiMAX สองขีด"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"สัญญาณ WiMAX สามขีด"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"สัญญาณ WiMAX เต็ม"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"เชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"ไม่มีสัญญาณ"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"ไม่ได้เชื่อมต่อ"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"ศูนย์ขีด"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"ปิดอยู่"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"เชื่อมต่อแล้ว"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"กำลังเชื่อมต่อ"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"โรมมิ่ง"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"ไม่มีซิมการ์ด"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"เน็ตมือถือ"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"อินเทอร์เน็ตมือถือเปิดอยู่"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"เน็ตมือถือปิดอยู่"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"ปิด"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"การปล่อยสัญญาณบลูทูธ"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"โหมดบนเครื่องบิน"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN เปิดอยู่"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"ไม่มีซิมการ์ด"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"เปิดรายละเอียดแบตเตอรี่"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"แบตเตอรี่ <xliff:g id="NUMBER">%d</xliff:g> เปอร์เซ็นต์"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"แบตเตอรี่ <xliff:g id="PERCENTAGE">%1$s</xliff:g> เปอร์เซ็นต์ ใช้ได้อีกประมาณ <xliff:g id="TIME">%2$s</xliff:g> ทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"อาจส่งเสียงหรือสั่นโดยขึ้นอยู่กับการตั้งค่าโทรศัพท์ การสนทนาจาก <xliff:g id="APP_NAME">%1$s</xliff:g> จะแสดงเป็นบับเบิลโดยค่าเริ่มต้น"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ดึงดูดความสนใจของคุณไว้เสมอด้วยทางลัดแบบลอยที่มายังเนื้อหานี้"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ให้ระบบพิจารณาว่าจะให้การแจ้งเตือนนี้ส่งเสียงหรือสั่นหรือไม่"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"แสดงที่ด้านบนของส่วนการสนทนา ปรากฏเป็นบับเบิลแบบลอย แสดงรูปโปรไฟล์บนหน้าจอล็อก"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"การตั้งค่า"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ลำดับความสำคัญ"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"แอปนี้กำลังแสดงทับแอปอื่นๆ ในหน้าจอและใช้ไมโครโฟนและกล้อง"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"การตั้งค่า"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ตกลง"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"การแจ้งเตือนนี้ถูกปิดเสียงโดยระบบ"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"การแจ้งเตือนนี้ได้รับการเพิ่มระดับโดยระบบ"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"การแจ้งเตือนนี้ถูกลดระดับโดยระบบ"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"การดำเนินการนี้ถูกต้องไหม"</string>
     <string name="feedback_response" msgid="4671729244976641339">"ขอบคุณที่แสดงความคิดเห็น"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ตกลง"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index 4a9144b..0724821 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"เชื่อมต่อ VPN แล้ว"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ยกเลิกการเชื่อมต่อ VPN แล้ว"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"การแจ้งเตือน"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ไม่มีการแจ้งเตือน"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b8cdef1..9e8aa96 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"I-tap upang tingnan ang iyong screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Hindi ma-save ang screenshot"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Dapat naka-unlock ang device bago ma-save ang screenshot"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Subukang kumuhang muli ng screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterya na tatlong bar."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Puno na ang baterya."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Hindi alam ang porsyento ng baterya."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Walang telepono."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telepono na isang bar."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telepono na dalawang bar."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telepono na tatlong bar."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Puno ang signal ng telepono."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Walang data."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data na isang bar."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data na dalawang bar."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data na tatlong bar."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Puno ang signal ng data."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Nakakonekta sa <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Nakakonekta sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Nakakonekta sa <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX na dalawang bar."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX na tatlong bar."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Puno ang signal ng WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Nadiskonekta ang Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Nakakonekta ang Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Walang signal."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Hindi nakakonekta."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Walang mga bar."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Naka-off."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Nakakonekta."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Kumokonekta."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Walang SIM."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobile Data"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Naka-on ang Mobile Data"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Naka-off ang mobile data"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Hindi nakatakdang gumamit ng data"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Naka-off"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Pag-tether ng Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode na eroplano."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Naka-on ang VPN."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Walang SIM card."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Nagpapalit ng carrier network"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Buksan ang mga detalye ng baterya"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterya <xliff:g id="NUMBER">%d</xliff:g> (na) porsyento."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (na) porsyento ang baterya, nasa <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa paggamit mo"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puwedeng mag-ring o mag-vibrate batay sa mga setting ng telepono. Mga pag-uusap mula sa <xliff:g id="APP_NAME">%1$s</xliff:g> bubble bilang default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Pinapanatili ang iyong atensyon sa pamamagitan ng lumulutang na shortcut sa content na ito."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ipatukoy sa system kung dapat gumawa ng tunog o pag-vibrate ang notification na ito"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Makikita sa itaas ng seksyon ng pag-uusap, lumalabas bilang floating bubble, ipinapakita sa lock screen ang larawan sa profile"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mga Setting"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priyoridad"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ipinapakita ang app na ito sa ibabaw ng iba pang app sa iyong screen at ginagamit nito ang mikropono at camera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Mga Setting"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Ginawang silent ng system ang notification na ito."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Na-promote ng system ang notification na ito."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Na-demote ng system ang notification na ito."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Tama ba ito?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Salamat sa iyong feedback!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 3489503..8dcc22f 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Nakakonekta ang VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Nakadiskonekta ang VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Mga Notification"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Walang Notification"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 74666b2..2b89578 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Ekran görüntünüzü görmek için dokunun"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekran görüntüsü kaydedilemedi"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ekran görüntüsünün kaydedilebilmesi için cihazın kilidi açık olmalıdır"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tekrar ekran görüntüsü almayı deneyin"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pil gücü üç çubuk."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Pil tam dolu."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pil yüzdesi bilinmiyor."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon sinyali yok."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon sinyali bir çubuk."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon sinyali iki çubuk."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon sinyali üç çubuk."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon sinyali tam."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Veri yok."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Veri sinyali bir çubuk."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Veri sinyali iki çubuk."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Veri sinyali üç çubuk."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Veri sinyali tam."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ile bağlı."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ile bağlı."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> bağlantısı kuruldu."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX iki çubuk."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX üç çubuk."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX sinyali tam."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bağlantısı kesildi."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet bağlandı."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Sinyal yok."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Bağlanmadı."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Sıfır çubuk."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Kapalı."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Bağlandı."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Bağlanıyor."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Dolaşım"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Kablosuz"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kart yok."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobil Veri"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil Veri Açık"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil veri kapalı"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Veri kullanmak üzere ayarlanmadı"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Kapalı"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçak modu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN açık."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM kart yok."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operatör ağı değiştiriliyor"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Pil ayrıntılarını aç"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Pil yüzdesi: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pil yüzde <xliff:g id="PERCENTAGE">%1$s</xliff:g> dolu. Kullanımınıza göre yaklaşık <xliff:g id="TIME">%2$s</xliff:g> süresi kaldı"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına bağlı olarak zili çalabilir veya titreyebilir <xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamadan görüşmeler varsayılan olarak baloncukla gösterilir."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kayan kısayolla dikkatinizi bu içerik üzerinde tutar."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirimin ses çıkarması veya titreşmesi gerekip gerekmediğine sistem karar versin"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Görüşme bölümünün üstünde gösterilir, kayan baloncuk olarak görünür, kilit ekranında profil resmini görüntüler"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Öncelik"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu uygulama, ekranınızdaki diğer uygulamaların üzerinde görüntüleniyor ve mikrofon ile kamerayı kullanıyor."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Ayarlar"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"Tamam"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildirim sistem tarafından sessize alındı."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildirimin düzeyi sistem tarafından yükseltildi."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildirimin düzeyi sistem tarafından düşürüldü."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Bu doğru muydu?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Geri bildiriminiz için teşekkürler!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"Tamam"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index bfb1ae2..babd460 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN bağlandı"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN bağlantısı kesildi"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> yoluyla"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirimler"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirim Yok"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 2737ce8..ec7b85a 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -28,7 +28,7 @@
     <string name="battery_low_percent_format" msgid="4276661262843170964">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"На основі використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"Залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим економії заряду акумулятора."</string>
+    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим енергозбереження."</string>
     <string name="invalid_charger" msgid="4370074072117767416">"Не вдається зарядити через USB. Використовуйте зарядний пристрій, який входить у комплект пристрою."</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"Не вдається зарядити через USB"</string>
     <string name="invalid_charger_text" msgid="2339310107232691577">"Використовуйте зарядний пристрій, який входить у комплект пристрою"</string>
@@ -36,7 +36,7 @@
     <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Увімкнути режим енергозбереження?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Про режим енергозбереження"</string>
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Увімкнути"</string>
-    <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим економії заряду акумулятора"</string>
+    <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим енергозбереження"</string>
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"Налаштування"</string>
     <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автообертання екрана"</string>
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Торкніться, щоб переглянути знімок екрана"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не вдалося зберегти знімок екрана"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Щоб зберегти знімок екрана, розблокуйте пристрій"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Спробуйте зробити знімок екрана ще раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд акумулятора: три смужки."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятор заряджений."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Відсоток заряду акумулятора невідомий."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Немає сигналу телефону."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Одна смужка сигналу телефону."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Дві смужки сигналу телефону."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Три смужки сигналу телефону."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Максимальний сигнал телефону."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Немає сигналу даних."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Одна смужка сигналу даних."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дві смужки сигналу даних."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Три смужки сигналу даних."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Максимальний сигнал даних."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Підключено до <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Підключено до <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Під’єднано до пристрою <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Дві смужки сигналу WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Три смужки сигналу WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Максимальний сигнал WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet відключено."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet підключено."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Немає сигналу."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Не з’єднано."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Нуль смужок сигналу."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Вимкнено."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Під’єднано."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"З’єднання."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Роумінг"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Немає SIM-карти."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Мобільне передавання даних"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобільне передавання даних увімкнено"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобільне передавання даних вимкнено"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Не вибрано для використання даних"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Вимкнено"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-модем"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим польоту."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Мережу VPN увімкнено."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Немає SIM-карти."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Змінення мережі оператора"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Відкрити деталі акумулятора"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд акумулятора у відсотках: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Згідно з даними про використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> заряду акумулятора – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -509,7 +485,7 @@
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Видалити"</string>
     <string name="battery_saver_notification_title" msgid="8419266546034372562">"Режим енергозбереження ввімкнено"</string>
     <string name="battery_saver_notification_text" msgid="2617841636449016951">"Знижується продуктивність і обмежуються фонові дані"</string>
-    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим економії заряду акумулятора"</string>
+    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим енергозбереження"</string>
     <string name="media_projection_dialog_text" msgid="1755705274910034772">"Додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string>
     <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string>
     <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Почати запис або трансляцію?"</string>
@@ -728,6 +704,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може дзвонити або вібрувати залежно від налаштувань телефона. Показує спливаючі розмови з додатка <xliff:g id="APP_NAME">%1$s</xliff:g> за умовчанням."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привертає увагу до контенту плаваючим ярликом."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволити системі визначати, чи має сповіщення супроводжуватися звуком або вібрацією"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"З\'являється вгорі розділу розмов у спливаючому сповіщенні та показує зображення профілю на заблокованому екрані"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Налаштування"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Пріоритет"</string>
@@ -746,9 +730,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Цей додаток відображається поверх інших додатків на екрані та використовує мікрофон і камеру."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Налаштування"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Система заглушила це сповіщення."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Система підвищила статус цього сповіщення."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Система знизила статус цього сповіщення."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Правильно?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Дякуємо за відгук!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
@@ -975,11 +964,11 @@
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> показувати фрагменти будь-якого додатка"</string>
     <string name="slice_permission_allow" msgid="6340449521277951123">"Дозволити"</string>
     <string name="slice_permission_deny" msgid="6870256451658176895">"Заборонити"</string>
-    <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб увімкнути автоматичний режим економії заряду акумулятора"</string>
+    <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб налаштувати режим енергозбереження"</string>
     <string name="auto_saver_text" msgid="3214960308353838764">"Вмикати, коли заряд акумулятора закінчується"</string>
     <string name="no_auto_saver_action" msgid="7467924389609773835">"Ні, дякую"</string>
     <string name="auto_saver_enabled_title" msgid="4294726198280286333">"Автоматичний перехід у режим енергозбереження ввімкнено"</string>
-    <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим економії заряду акумулятора вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string>
+    <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим енергозбереження вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string>
     <string name="open_saver_setting_action" msgid="2111461909782935190">"Налаштування"</string>
     <string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
     <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index 4a4cac9..170b068 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Мережу VPN під\'єднано"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Мережу VPN від\'єднано"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Сповіщення"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Немає сповіщень"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 7488323..15a4f30 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکا"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"اسکرین شاٹ محفوظ کرنے سے پہلے آلے کو غیر مقفل کرنا ضروری ہے"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"بیٹری کے تین بارز۔"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"بیٹری بھری ہے۔"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"بیٹری کی فیصد نامعلوم ہے۔"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"کوئی فون نہیں ہے۔"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"فون کا ایک بار۔"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"فون کے دو بارز۔"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"فون کے تین بارز۔"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"فون سگنل پورا ہے۔"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"کوئی ڈیٹا نہیں ہے۔"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ڈیٹا کا ایک بار۔"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ڈیٹا کے دو بارز۔"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ڈیٹا کے تین بارز۔"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"ڈیٹا سگنل بھرا ہوا ہے۔"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> سے منسلک ہیں۔"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> سے منسلک ہیں۔"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> سے منسلک ہے۔"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‏WiMAX دو بارز۔"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"‏WiMAX تین بارز۔"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"‏WiMAX سگنل پورا ہے۔"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ایتھرنیٹ منقطع ہے۔"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ایتھرنیٹ منسلک ہے۔"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"کوئی سگنل نہیں ہے۔"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"مربوط نہیں ہے۔"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"صفر بارز۔"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"آف۔"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"مربوط۔"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"مربوط ہو رہا ہے۔"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+‎"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+‎"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+‎"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X‎"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"رومنگ"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"‏کوئی SIM نہیں ہے۔"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"موبائل ڈیٹا"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"موبائل ڈیٹا آن ہے"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"موبائل ڈیٹا آف ہے"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"ڈیٹا استعمال کرنے کے لیے سیٹ نہیں ہے"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"آف ہے"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"بلوٹوتھ ٹیدرنگ۔"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ہوائی جہاز وضع۔"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN آن ہے۔"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"‏کوئی SIM کارڈ نہیں ہے۔"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"کیریئر نیٹ ورک کی تبدیلی"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"بیٹری کی تفصیلات کھولیں"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"بیٹری <xliff:g id="NUMBER">%d</xliff:g> فیصد۔"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"آپ کے استعمال کی بنیاد پر بیٹری <xliff:g id="PERCENTAGE">%1$s</xliff:g> فیصد، تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"فون کی ترتیبات کے مطابق وائبریٹ یا گھنٹی بج سکتی ہے۔ بذریعہ ڈیفالٹ <xliff:g id="APP_NAME">%1$s</xliff:g> بلبلہ سے گفتگوئیں۔"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"اس مواد کے فلوٹنگ شارٹ کٹ کے ساتھ آپ کی توجہ دیتی ہے۔"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"سسٹم کو اس بات کا تعین کرنے دیں کہ آیا اس اطلاع کی آواز ہو یا وائبریٹ ہونا چاہیے"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"گفتگو کے سیکشن کے اوپری حصے پر دکھاتا ہے، تیرتے بلبلے کی طرح ظاہر ہوتا ہے، لاک اسکرین پر پروفائل تصویر دکھاتا ہے"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ترتیبات"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ترجیح"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"یہ ایپ آپ کی اسکرین پر دیگر ایپس پر ڈسپلے کر رہی ہے اور مائیکروفون اور کیمرے کا استعمال کر رہی ہے۔"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"ترتیبات"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"ٹھیک ہے"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"سسٹم کے ذریعے اس اطلاع کو خاموش کیا گيا۔"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"سسٹم کے ذریعے اس اطلاع کو پروموٹ کیا گيا۔"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"سسٹم کے ذریعے اس اطلاع کو ڈیموٹ کیا گيا۔"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"کیا یہ درست تھا؟"</string>
     <string name="feedback_response" msgid="4671729244976641339">"آپ کے تاثرات کا شکریہ!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"ٹھیک ہے"</string>
diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml
index 20d3a58..fbaa3f6 100644
--- a/packages/SystemUI/res/values-ur/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏VPN منسلک ہے"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏VPN غیر منسلک ہے"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"اطلاعات"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"کوئی اطلاع نہیں ہے"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 997197d..9e1387e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinshotni ochish uchun bosing"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinshot saqlanmadi"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinshotni saqlashdan oldin qurilma qulflanmagan boʻlishi lozim"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Qayta skrinshot olib ko‘ring"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya uchta panelda."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya to‘la."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareya quvvati foizi nomaʼlum."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Signal yo‘q."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon bitta panelda."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon ikkita panelda."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon uchta panelda."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon signali to‘liq."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ma’lumotlar yo‘q."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Ma’lumotlar bitta panelda."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Ma’lumotlar ikkita panelda."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Ma’lumotlar uchta panelda."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Internet signali butun."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Ulangan: <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ulangan: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Bunga ulangan: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Ikkita ustunli WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Uchta ustunli WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"To‘liq signalli WiMAX."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Qurilma Ethernet tarmog‘idan uzildi."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Qurilma Ethernet tarmog‘iga ulandi."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Signal yo‘q."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Ulanmagan."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Signal ustuni yo‘q."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Yoqilmagan"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Ulangan."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ulanmoqda…"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Rouming"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kartasiz."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Mobil internet"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil internet yoniq"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil internet yoqilmagan"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Yoqilmagan"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth modem"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Parvoz rejimi"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN yoniq."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"SIM karta solinmagan."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobil tarmoqni o‘zgartirish"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Quvvat sarfi tafsilotlari"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> foiz."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya quvvati <xliff:g id="PERCENTAGE">%1$s</xliff:g> foiz, joriy holatda yana <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon sozlamalari asosida jiringlashi yoki tebranishi mumkin. <xliff:g id="APP_NAME">%1$s</xliff:g> suhbatlari standart holatda bulutcha shaklida chiqadi."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu kontentni ochuvchi erkin yorliq diqqatingizda boʻladi."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirishnoma jiringlashi yoki tebranishini hal qilsin"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Suhbatlar ruknining tepasida qalqib chiquvchi bulutcha shaklida chiqadi, ekran qulfida profil rasmi chiqadi"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Sozlamalar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Muhim"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu ilova ekranda boshqa ilovalar ustidan ochilgan hamda mikrofon va kameradan foydalanmoqda."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Sozlamalar"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildirishnoma tizim tomonidan ovozsiz qilindi."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildirishnoma tizim tomonidan balandlatildi."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildirishnoma tizim tomonidan pasaytirildi."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Xatolar boʻlmadimi?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Fikr-mulohazangiz uchun tashakkur!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
@@ -778,7 +767,7 @@
     </plurals>
     <string name="battery_panel_title" msgid="5931157246673665963">"Batareya sarfi"</string>
     <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
-    <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash rejimi"</string>
+    <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash"</string>
     <string name="battery_detail_switch_summary" msgid="3668748557848025990">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> tugmasi"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Bosh ekran"</string>
diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml
index fc4ecd3..f4b4b08 100644
--- a/packages/SystemUI/res/values-uz/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ulandi"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN uzildi"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirishnomalar"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirishnomalar yoʻq"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1acdbb5..92929b8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Nhấn để xem ảnh chụp màn hình của bạn"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Không thể lưu ảnh chụp màn hình"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Bạn phải mở khóa thiết bị để chúng tôi có thể lưu ảnh chụp màn hình"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Hãy thử chụp lại màn hình"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Mức pin ba vạch."</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Mức pin đầy."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Tỷ lệ phần trăm pin không xác định."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Không có điện thoại nào."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tín hiệu điện thoại một vạch."</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tín hiệu điện thoại hai vạch."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tín hiệu điện thoại ba vạch."</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Tín hiệu điện thoại đầy đủ."</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Không có dữ liệu."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Tín hiệu dữ liệu một vạch."</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Tín hiệu dữ liệu hai vạch."</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tín hiệu dữ liệu ba vạch."</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Tín hiệu dữ liệu đầy đủ."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Đã kết nối với <xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Đã kết nối với <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Đã kết nối với <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX hai vạch."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ba vạch."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Tín hiệu WiMAX đầy đủ."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Đã ngắt kết nối Ethernet."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Đã kết nối Ethernet."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Không có tín hiệu nào."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Chưa được kết nối."</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"0 vạch."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Tắt."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Đã kết nối."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Đang kết nối."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Chuyển vùng"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Không có SIM nào."</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Dữ liệu di động"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Dữ liệu di động đang bật"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Đã tắt dữ liệu di động"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Chưa được đặt để sử dụng dữ liệu"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Tắt"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Chia sẻ Internet qua Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Chế độ trên máy bay."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN đang bật."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Không có thẻ SIM nào."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Thay đổi mạng của nhà mạng"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Mở chi tiết về pin"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> phần trăm pin."</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> phần trăm pin, còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Có thể đổ chuông hoặc rung tùy theo chế độ cài đặt trên điện thoại. Theo mặc định, các cuộc trò chuyện từ <xliff:g id="APP_NAME">%1$s</xliff:g> được phép hiển thị dưới dạng bong bóng."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Luôn chú ý vào nội dung này bằng phím tắt nổi."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Cho phép hệ thống quyết định xem thông báo này phát âm thanh hay rung"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Hiển thị cuộc trò chuyện ở đầu phần cuộc trò chuyện và dưới dạng bong bóng nổi, hiển thị ảnh hồ sơ trên màn hình khóa"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cài đặt"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ứng dụng này đang hiển thị chồng lên các ứng dụng khác trên màn hình, đồng thời đang sử dụng micrô và máy ảnh."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Cài đặt"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Hệ thống đã tắt tiếng thông báo này."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Hệ thống đã nâng mức ưu tiên của thông báo này."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Hệ thống đã giảm mức ưu tiên của thông báo này."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Thông tin này có chính xác không?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Cảm ơn bạn đã phản hồi!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 98697fd..3dfc8c1 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN đã được kết nối"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN đã bị ngắt kết nối"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Thông báo"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Không có thông báo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 68630bb..827ca5f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"点按即可查看您的屏幕截图"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"无法保存屏幕截图"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必须先解锁设备,然后才能保存屏幕截图"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"请再次尝试截屏"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由于存储空间有限,无法保存屏幕截图"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"此应用或您所在的单位不允许进行屏幕截图"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"电池电量为三格。"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"电池电量满格。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"电池电量百分比未知。"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"没有手机信号。"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"手机信号强度为一格。"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"手机信号强度为两格。"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"手机信号强度为三格。"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"手机信号满格。"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"没有数据网络信号。"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"数据信号强度为一格。"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"数据信号强度为两格。"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"数据信号强度为三格。"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"数据信号满格。"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"已连接到“<xliff:g id="WIFI">%s</xliff:g>”。"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已连接到<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"已连接到 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 信号强度为两格。"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 信号强度为三格。"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 信号满格。"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"以太网已断开连接。"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"以太网已连接。"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"无信号。"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"未连接。"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"信号强度为零格。"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"关闭。"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"已连接。"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"正在连接。"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"漫游"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"无 SIM 卡。"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"移动数据"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"移动数据已开启"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"移动数据网络已关闭"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"未设置为使用移动数据"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"关闭"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"蓝牙网络共享。"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飞行模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已开启。"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"没有 SIM 卡。"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"运营商网络正在更改"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"打开电量详情"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"电池电量为百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"电池电量为 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,根据您的使用情况,大约还可使用 <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能会响铃或振动(取决于手机设置)。默认情况下,来自<xliff:g id="APP_NAME">%1$s</xliff:g>的对话会以对话泡的形式显示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"通过可链接到这项内容的浮动快捷方式吸引您的注意。"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"让系统决定是否应让设备在收到此通知时发出提示音或振动"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以悬浮对话泡形式显示在对话部分顶部,如果设备处于锁定状态,在锁定屏幕上显示个人资料照片"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"设置"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"优先"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"此应用正显示在屏幕上其他应用的上层,并且正在使用麦克风和摄像头。"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"设置"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"确定"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"此通知已被系统静音。"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"此通知已被系统升级。"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"此通知已被系统降级。"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"是否正确?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"感谢您提供反馈!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"确定"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index 169d98a..1e599ca 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已连接"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已断开连接"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"没有通知"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ddf60fb..50bac07 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"輕按即可查看螢幕擷取畫面"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕擷取畫面"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再嘗試拍攝螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"應用程式或您的機構不允許擷取螢幕畫面"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量為三格。"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"電池已滿。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電量百分比不明。"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度為一格。"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度為兩格。"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電話訊號強度為三格。"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電話訊號滿格。"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"沒有數據網絡。"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"數據網絡訊號強度為一格。"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"數據網絡訊號強度為兩格。"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"數據網絡訊號強度為三格。"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"數據網絡訊號滿格。"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"已連線至<xliff:g id="WIFI">%s</xliff:g>。"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"已連接至 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 訊號強度兩格。"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 訊號強度三格。"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 訊號滿格。"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"以太網連接中斷。"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"已連接以太網。"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"沒有訊號。"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"未連線。"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"訊號強度為零格。"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"關閉。"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"已連線。"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"連線中。"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"漫遊"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"無 SIM 卡。"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"流動數據"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"開咗流動數據"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"流動數據已關閉"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"未設定至可使用資料"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"關閉"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"藍牙網絡共享。"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛航模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"開咗 VPN。"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"沒有 SIM 卡。"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"流動網絡供應商網絡正在變更"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"開啟電池詳細資料"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"電量仲剩番 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你嘅使用情況,仲可以用大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機設定發出鈴聲或震動。「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會預設以對話氣泡顯示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"為此內容建立浮動捷徑以保持注意力。"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"由系統判斷是否要讓此通知發出音效或震動"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話泡顯示在對話部分的頂部,並在上鎖畫面顯示個人檔案相片"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"重要"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"此應用程式目前透過其他應用程式在畫面上顯示內容,且正在使用麥克風和相機。"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"確定"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"系統已將此通知設為靜音。"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"系統已將此通知升級。"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"系統已將此通知降級。"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"多謝您提供意見!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 8581851..92b1762 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已中斷連線"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 85aae2e..0ff8ffa 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"輕觸即可查看螢幕截圖"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕截圖"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再次嘗試拍攝螢幕截圖"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕截圖"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量三格。"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"電池電量已滿。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池電量不明。"</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度一格。"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度兩格。"</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電話訊號強度三格。"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電話訊號滿格。"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"沒有數據網路。"</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"數據網路訊號強度一格。"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"數據網路訊號強度兩格。"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"數據網路訊號強度三格。"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"數據網路訊號滿格。"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"已連線至<xliff:g id="WIFI">%s</xliff:g>。"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"已連線至 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 訊號兩格。"</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 訊號三格。"</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 訊號滿格。"</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"未連上乙太網路。"</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"已連上乙太網路。"</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"沒有訊號。"</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"尚未連線。"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"訊號強度零格。"</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"關閉。"</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"已連線。"</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"連線中。"</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"漫遊"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"沒有 SIM 卡。"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"行動數據"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"行動數據已開啟"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"行動數據已關閉"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"並未設為使用行動數據"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"已關閉"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"藍牙網路共用"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛行模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已開啟。"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"沒有 SIM 卡。"</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"電信業者網路正在進行變更"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"開啟電量詳細資料"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"目前的電量為 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你的使用情形,大約還能使用到<xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機的設定響鈴或震動。根據預設,來自「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會以對話框形式顯示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"利用浮動式捷徑快速存取這項內容。"</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"由系統判斷要讓裝置在收到這則通知時震動還是發出音效"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話框的形式顯示在對話部分的頂端。如果裝置處於鎖定狀態,則在螢幕鎖定畫面上顯示個人資料相片"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"這個應用程式顯示在畫面上其他應用程式的上層,且正在使用麥克風和相機。"</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"確定"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"系統已將這則通知設為靜音。"</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"系統已提升這則通知的優先順序。"</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"系統已降低這則通知的優先順序。"</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"感謝你提供意見!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index fcb16b7..db0781a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 連線已中斷"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index ca87d97..321fd20 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -83,6 +83,7 @@
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string>
     <string name="screenshot_saved_text" msgid="7778833104901642442">"Thepha ukuze ubuke isithombe-skrini sakho"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ayikwazanga ukulondoloza isithombe-skrini"</string>
+    <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Idivayisi kufanele ivulwe ngaphambi kokuthi isithombe-skrini singalondolozwa"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zama ukuthatha isithombe-skrini futhi"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string>
@@ -186,16 +187,6 @@
     <string name="accessibility_battery_three_bars" msgid="118341923832368291">"Amabha amathathu ebhethri"</string>
     <string name="accessibility_battery_full" msgid="1480463938961288494">"Ibhethri igcwele."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Iphesenti lebhethri alaziwa."</string>
-    <string name="accessibility_no_phone" msgid="8828412144430247025">"Ayikho ifoni."</string>
-    <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ibha eyodwa yefoni"</string>
-    <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Amabha amabilil efoni."</string>
-    <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Amabha amathathu efoni"</string>
-    <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Isiginali yefoni igcwele"</string>
-    <string name="accessibility_no_data" msgid="2124768255213392359">"Ayikho idatha."</string>
-    <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Idatha enye yebha"</string>
-    <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Amabha amabili edatha"</string>
-    <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Amabha amathathu edatha"</string>
-    <string name="accessibility_data_signal_full" msgid="283507058258113551">"Igcwele i-signal yedatha"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"Xhuma ku-<xliff:g id="WIFI">%s</xliff:g>."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Xhuma ku-<xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_cast_name" msgid="7344437925388773685">"Ixhumeke ku-<xliff:g id="CAST">%s</xliff:g>."</string>
@@ -204,8 +195,6 @@
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Amabha amabili we-WiMAX."</string>
     <string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Amabha amathathu we-WiMAX."</string>
     <string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Isiginali ye-WiMAX egcwele."</string>
-    <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"I-Ethernet inqanyuliwe."</string>
-    <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"I-Ethernet ixhunyiwe."</string>
     <string name="accessibility_no_signal" msgid="1115622734914921920">"Ayikho isignali."</string>
     <string name="accessibility_not_connected" msgid="4061305616351042142">"Akuxhunyiwe"</string>
     <string name="accessibility_zero_bars" msgid="1364823964848784827">"Amabha ayiqanda."</string>
@@ -217,30 +206,17 @@
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Vala."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"Ixhunyiwe."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Iyaxhuma."</string>
-    <string name="data_connection_gprs" msgid="2752584037409568435">"I-GPRS"</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"I-HSPA"</string>
-    <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
-    <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
-    <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
-    <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
-    <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
-    <string name="data_connection_lte" msgid="557021044282539923">"I-LTE"</string>
-    <string name="data_connection_lte_plus" msgid="4799302403782283178">"I-LTE+"</string>
-    <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Iyazulazula"</string>
-    <string name="data_connection_edge" msgid="6316755666481405762">"I-EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"I-Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="1140839832913084973">"Ayikho i-SIM"</string>
     <string name="accessibility_cell_data" msgid="172950885786007392">"Idatha Yeselula"</string>
     <string name="accessibility_cell_data_on" msgid="691666434519443162">"Idatha yeselula ivuliwe"</string>
-    <string name="cell_data_off_content_description" msgid="9165555931499878044">"Idatha yeselula ivaliwe"</string>
-    <string name="not_default_data_content_description" msgid="6757881730711522517">"Akusethiwe ukuze kusetshenziswe idatha"</string>
     <string name="cell_data_off" msgid="4886198950247099526">"Valiwe"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Imodemu nge-Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Imodi yendiza."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"I-VPN ivuliwe."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"Alikho ikhadi le-SIM."</string>
-    <string name="carrier_network_change_mode" msgid="5174141476991149918">"Inethiwekhi yenkampani yenethiwekhi iyashintsha"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"Vula imininingwane yebhethri"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Iphesenti <xliff:g id="NUMBER">%d</xliff:g> lebhethri"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Amaphesenti ebhethri ngu-<xliff:g id="PERCENTAGE">%1$s</xliff:g>, cishe kusele okungu-<xliff:g id="TIME">%2$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
@@ -722,6 +698,14 @@
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ingase ikhale noma idlidlize kuya ngamasethingi wefoni yakho. Izingxoxo ezivela ku-<xliff:g id="APP_NAME">%1$s</xliff:g> ziba yibhamuza ngokuzenzakalela."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Igcina ukunaka kwakho ngesinqamuleli esintantayo kulokhu okuqukethwe."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Vumela isistimu inqume uma lesi saziso kufanele senze umsindo noma sidlidlize"</string>
+    <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+    <skip />
+    <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+    <skip />
     <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Iboniswa ngenhla kwesigaba sengxoxo, ivela njengebhamuza elintantayo, ibonisa isithombe sephrofayela kukukhiya isikrini"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Izilungiselelo"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Okubalulekile"</string>
@@ -740,9 +724,14 @@
     <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Lolu hlelo lokusebenza liboniswa ngaphezulu kwezinye izinhlelo zokusebenza kusikrini sakho futhi kusetshenziswa imakrofoni nekhamera."</string>
     <string name="notification_appops_settings" msgid="5208974858340445174">"Izilungiselelo"</string>
     <string name="notification_appops_ok" msgid="2177609375872784124">"KULUNGILE"</string>
-    <string name="feedback_silenced" msgid="5382212321253328247">"Lesi saziso sithuliswe isistimu."</string>
-    <string name="feedback_promoted" msgid="8075757485407091976">"Lesi saziso siphromothwe isistimu."</string>
-    <string name="feedback_demoted" msgid="5848066008939031913">"Lesi saziso sehliswe isikhundla isistimu."</string>
+    <!-- no translation found for feedback_alerted (5192459808484271208) -->
+    <skip />
+    <!-- no translation found for feedback_silenced (9116540317466126457) -->
+    <skip />
+    <!-- no translation found for feedback_promoted (2125562787759780807) -->
+    <skip />
+    <!-- no translation found for feedback_demoted (951884763467110604) -->
+    <skip />
     <string name="feedback_prompt" msgid="2278631214125128281">"Ingabe kade kulungile lokhu?"</string>
     <string name="feedback_response" msgid="4671729244976641339">"Siyabonga ngempendulo!"</string>
     <string name="feedback_ok" msgid="6481426753298857144">"KULUNGILE"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index 5cb6c1d1..a9b7597 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -24,4 +24,6 @@
     <string name="notification_vpn_connected" msgid="3891023882833274730">"I-VPN ixhunyiwe"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"I-VPN inqanyuliwe"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="tv_notification_panel_title" msgid="5311050946506276154">"Izaziso"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Azikho Izaziso"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 78d92c4..897e390 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -161,5 +161,11 @@
         <attr name="sensorPressureCoefficient" format="float"/>
         <attr name="sensorTouchAreaCoefficient" format="float"/>
     </declare-styleable>
+
+    <declare-styleable name="AlphaTintDrawableWrapper">
+        <attr name="android:tint" />
+        <attr name="android:drawable" />
+        <attr name="android:alpha" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index c51e0bf..9731d78 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,8 +35,7 @@
     <color name="status_bar_clock_color">#FFFFFFFF</color>
     <color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
     <color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
-    <color name="qs_customize_background">@color/GM2_grey_50</color>
-    <color name="qs_customize_decoration">@color/GM2_grey_100</color>
+    <color name="qs_customize_decoration">@color/GM2_grey_300</color>
 
     <!-- The color of the background in the separated list of the Global Actions menu -->
     <color name="global_actions_separated_background">#F5F5F5</color>
@@ -257,6 +256,8 @@
     <color name="control_enabled_heat_foreground">#FF8B66</color>
     <color name="control_enabled_default_foreground">@color/GM2_blue_300</color>
     <color name="control_enabled_cool_foreground">@color/GM2_blue_300</color>
+    <color name="control_thumbnail_tint">#33000000</color>
+    <color name="control_thumbnail_shadow_color">@*android:color/black</color>
 
     <!-- Docked misalignment message -->
     <color name="misalignment_text_color">#F28B82</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 880dd378..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>
@@ -570,4 +563,7 @@
     <bool name="config_showNotificationForUnknownBatteryState">false</bool>
     <!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false -->
     <string translatable="false" name="config_batteryStateUnknownUrl"></string>
+
+    <!-- Whether wallet view is shown in landscape / seascape orientations -->
+    <bool name="global_actions_show_landscape_wallet_view">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 57e1d43..6f69483 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -176,8 +176,8 @@
     <!-- Minimum height of a notification to be interactable -->
     <dimen name="notification_min_interaction_height">40dp</dimen>
 
-    <!-- New radius for notifications. -->
-    <dimen name="notification_corner_radius">20dp</dimen>
+    <!-- Radius for notifications corners without adjacent notifications -->
+    <dimen name="notification_corner_radius">28dp</dimen>
 
     <!-- the padding of the shelf icon container -->
     <dimen name="shelf_icon_container_padding">13dp</dimen>
@@ -677,6 +677,8 @@
     <dimen name="keyguard_clock_top_margin">36dp</dimen>
     <!-- The margin between top of clock and bottom of lock icon. -->
     <dimen name="keyguard_clock_lock_margin">16dp</dimen>
+    <!-- The amount to shift the clocks during a small/large transition -->
+    <dimen name="keyguard_clock_switch_y_shift">10dp</dimen>
 
     <item name="scrim_behind_alpha" format="float" type="dimen">0.62</item>
 
@@ -1005,6 +1007,7 @@
     <dimen name="global_actions_grid_vertical_padding">3dp</dimen>
     <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
 
+    <dimen name="global_actions_grid_item_layout_height">98dp</dimen>
     <dimen name="global_actions_grid_item_side_margin">5dp</dimen>
     <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen>
     <dimen name="global_actions_grid_item_width">64dp</dimen>
@@ -1194,8 +1197,8 @@
     <dimen name="magnification_frame_move_long">25dp</dimen>
     <dimen name="magnification_drag_view_size">38dp</dimen>
     <dimen name="magnification_controls_size">90dp</dimen>
-    <dimen name="magnification_switch_button_size">32dp</dimen>
-    <dimen name="magnification_switch_button_padding">8dp</dimen>
+    <dimen name="magnification_switch_button_size">60dp</dimen>
+    <dimen name="magnification_switch_button_padding">12dp</dimen>
     <dimen name="magnifier_left_right_controls_width">35dp</dimen>
     <dimen name="magnifier_left_right_controls_height">45dp</dimen>
     <dimen name="magnifier_up_down_controls_width">45dp</dimen>
@@ -1269,6 +1272,10 @@
     <dimen name="controls_app_divider_height">2dp</dimen>
     <dimen name="controls_app_divider_side_margin">32dp</dimen>
 
+    <item name="controls_thumbnail_shadow_x" type="dimen" format="float">2.0</item>
+    <item name="controls_thumbnail_shadow_y" type="dimen" format="float">2.0</item>
+    <item name="controls_thumbnail_shadow_radius" type="dimen" format="float">2.0</item>
+
     <dimen name="controls_card_margin">@dimen/control_base_item_margin</dimen>
     <item name="control_card_elevation" type="dimen" format="float">15</item>
 
@@ -1303,6 +1310,7 @@
     <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
     <dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
 
-    <dimen name="people_space_widget_radius">10dp</dimen>
+    <dimen name="people_space_widget_radius">24dp</dimen>
+    <dimen name="people_space_widget_round_radius">100dp</dimen>
     <dimen name="people_space_widget_background_padding">6dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5b74687..0687d06 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -231,7 +231,7 @@
     <!-- Notification text displayed when we fail to save a screenshot for unknown reasons. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_save_unknown_text">Try taking screenshot again</string>
     <!-- Notification text displayed when we fail to save a screenshot. [CHAR LIMIT=100] -->
-    <string name="screenshot_failed_to_save_text">Can\'t save screenshot due to limited storage space</string>
+    <string name="screenshot_failed_to_save_text">Can\'t save screenshot</string>
     <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_capture_text">Taking screenshots isn\'t allowed by the app or
         your organization</string>
@@ -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] -->
@@ -2824,13 +2764,23 @@
     <string name="build_number_copy_toast">Build number copied to clipboard.</string>
 
     <!-- Status for last interaction with exact time [CHAR LIMIT=120] -->
-    <string name="last_interaction_status" translatable="false">You last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status" translatable="false">Last chatted <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
     <!-- Status for last interaction when less than a certain time window [CHAR LIMIT=120] -->
-    <string name="last_interaction_status_less_than" translatable="false">You last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status_less_than" translatable="false">Last chatted less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
     <!-- Status for last interaction when over a certain time window [CHAR LIMIT=120] -->
-    <string name="last_interaction_status_over" translatable="false">You last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
+    <string name="last_interaction_status_over" translatable="false">Last chatted over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
     <!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
     <string name="basic_status" translatable="false">Open conversation</string>
+    <!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
+    <string name="select_conversation_text" translatable="false">Select one conversation to show in your widget:</string>
+    <!-- Timestamp for notification with exact time [CHAR LIMIT=120] -->
+    <string name="timestamp" translatable="false"><xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <!-- Timestamp for notification when less than a certain time window [CHAR LIMIT=120] -->
+    <string name="less_than_timestamp" translatable="false">Less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+    <!-- Timestamp for notification when over a certain time window [CHAR LIMIT=120] -->
+    <string name="over_timestamp" translatable="false">Over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
+    <!-- Status text for a birthday today [CHAR LIMIT=120] -->
+    <string name="birthday_status" translatable="false">Today is their birthday!</string>
 
     <!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
     [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0697c5c..6c0635a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -489,7 +489,6 @@
 
     <style name="TextAppearance.NotificationInfo">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
-        <item name="android:textColor">@color/notification_primary_text_color</item>
     </style>
 
     <style name="TextAppearance.NotificationInfo.Secondary">
@@ -498,7 +497,6 @@
     </style>
 
     <style name="TextAppearance.NotificationInfo.Title">
-        <item name="android:textColor">@color/notification_primary_text_color</item>
         <item name="android:textStyle">bold</item>
     </style>
 
diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml
index f08c8c8..10e28c4 100644
--- a/packages/SystemUI/res/xml/people_space_widget_info.xml
+++ b/packages/SystemUI/res/xml/people_space_widget_info.xml
@@ -15,10 +15,11 @@
   -->
 
 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-    android:minWidth="72dp"
-    android:minHeight="150dp"
+    android:minWidth="180dp"
+    android:minHeight="40dp"
     android:updatePeriodMillis="60000"
-    android:previewImage="@drawable/cloud"
+    android:previewImage="@drawable/ic_android"
     android:resizeMode="horizontal|vertical"
+    android:configure="com.android.systemui.people.PeopleSpaceActivity"
     android:initialLayout="@layout/people_space_widget">
 </appwidget-provider>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index d8fa90a..7dc537c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -22,7 +22,7 @@
 
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Point;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java
index b79fcbd..325bcfc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java
@@ -81,6 +81,7 @@
         HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER);
         ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE);
 
-        return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), colorSpace);
+        return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer),
+                colorSpace.getColorSpace());
     }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 229d20b..e5c4bf3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -27,7 +27,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.RecentTaskInfo;
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
@@ -122,7 +122,7 @@
      * @return the task snapshot for the given {@param taskId}.
      */
     public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
-        ActivityManager.TaskSnapshot snapshot = null;
+        TaskSnapshot snapshot = null;
         try {
             snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
         } catch (RemoteException e) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 611c4b7..af7c5da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.shared.system;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
@@ -137,4 +137,15 @@
             return false;
         }
     }
+
+    /**
+     * @see IRecentsAnimationController#detachNavigationBarFromApp
+     */
+    public void detachNavigationBarFromApp() {
+        try {
+            mAnimationController.detachNavigationBarFromApp();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to detach the navigation bar from app", e);
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 065d084..a907e66 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -17,8 +17,8 @@
 package com.android.systemui.shared.system;
 
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityTaskManager;
+import android.window.TaskSnapshot;
 import android.app.TaskStackListener;
 import android.content.ComponentName;
 import android.os.Handler;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
index bf88a29..ffd8a08 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
@@ -23,6 +23,7 @@
  */
 public class ThreadedRendererCompat {
 
+    public static int EGL_CONTEXT_PRIORITY_REALTIME_NV = 0x3357;
     public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
     public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
     public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index ab7ba8a..323449a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,6 +1,8 @@
 package com.android.keyguard;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Paint;
@@ -48,6 +50,9 @@
      */
     private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
 
+    private static final long CLOCK_OUT_MILLIS = 150;
+    private static final long CLOCK_IN_MILLIS = 200;
+
     /**
      * Layout transition that scales the default clock face.
      */
@@ -112,6 +117,7 @@
     private int[] mColorPalette;
 
     private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+    private int mClockSwitchYAmount;
 
     public KeyguardClockSwitch(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -131,6 +137,17 @@
     }
 
     /**
+     * Apply dp changes on font/scale change
+     */
+    public void onDensityOrFontScaleChanged() {
+        setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
+                .getDimensionPixelSize(R.dimen.widget_big_font_size));
+
+        mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
+                R.dimen.keyguard_clock_switch_y_shift);
+    }
+
+    /**
      * Returns if this view is presenting a custom clock, or the default implementation.
      */
     public boolean hasCustomClock() {
@@ -181,6 +198,8 @@
         mNewLockscreenLargeClockFrame = findViewById(R.id.new_lockscreen_clock_view_large);
         mSmallClockFrame = findViewById(R.id.clock_view);
         mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
+
+        onDensityOrFontScaleChanged();
     }
 
     void setClockPlugin(ClockPlugin plugin, int statusBarState) {
@@ -296,31 +315,43 @@
         mClockViewBold.setFormat24Hour(format);
     }
 
-    private void updateClockLayout(boolean useLargeClock) {
+    private void animateClockChange(boolean useLargeClock) {
         if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) return;
 
-        Fade fadeIn = new Fade();
-        fadeIn.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION);
-        fadeIn.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-
-        Fade fadeOut = new Fade();
-        fadeOut.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2);
-        fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-
+        View in, out;
+        int direction = 1;
         if (useLargeClock) {
-            TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeOut);
-            TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeIn);
-
-            mNewLockscreenClockFrame.setVisibility(View.INVISIBLE);
-            addView(mNewLockscreenLargeClockFrame);
-            mNewLockscreenLargeClockFrame.setVisibility(View.VISIBLE);
+            out = mNewLockscreenClockFrame;
+            in = mNewLockscreenLargeClockFrame;
+            addView(in);
+            direction = -1;
         } else {
-            TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeIn);
-            TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeOut);
+            in = mNewLockscreenClockFrame;
+            out = mNewLockscreenLargeClockFrame;
 
-            removeView(mNewLockscreenLargeClockFrame);
-            mNewLockscreenClockFrame.setVisibility(View.VISIBLE);
+            // Must remove in order for notifications to appear in the proper place
+            removeView(out);
         }
+
+        AnimatorSet outAnim = new AnimatorSet();
+        outAnim.setDuration(CLOCK_OUT_MILLIS);
+        outAnim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+        outAnim.playTogether(
+                ObjectAnimator.ofFloat(out, View.ALPHA, 0f),
+                ObjectAnimator.ofFloat(out, View.TRANSLATION_Y, 0,
+                        direction * -mClockSwitchYAmount));
+
+        in.setAlpha(0);
+        in.setVisibility(View.VISIBLE);
+        AnimatorSet inAnim = new AnimatorSet();
+        inAnim.setDuration(CLOCK_IN_MILLIS);
+        inAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        inAnim.playTogether(ObjectAnimator.ofFloat(in, View.ALPHA, 1f),
+                ObjectAnimator.ofFloat(in, View.TRANSLATION_Y, direction * mClockSwitchYAmount, 0));
+        inAnim.setStartDelay(CLOCK_OUT_MILLIS / 2);
+
+        inAnim.start();
+        outAnim.start();
     }
 
     /**
@@ -343,7 +374,8 @@
         if (hasVisibleNotifications == mHasVisibleNotifications) {
             return;
         }
-        updateClockLayout(!hasVisibleNotifications);
+
+        animateClockChange(!hasVisibleNotifications);
 
         mHasVisibleNotifications = hasVisibleNotifications;
         if (mDarkAmount == 0f && mBigClockContainer != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 4d6e8a9..e0de180 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -21,7 +21,6 @@
 import android.content.res.Resources;
 import android.provider.Settings;
 import android.text.format.DateFormat;
-import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -146,11 +145,10 @@
     }
 
     /**
-     * Updates clock's text
+     * Apply dp changes on font/scale change
      */
     public void onDensityOrFontScaleChanged() {
-        mView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                mResources.getDimensionPixelSize(R.dimen.widget_big_font_size));
+        mView.onDensityOrFontScaleChanged();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index bf42a60..036fcf3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -33,14 +33,15 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.util.TimingsTraceLog;
+import android.view.SurfaceControl;
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.systemui.dagger.ContextComponentHelper;
 import com.android.systemui.dagger.GlobalRootComponent;
 import com.android.systemui.dagger.SysUIComponent;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
+import com.android.systemui.shared.system.ThreadedRendererCompat;
 import com.android.systemui.util.NotificationChannels;
 
 import java.lang.reflect.Constructor;
@@ -98,6 +99,18 @@
         if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
             IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
             bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+
+            // If SF GPU context priority is set to realtime, then SysUI should run at high.
+            // The priority is defaulted at medium.
+            int sfPriority = SurfaceControl.getGPUContextPriority();
+            Log.i(TAG, "Found SurfaceFlinger's GPU Priority: " + sfPriority);
+            if (sfPriority == ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_REALTIME_NV) {
+                Log.i(TAG, "Setting SysUI's GPU Context priority to: "
+                        + ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+                ThreadedRendererCompat.setContextPriority(
+                        ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+            }
+
             registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
@@ -112,26 +125,12 @@
                             mServices[i].onBootCompleted();
                         }
                     }
-                    // If flag SHOW_PEOPLE_SPACE is true, enable People Space launcher icon.
-                    // TODO(b/170396074): Remove this when we don't need an icon anymore.
-                    try {
-                        int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
-                                Settings.Global.SHOW_PEOPLE_SPACE, 0);
-                        context.getPackageManager().setComponentEnabledSetting(
-                                new ComponentName(context, PeopleSpaceActivity.class),
-                                showPeopleSpace == 1
-                                        ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                                PackageManager.DONT_KILL_APP);
-                    } catch (Exception e) {
-                        Log.w(TAG, "Error enabling People Space launch icon:", e);
-                    }
 
                     // If SHOW_PEOPLE_SPACE is true, enable People Space widget provider.
                     // TODO(b/170396074): Remove this when we don't need a widget anymore.
                     try {
                         int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
-                                Settings.Global.SHOW_PEOPLE_SPACE, 0);
+                                Settings.Global.SHOW_PEOPLE_SPACE, 1);
                         context.getPackageManager().setComponentEnabledSetting(
                                 new ComponentName(context, PeopleSpaceWidgetProvider.class),
                                 showPeopleSpace == 1
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/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index e40185c..edc3216 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -23,6 +23,7 @@
 import android.content.pm.ActivityInfo;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -41,6 +42,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 
+import java.util.Collections;
+
 /**
  * Shows/hides a {@link android.widget.ImageView} on the screen and changes the values of
  * {@link Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE} when the UI is toggled.
@@ -52,7 +55,7 @@
     @VisibleForTesting
     static final long FADING_ANIMATION_DURATION_MS = 300;
     @VisibleForTesting
-    static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
+    static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 5000;
     private int mUiTimeout;
     private final Runnable mFadeInAnimationTask;
     private final Runnable mFadeOutAnimationTask;
@@ -85,7 +88,6 @@
         mImageView = imageView;
         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
         applyResourcesValues();
-        mImageView.setImageResource(getIconResId(mMagnificationMode));
         mImageView.setOnTouchListener(this::onTouch);
         mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
             @Override
@@ -138,6 +140,7 @@
         final int padding = mContext.getResources().getDimensionPixelSize(
                 R.dimen.magnification_switch_button_padding);
         mImageView.setPadding(padding, padding, padding, padding);
+        mImageView.setImageResource(getIconResId(mMagnificationMode));
     }
 
     private boolean onTouch(View v, MotionEvent event) {
@@ -146,7 +149,7 @@
         }
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
-                mImageView.animate().cancel();
+                stopFadeOutAnimation();
                 mLastDown.set(event.getRawX(), event.getRawY());
                 mLastDrag.set(event.getRawX(), event.getRawY());
                 return true;
@@ -205,6 +208,8 @@
         }
         if (!mIsVisible) {
             mWindowManager.addView(mImageView, mParams);
+            // Exclude magnification switch button from system gesture area.
+            setSystemGestureExclusion();
             mIsVisible = true;
             mImageView.postOnAnimation(mFadeInAnimationTask);
             mUiTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(
@@ -212,19 +217,28 @@
                     AccessibilityManager.FLAG_CONTENT_ICONS
                             | AccessibilityManager.FLAG_CONTENT_CONTROLS);
         }
+        // Refresh the time slot of the fade-out task whenever this method is called.
+        stopFadeOutAnimation();
+        mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout);
+    }
+
+    private void stopFadeOutAnimation() {
+        mImageView.removeCallbacks(mFadeOutAnimationTask);
         if (mIsFadeOutAnimating) {
             mImageView.animate().cancel();
             mImageView.setAlpha(1f);
+            mIsFadeOutAnimating = false;
         }
-        // Refresh the time slot of the fade-out task whenever this method is called.
-        mImageView.removeCallbacks(mFadeOutAnimationTask);
-        mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout);
     }
 
     void onConfigurationChanged(int configDiff) {
         if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
             applyResourcesValues();
-            mImageView.setImageResource(getIconResId(mMagnificationMode));
+            if (mIsVisible) {
+                mWindowManager.updateViewLayout(mImageView, mParams);
+                // Exclude magnification switch button from system gesture area.
+                setSystemGestureExclusion();
+            }
             return;
         }
         if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
@@ -261,7 +275,6 @@
         ImageView imageView = new ImageView(context);
         imageView.setClickable(true);
         imageView.setFocusable(true);
-        imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
         imageView.setAlpha(0f);
         return imageView;
     }
@@ -288,4 +301,13 @@
     private static String getAccessibilityWindowTitle(Context context) {
         return context.getString(com.android.internal.R.string.android_system_label);
     }
+
+    private void setSystemGestureExclusion() {
+        mImageView.post(() -> {
+            mImageView.setSystemGestureExclusionRects(
+                    Collections.singletonList(
+                            new Rect(0, 0, mImageView.getWidth(), mImageView.getHeight())));
+        });
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 0fd4765..c289ca2 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -438,7 +438,8 @@
     }
 
     @Override
-    public void onOpNoted(int code, int uid, String packageName, int result) {
+    public void onOpNoted(int code, int uid, String packageName,
+            @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
         if (DEBUG) {
             Log.w(TAG, "Noted op: " + code + " with result "
                     + AppOpsManager.MODE_NAMES[result] + " for package " + packageName);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 7bb8a84..a15a5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -91,7 +91,7 @@
     private final String mHbmDisableCommand;
     private final boolean mHbmSupported;
     // Brightness in nits in the high-brightness mode.
-    private final float mHbmNits;
+    private final float mMaxNits;
     // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to a
     // brightness in nits.
     private final Spline mBacklightToNitsSpline;
@@ -211,30 +211,51 @@
         // non-high-brightness mode.
         float[] nitsRange = toFloatArray(resources.obtainTypedArray(
                 com.android.internal.R.array.config_screenBrightnessNits));
+        if (nitsRange.length < 2) {
+            throw new IllegalArgumentException(
+                    String.format("nitsRange.length: %d. Must be >= 2", nitsRange.length));
+        }
 
         // The last value of this range corresponds to the high-brightness mode.
         float[] nitsAutoBrightnessValues = toFloatArray(resources.obtainTypedArray(
                 com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+        if (nitsAutoBrightnessValues.length < 2) {
+            throw new IllegalArgumentException(
+                    String.format("nitsAutoBrightnessValues.length: %d. Must be >= 2",
+                            nitsAutoBrightnessValues.length));
+        }
 
-        mHbmNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1];
-        float[] hbmNitsRange = {nitsRange[0], mHbmNits};
+        mMaxNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1];
+        float[] hbmNitsRange = nitsRange.clone();
+        hbmNitsRange[hbmNitsRange.length - 1] = mMaxNits;
 
         // This range only consists of the minimum and maximum backlight values, which only apply
         // in non-high-brightness mode.
         float[] normalizedBacklightRange = normalizeBacklightRange(
                 resources.getIntArray(
                         com.android.internal.R.array.config_screenBrightnessBacklight));
+        if (normalizedBacklightRange.length < 2) {
+            throw new IllegalArgumentException(
+                    String.format("normalizedBacklightRange.length: %d. Must be >= 2",
+                            normalizedBacklightRange.length));
+        }
+        if (normalizedBacklightRange.length != nitsRange.length) {
+            throw new IllegalArgumentException(
+                    "normalizedBacklightRange.length != nitsRange.length");
+        }
 
         mBacklightToNitsSpline = Spline.createSpline(normalizedBacklightRange, nitsRange);
         mNitsToHbmBacklightSpline = Spline.createSpline(hbmNitsRange, normalizedBacklightRange);
         mDefaultBrightness = obtainDefaultBrightness(powerManager);
 
         // TODO(b/160025856): move to the "dump" method.
-        Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0], nitsRange[1]));
+        Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0],
+                nitsRange[nitsRange.length - 1]));
         Log.v(TAG, String.format("ctor | mHbmNitsRange: [%f, %f]", hbmNitsRange[0],
-                hbmNitsRange[1]));
+                hbmNitsRange[hbmNitsRange.length - 1]));
         Log.v(TAG, String.format("ctor | mNormalizedBacklightRange: [%f, %f]",
-                normalizedBacklightRange[0], normalizedBacklightRange[1]));
+                normalizedBacklightRange[0],
+                normalizedBacklightRange[normalizedBacklightRange.length - 1]));
 
         mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
         mIsOverlayShowing = false;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e24a513..e78057f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -23,7 +23,6 @@
 import android.os.Build;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
-import android.view.MotionEvent;
 
 import androidx.annotation.NonNull;
 
@@ -33,10 +32,12 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.util.sensors.ThresholdSensor;
+import com.android.systemui.util.time.SystemClock;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Locale;
@@ -63,6 +64,8 @@
     private final DockManager mDockManager;
     private final SingleTapClassifier mSingleTapClassifier;
     private final DoubleTapClassifier mDoubleTapClassifier;
+    private final HistoryTracker mHistoryTracker;
+    private final SystemClock mSystemClock;
     private final boolean mTestHarness;
     private final MetricsLogger mMetricsLogger;
     private int mIsFalseTouchCalls;
@@ -85,6 +88,17 @@
         }
     };
 
+    private final FalsingDataProvider.GestureCompleteListener mGestureCompleteListener =
+            new FalsingDataProvider.GestureCompleteListener() {
+        @Override
+        public void onGestureComplete() {
+            mHistoryTracker.addResults(
+                    mClassifiers.stream().map(FalsingClassifier::classifyGesture)
+                            .collect(Collectors.toCollection(ArrayList::new)),
+                    mSystemClock.uptimeMillis());
+        }
+    };
+
     private boolean mPreviousResult = false;
 
     @Inject
@@ -92,6 +106,7 @@
             DockManager dockManager, MetricsLogger metricsLogger,
             @Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers,
             SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier,
+            HistoryTracker historyTracker, SystemClock systemClock,
             @TestHarness boolean testHarness) {
         mDataProvider = falsingDataProvider;
         mDockManager = dockManager;
@@ -99,9 +114,12 @@
         mClassifiers = classifiers;
         mSingleTapClassifier = singleTapClassifier;
         mDoubleTapClassifier = doubleTapClassifier;
+        mHistoryTracker = historyTracker;
+        mSystemClock = systemClock;
         mTestHarness = testHarness;
 
         mDataProvider.addSessionListener(mSessionListener);
+        mDataProvider.addGestureCompleteListener(mGestureCompleteListener);
     }
 
     @Override
@@ -119,21 +137,22 @@
         mPreviousResult = !mTestHarness
                 && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()
                 && mClassifiers.stream().anyMatch(falsingClassifier -> {
-                    boolean result = falsingClassifier.isFalseTouch();
-                    if (result) {
+                    FalsingClassifier.Result result = falsingClassifier.classifyGesture(
+                            mHistoryTracker.falsePenalty(), mHistoryTracker.falseConfidence());
+                    if (result.isFalse()) {
                         logInfo(String.format(
                                 (Locale) null,
                                 "{classifier=%s, interactionType=%d}",
                                 falsingClassifier.getClass().getName(),
                                 mDataProvider.getInteractionType()));
-                        String reason = falsingClassifier.getReason();
+                        String reason = result.getReason();
                         if (reason != null) {
                             logInfo(reason);
                         }
                     } else {
                         logDebug(falsingClassifier.getClass().getName() + ": false");
                     }
-                    return result;
+                    return result.isFalse();
                 });
 
         logDebug("Is false touch? " + mPreviousResult);
@@ -159,10 +178,12 @@
 
     @Override
     public boolean isFalseTap(boolean robustCheck) {
-        if (!mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents())) {
+        FalsingClassifier.Result singleTapResult =
+                mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents());
+        if (singleTapResult.isFalse()) {
             logInfo(String.format(
                     (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName()));
-            String reason = mSingleTapClassifier.getReason();
+            String reason = singleTapResult.getReason();
             if (reason != null) {
                 logInfo(reason);
             }
@@ -179,23 +200,16 @@
 
     @Override
     public boolean isFalseDoubleTap() {
-        boolean result = mDoubleTapClassifier.isFalseTouch();
-        if (result) {
+        FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture();
+        if (result.isFalse()) {
             logInfo(String.format(
                     (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName()));
-            String reason = mDoubleTapClassifier.getReason();
+            String reason = result.getReason();
             if (reason != null) {
                 logInfo(reason);
             }
         }
-        return result;
-    }
-
-    @Override
-    public void onTouchEvent(MotionEvent motionEvent, int width, int height) {
-        // TODO: some of these classifiers might allow us to abort early, meaning we don't have to
-        // make these calls.
-        mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent));
+        return result.isFalse();
     }
 
     @Override
@@ -271,6 +285,8 @@
     @Override
     public void cleanup() {
         mDataProvider.removeSessionListener(mSessionListener);
+        mDataProvider.removeGestureCompleteListener(mGestureCompleteListener);
+        mClassifiers.forEach(FalsingClassifier::cleanup);
     }
 
     static void logDebug(String msg) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
index 92dd8b7..bbb9371 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
@@ -62,17 +62,16 @@
                 VERTICAL_ANGLE_RANGE);
     }
 
-    @Override
-    boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         float angle = getAngle();
 
         if (angle == Float.MAX_VALUE) {  // Unknown angle
-            return false;
+            return Result.passed(0);
         }
 
         if (getInteractionType() == LEFT_AFFORDANCE
                 || getInteractionType() == RIGHT_AFFORDANCE) {
-            return false;
+            return Result.passed(0);
         }
 
         float minAngle = DIAGONAL - mHorizontalAngleRange;
@@ -82,15 +81,15 @@
             maxAngle = DIAGONAL + mVerticalAngleRange;
         }
 
-        return angleBetween(angle, minAngle, maxAngle)
+        boolean falsed = angleBetween(angle, minAngle, maxAngle)
                 || angleBetween(angle, minAngle + NINETY_DEG, maxAngle + NINETY_DEG)
                 || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG)
                 || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG,
                 maxAngle + ONE_HUNDRED_EIGHTY_DEG);
+        return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5);
     }
 
-    @Override
-    String getReason() {
+    private String getReason() {
         return String.format(
                 (Locale) null,
                 "{angle=%f, vertical=%s}",
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
index 50d55f6..4cb5aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
@@ -123,7 +123,6 @@
         }
 
         VelocityTracker velocityTracker = VelocityTracker.obtain();
-
         for (MotionEvent motionEvent : motionEvents) {
             velocityTracker.addMovement(motionEvent);
         }
@@ -148,11 +147,11 @@
     }
 
     @Override
-    public boolean isFalseTouch() {
-        return !getPassedFlingThreshold();
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+        return !getPassedFlingThreshold()
+                ? Result.falsed(0.5, getReason()) : Result.passed(0.5);
     }
 
-    @Override
     String getReason() {
         DistanceVectors distanceVectors = getDistances();
 
@@ -170,10 +169,10 @@
                 mVerticalSwipeThresholdPx);
     }
 
-    boolean isLongSwipe() {
+    Result isLongSwipe() {
         boolean longSwipe = getPassedDistanceThreshold();
         logDebug("Is longSwipe? " + longSwipe);
-        return longSwipe;
+        return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason());
     }
 
     private boolean getPassedDistanceThreshold() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
index 1c8f420..64576a9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
@@ -36,8 +36,6 @@
     private final float mDoubleTapSlop;
     private final long mDoubleTapTimeMs;
 
-    private StringBuilder mReason = new StringBuilder();
-
     @Inject
     DoubleTapClassifier(FalsingDataProvider dataProvider, SingleTapClassifier singleTapClassifier,
             @Named(DOUBLE_TAP_TOUCH_SLOP) float doubleTapSlop,
@@ -49,32 +47,34 @@
     }
 
     @Override
-    boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         List<MotionEvent> secondTapEvents = getRecentMotionEvents();
         Queue<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents();
         List<MotionEvent> firstTapEvents = historicalEvents.peek();
 
-        mReason = new StringBuilder();
+        StringBuilder reason = new StringBuilder();
 
         if (firstTapEvents == null) {
-            mReason.append("Only one gesture recorded");
-            return true;
+            return Result.falsed(1, "Only one gesture recorded");
         }
 
-        return !isDoubleTap(firstTapEvents, secondTapEvents, mReason);
+        return !isDoubleTap(firstTapEvents, secondTapEvents, reason)
+                ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5);
     }
 
     /** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */
     public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents,
             StringBuilder reason) {
 
-        if (!mSingleTapClassifier.isTap(firstEvents)) {
-            reason.append("First gesture is not a tap. ").append(mSingleTapClassifier.getReason());
+        Result firstTap = mSingleTapClassifier.isTap(firstEvents);
+        if (firstTap.isFalse()) {
+            reason.append("First gesture is not a tap. ").append(firstTap.getReason());
             return false;
         }
 
-        if (!mSingleTapClassifier.isTap(secondEvents)) {
-            reason.append("Second gesture is not a tap. ").append(mSingleTapClassifier.getReason());
+        Result secondTap = mSingleTapClassifier.isTap(secondEvents);
+        if (secondTap.isFalse()) {
+            reason.append("Second gesture is not a tap. ").append(secondTap.getReason());
             return false;
         }
 
@@ -106,9 +106,4 @@
 
         return true;
     }
-
-    @Override
-    String getReason() {
-        return mReason.toString();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
index 82575c3..dbfeacf 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
@@ -29,8 +29,11 @@
 public abstract class FalsingClassifier {
     private final FalsingDataProvider mDataProvider;
 
+    private final FalsingDataProvider.MotionEventListener mMotionEventListener = this::onTouchEvent;
+
     FalsingClassifier(FalsingDataProvider dataProvider) {
         mDataProvider = dataProvider;
+        mDataProvider.addMotionEventListener(mMotionEventListener);
     }
 
     List<MotionEvent> getRecentMotionEvents() {
@@ -89,6 +92,10 @@
         return mDataProvider.getInteractionType();
     }
 
+    void cleanup() {
+        mDataProvider.removeMotionEventListener(mMotionEventListener);
+    }
+
     /**
      * Called whenever a MotionEvent occurs.
      *
@@ -113,17 +120,32 @@
     void onSessionEnded() {};
 
     /**
-     * Returns true if the data captured so far looks like a false touch.
+     * Returns whether a gesture looks like a false touch.
+     *
+     * See also {@link #classifyGesture(double, double)}.
      */
-    abstract boolean isFalseTouch();
+    Result classifyGesture() {
+        return calculateFalsingResult(0, 0);
+    }
 
     /**
-     * Give the classifier a chance to log more details about why it triggered.
+     * Returns whether a gesture looks like a false touch, with the option to consider history.
      *
-     * This should only be called after a call to {@link #isFalseTouch()}, and only if
-     * {@link #isFalseTouch()} returns true;
+     * Unlike the parameter-less version of this method, this method allows the classifier to take
+     * history into account, penalizing or boosting confidence in a gesture based on recent results.
+     *
+     * See also {@link #classifyGesture()}.
      */
-    abstract String getReason();
+    Result classifyGesture(double historyPenalty, double historyConfidence) {
+        return calculateFalsingResult(historyPenalty, historyConfidence);
+    }
+
+    /**
+     * Calculate a result based on available data.
+     *
+     * When passed a historyConfidence of 0, the history penalty should be wholly ignored.
+     */
+    abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence);
 
     /** */
     public static void logDebug(String msg) {
@@ -139,4 +161,48 @@
     public static void logError(String msg) {
         BrightLineFalsingManager.logError(msg);
     }
+
+    /**
+     * A Falsing result that encapsulates the boolean result along with confidence and a reason.
+     */
+    static class Result {
+        private final boolean mFalsed;
+        private final double mConfidence;
+        private final String mReason;
+
+        /**
+         * See {@link #falsed(double, String)} abd {@link #passed(double)}.
+         */
+        private Result(boolean falsed, double confidence, String reason) {
+            mFalsed = falsed;
+            mConfidence = confidence;
+            mReason = reason;
+        }
+
+        public boolean isFalse() {
+            return mFalsed;
+        }
+
+        public double getConfidence() {
+            return mConfidence;
+        }
+
+        public String getReason() {
+            return mReason;
+        }
+
+        /**
+         * Construct a "falsed" result indicating that a gesture should be treated as accidental.
+         */
+        static Result falsed(double confidence, String reason) {
+            return new Result(true, confidence, reason);
+        }
+
+        /**
+         * Construct a "passed" result indicating that a gesture should be allowed.
+         */
+        static Result passed(double confidence) {
+            return new Result(false, confidence, null);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
index c05ce93..fe47162 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
@@ -113,7 +113,7 @@
     void onBouncerHidden();
 
     /** */
-    void onTouchEvent(MotionEvent ev, int width, int height);
+    void onTouchEvent(MotionEvent ev);
 
     /** */
     void cleanup();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
index a569111..fd05989 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
@@ -143,7 +143,7 @@
     }
 
     @Override
-    public void onTouchEvent(MotionEvent ev, int width, int height) {
+    public void onTouchEvent(MotionEvent ev) {
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 3547392..4c11ecf 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -244,9 +244,8 @@
     }
 
     @Override
-    public void onTouchEvent(MotionEvent ev, int width, int height) {
+    public void onTouchEvent(MotionEvent ev) {
         mFalsingDataProvider.onMotionEvent(ev);
-        mFalsingManager.onTouchEvent(ev, width, height);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 009b311..deb9e6d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -50,6 +50,8 @@
     private final float mXdpi;
     private final float mYdpi;
     private final List<SessionListener> mSessionListeners = new ArrayList<>();
+    private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>();
+    private final List<GestureCompleteListener> mGestuerCompleteListeners = new ArrayList<>();
 
     private @Classifier.InteractionType int mInteractionType;
     private final Deque<TimeLimitedMotionEventBuffer> mExtendedMotionEvents = new LinkedList<>();
@@ -97,6 +99,8 @@
 
         FalsingClassifier.logDebug("Size: " + mRecentMotionEvents.size());
 
+        mMotionEventListeners.forEach(listener -> listener.onMotionEvent(motionEvent));
+
         mDirty = true;
     }
 
@@ -321,6 +325,26 @@
         mSessionListeners.remove(listener);
     }
 
+    /** Register a {@link MotionEventListener}. */
+    public void addMotionEventListener(MotionEventListener listener) {
+        mMotionEventListeners.add(listener);
+    }
+
+    /** Unegister a {@link MotionEventListener}. */
+    public void removeMotionEventListener(MotionEventListener listener) {
+        mMotionEventListeners.remove(listener);
+    }
+
+    /** Register a {@link GestureCompleteListener}. */
+    public void addGestureCompleteListener(GestureCompleteListener listener) {
+        mGestuerCompleteListeners.add(listener);
+    }
+
+    /** Unregister a {@link GestureCompleteListener}. */
+    public void removeGestureCompleteListener(GestureCompleteListener listener) {
+        mGestuerCompleteListeners.remove(listener);
+    }
+
     void onSessionStarted() {
         mSessionListeners.forEach(SessionListener::onSessionStarted);
     }
@@ -353,4 +377,16 @@
         /** Called when the lock screen exits and falsing-tracking ends. */
         void onSessionEnded();
     }
+
+    /** Callback for receiving {@link android.view.MotionEvent}s as they are reported. */
+    public interface MotionEventListener {
+        /** */
+        void onMotionEvent(MotionEvent ev);
+    }
+
+    /** Callback to be alerted when the current gesture ends. */
+    public interface GestureCompleteListener {
+        /** */
+        void onGestureComplete();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index 32d27bc..d4d8d06 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -17,7 +17,6 @@
 package com.android.systemui.classifier;
 
 import android.net.Uri;
-import android.view.MotionEvent;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.plugins.FalsingManager;
@@ -117,11 +116,6 @@
     }
 
     @Override
-    public void onTouchEvent(MotionEvent ev, int width, int height) {
-
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index d4f58c3..cbec057 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.net.Uri;
 import android.provider.DeviceConfig;
-import android.view.MotionEvent;
 
 import androidx.annotation.NonNull;
 
@@ -162,11 +161,6 @@
     }
 
     @Override
-    public void onTouchEvent(MotionEvent ev, int width, int height) {
-        mInternalFalsingManager.onTouchEvent(ev, width, height);
-    }
-
-    @Override
     public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
         mInternalFalsingManager.onProximityEvent(proximityEvent);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java
new file mode 100644
index 0000000..8bd94a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java
@@ -0,0 +1,177 @@
+/*
+ * 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.classifier;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.util.time.SystemClock;
+
+import java.util.Collection;
+import java.util.concurrent.DelayQueue;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+/**
+ * A stateful class for tracking recent {@link FalsingManager} results.
+ *
+ * Can return a "penalty" based on recent gestures that may make it harder or easier to
+ * unlock a phone, as well as a "confidence" relating to how consistent recent falsing results
+ * have been.
+ */
+@SysUISingleton
+public class HistoryTracker {
+    private static final double HISTORY_DECAY = 0.8f;
+    private static final long DECAY_INTERVAL_MS = 100;
+    // We expire items once their decay factor is below 0.001.
+    private static final double MINIMUM_SCORE = 0.001;
+    private static final long TOTAL_DECAY_TIME_MS =
+            DECAY_INTERVAL_MS * (long) (Math.log(MINIMUM_SCORE) / Math.log(HISTORY_DECAY));
+    private final SystemClock mSystemClock;
+
+    DelayQueue<CombinedResult> mResults = new DelayQueue<>();
+
+    @Inject
+    HistoryTracker(SystemClock systemClock) {
+        mSystemClock = systemClock;
+    }
+
+    /**
+     * Returns how much the HistoryClassifier thinks the past events indicate pocket dialing.
+     *
+     * A result of 0 means that all prior gestures succeeded or there is no data to
+     * calculate a score with. Use {@link #falseConfidence()} to differentiate between the
+     * two cases.
+     *
+     * A result of 1 means that all prior gestures were very obviously false. The current gesture
+     * might be valid, but it should have a high-bar to be classified as such.
+     *
+     * See also {@link #falseConfidence()}.
+     */
+    double falsePenalty() {
+        //noinspection StatementWithEmptyBody
+        while (mResults.poll() != null) {
+            // Empty out the expired results.
+        }
+
+        if (mResults.isEmpty()) {
+            return 0;
+        }
+
+        long nowMs = mSystemClock.uptimeMillis();
+        return mResults.stream()
+                .map(result -> result.getDecayedScore(nowMs))
+                .reduce(0.0, Double::sum) / mResults.size();
+    }
+
+    /**
+     * Returns how confident the HistoryClassifier is in its own score.
+     *
+     * A result of 0.0 means that there are no data to make a calculation with. The HistoryTracker's
+     * results have nothing to add and should not be considered.
+     *
+     * A result of 0.5 means that the data are not consistent with each other, sometimes falsing
+     * sometimes not.
+     *
+     * A result of 1 means that there are ample, fresh data to act upon that is all consistent
+     * with each other.
+     *
+     * See als {@link #falsePenalty()}.
+     */
+    double falseConfidence() {
+        //noinspection StatementWithEmptyBody
+        while (mResults.poll() != null) {
+            // Empty out the expired results.
+        }
+
+        // Our confidence is 1 - the population stddev. Smaller stddev == higher confidence.
+        if (mResults.isEmpty()) {
+            return 0;
+        }
+
+        double mean = mResults.stream()
+                .map(CombinedResult::getScore)
+                .reduce(0.0, Double::sum) / mResults.size();
+
+        double stddev = Math.sqrt(
+                mResults.stream()
+                        .map(result -> Math.pow(result.getScore() - mean, 2))
+                        .reduce(0.0, Double::sum) / mResults.size());
+
+        return 1 - stddev;
+    }
+
+    void addResults(Collection<FalsingClassifier.Result> results, long uptimeMillis) {
+        double finalScore = 0;
+        for (FalsingClassifier.Result result : results) {
+            // A confidence of 1 adds either 0 for non-falsed or 1 for falsed.
+            // A confidence of 0 adds 0.5.
+            finalScore += (result.isFalse() ? .5 : -.5) * result.getConfidence() + 0.5;
+        }
+
+        finalScore /= results.size();
+
+        //noinspection StatementWithEmptyBody
+        while (mResults.poll() != null) {
+            // Empty out the expired results.
+        }
+
+        mResults.add(new CombinedResult(uptimeMillis, finalScore));
+    }
+
+    /**
+     * Represents a falsing score combing all the classifiers together.
+     *
+     * Can "decay" over time, such that older results contribute less. Once they drop below
+     * a certain threshold, the {@link #getDelay(TimeUnit)} method will return <= 0, indicating
+     * that this result can be discarded.
+     */
+    private class CombinedResult implements Delayed {
+
+        private final long mExpiryMs;
+        private final double mScore;
+
+        CombinedResult(long uptimeMillis, double score) {
+            mExpiryMs = uptimeMillis + TOTAL_DECAY_TIME_MS;
+            mScore = score;
+        }
+
+        double getDecayedScore(long nowMs) {
+            long remainingTimeMs = mExpiryMs - nowMs;
+            long decayedTimeMs = TOTAL_DECAY_TIME_MS - remainingTimeMs;
+            double timeIntervals = (double) decayedTimeMs / DECAY_INTERVAL_MS;
+            return mScore * Math.pow(HISTORY_DECAY, timeIntervals);
+        }
+
+        double getScore() {
+            return mScore;
+        }
+
+        @Override
+        public long getDelay(TimeUnit unit) {
+            return unit.convert(mExpiryMs - mSystemClock.uptimeMillis(), TimeUnit.MILLISECONDS);
+        }
+
+        @Override
+        public int compareTo(Delayed o) {
+            long ourDelay = getDelay(TimeUnit.MILLISECONDS);
+            long otherDelay = o.getDelay(TimeUnit.MILLISECONDS);
+            return Long.compare(ourDelay, otherDelay);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
index 0565165..cd399fe 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
@@ -56,20 +56,21 @@
     }
 
     @Override
-    public boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         int interactionType = getInteractionType();
-        if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) {
-            return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN;
-        }
-        return mMaxPointerCount > MAX_ALLOWED_POINTERS;
+        int allowedPointerCount =
+                (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN)
+                ? MAX_ALLOWED_POINTERS_SWIPE_DOWN : MAX_ALLOWED_POINTERS;
+
+        return mMaxPointerCount > allowedPointerCount
+                ? Result.falsed(1, getReason(allowedPointerCount)) : Result.passed(0);
     }
 
-    @Override
-    String getReason() {
+    private String getReason(int allowedPointerCount) {
         return String.format(
                 (Locale) null,
                 "{pointersObserved=%d, threshold=%d}",
                 mMaxPointerCount,
-                MAX_ALLOWED_POINTERS);
+                allowedPointerCount);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index 6e73fc0..9ee8598 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -33,7 +33,7 @@
 /**
  * False touch if proximity sensor is covered for more than a certain percentage of the gesture.
  *
- * This classifer is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be
+ * This classifier is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be
  * covered when swiping from the top.
  */
 class ProximityClassifier extends FalsingClassifier {
@@ -112,28 +112,29 @@
     }
 
     @Override
-    public boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         if (getInteractionType() == QUICK_SETTINGS) {
-            return false;
+            return Result.passed(0);
         }
 
         logInfo("Percent of gesture in proximity: " + mPercentNear);
 
         if (mPercentNear > mPercentCoveredThreshold) {
-            return !mDistanceClassifier.isLongSwipe();
+            Result longSwipeResult = mDistanceClassifier.isLongSwipe();
+            return longSwipeResult.isFalse()
+                    ? Result.falsed(0.5, getReason(longSwipeResult)) : Result.passed(0.5);
         }
 
-        return false;
+        return Result.passed(0.5);
     }
 
-    @Override
-    String getReason() {
+    private String getReason(Result longSwipeResult) {
         return String.format(
                 (Locale) null,
                 "{percentInProximity=%f, threshold=%f, distanceClassifier=%s}",
                 mPercentNear,
                 mPercentCoveredThreshold,
-                mDistanceClassifier.getReason());
+                longSwipeResult.getReason());
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
index 6b7a141..f2622ec 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
@@ -30,7 +30,6 @@
  */
 public class SingleTapClassifier extends FalsingClassifier {
     private final float mTouchSlop;
-    private String mReason;
 
     @Inject
     SingleTapClassifier(FalsingDataProvider dataProvider,
@@ -40,36 +39,31 @@
     }
 
     @Override
-    boolean isFalseTouch() {
-        return !isTap(getRecentMotionEvents());
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+        return isTap(getRecentMotionEvents());
     }
 
     /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */
-    public boolean isTap(List<MotionEvent> motionEvents) {
+    public Result isTap(List<MotionEvent> motionEvents) {
         float downX = motionEvents.get(0).getX();
         float downY = motionEvents.get(0).getY();
 
         for (MotionEvent event : motionEvents) {
+            String reason;
             if (Math.abs(event.getX() - downX) >= mTouchSlop) {
-                mReason = "dX too big for a tap: "
+                reason = "dX too big for a tap: "
                         + Math.abs(event.getX() - downX)
                         + "vs "
                         + mTouchSlop;
-                return false;
+                return Result.falsed(0.5, reason);
             } else if (Math.abs(event.getY() - downY) >= mTouchSlop) {
-                mReason = "dY too big for a tap: "
+                reason = "dY too big for a tap: "
                         + Math.abs(event.getY() - downY)
                         + "vs "
                         + mTouchSlop;
-                return false;
+                return Result.falsed(0.5, reason);
             }
         }
-        mReason = "";
-        return true;
-    }
-
-    @Override
-    String getReason() {
-        return mReason;
+        return Result.passed(0);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
index 711a0fc..d470d62 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
@@ -38,32 +38,40 @@
     }
 
     @Override
-    public boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         boolean vertical = isVertical();
         boolean up = isUp();
         boolean right = isRight();
 
+        boolean wrongDirection = true;
         switch (getInteractionType()) {
             case QUICK_SETTINGS:
             case PULSE_EXPAND:
             case NOTIFICATION_DRAG_DOWN:
-                return !vertical || up;
+                wrongDirection = !vertical || up;
+                break;
             case NOTIFICATION_DISMISS:
-                return vertical;
+                wrongDirection = vertical;
+                break;
             case UNLOCK:
             case BOUNCER_UNLOCK:
-                return !vertical || !up;
+                wrongDirection = !vertical || !up;
+                break;
             case LEFT_AFFORDANCE:  // Swiping from the bottom left corner for camera or similar.
-                return !right || !up;
+                wrongDirection = !right || !up;
+                break;
             case RIGHT_AFFORDANCE:  // Swiping from the bottom right corner for camera or similar.
-                return right || !up;
+                wrongDirection = right || !up;
+                break;
             default:
-                return true;
+                wrongDirection = true;
+                break;
         }
+
+        return wrongDirection ? Result.falsed(1, getReason()) : Result.passed(0.5);
     }
 
-    @Override
-    String getReason() {
+    private String getReason() {
         return String.format("{vertical=%s, up=%s, right=%s}", isVertical(), isUp(), isRight());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
index 383dda4..2bfb218 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
@@ -84,7 +84,7 @@
     }
 
     @Override
-    boolean isFalseTouch() {
+    Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
         List<MotionEvent> motionEvents = getRecentMotionEvents();
         // Rotate horizontal gestures to be horizontal between their first and last point.
         // Rotate vertical gestures to be vertical between their first and last point.
@@ -95,7 +95,7 @@
         // For vertical lines, the difference in the y direction should be small.
 
         if (motionEvents.size() < 3) {
-            return false;
+            return Result.passed(0);
         }
 
         List<Point> rotatedPoints;
@@ -155,11 +155,11 @@
 
         logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs "
                 + "(" + maxXDeviance + "," + maxYDeviance + ")");
-        return devianceX > maxXDeviance || devianceY > maxYDeviance;
+        return devianceX > maxXDeviance || devianceY > maxYDeviance
+            ? Result.falsed(0.5, getReason()) : Result.passed(0.5);
     }
 
-    @Override
-    String getReason() {
+    private String getReason() {
         return String.format(
                 (Locale) null,
                 "{devianceX=%f, maxDevianceX=%s, devianceY=%s, maxDevianceY=%s}",
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 0e4f684..9d92a40 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -37,6 +37,7 @@
 import android.service.controls.templates.RangeTemplate
 import android.service.controls.templates.StatelessTemplate
 import android.service.controls.templates.TemperatureControlTemplate
+import android.service.controls.templates.ThumbnailTemplate
 import android.service.controls.templates.ToggleRangeTemplate
 import android.service.controls.templates.ToggleTemplate
 import android.util.MathUtils
@@ -87,8 +88,11 @@
         ): KClass<out Behavior> {
             return when {
                 status != Control.STATUS_OK -> StatusBehavior::class
-                deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
                 template == ControlTemplate.NO_TEMPLATE -> TouchBehavior::class
+                template is ThumbnailTemplate -> ThumbnailBehavior::class
+
+                // Required for legacy support, or where cameras do not use the new template
+                deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
                 template is ToggleTemplate -> ToggleBehavior::class
                 template is StatelessTemplate -> TouchBehavior::class
                 template is ToggleRangeTemplate -> ToggleRangeBehavior::class
@@ -105,7 +109,7 @@
     private var statusAnimator: Animator? = null
     private val baseLayer: GradientDrawable
     val icon: ImageView = layout.requireViewById(R.id.icon)
-    private val status: TextView = layout.requireViewById(R.id.status)
+    val status: TextView = layout.requireViewById(R.id.status)
     private var nextStatusText: CharSequence = ""
     val title: TextView = layout.requireViewById(R.id.title)
     val subtitle: TextView = layout.requireViewById(R.id.subtitle)
@@ -132,7 +136,6 @@
         val ld = layout.getBackground() as LayerDrawable
         ld.mutate()
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
-        clipLayer.alpha = ALPHA_DISABLED
         baseLayer = ld.findDrawableByLayerId(R.id.background) as GradientDrawable
         // needed for marquee to start
         status.setSelected(true)
@@ -315,7 +318,9 @@
             )
         }
 
-        (clipLayer.getDrawable() as GradientDrawable).apply {
+        clipLayer.getDrawable().apply {
+            clipLayer.alpha = ALPHA_DISABLED
+
             val newBaseColor = if (behavior is ToggleRangeBehavior) {
                 ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity)
             } else {
@@ -323,15 +328,25 @@
             }
             stateAnimator?.cancel()
             if (animated) {
-                val oldColor = color?.defaultColor ?: newClipColor
+                val oldColor = if (this is GradientDrawable) {
+                    this.color?.defaultColor ?: newClipColor
+                } else {
+                    newClipColor
+                }
                 val oldBaseColor = baseLayer.color?.defaultColor ?: newBaseColor
                 val oldAlpha = layout.alpha
+
+                // Animate both alpha and background colors. Only animate colors for
+                // GradientDrawables and not static images as used for the ThumbnailTemplate.
                 stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply {
                     addUpdateListener {
                         alpha = it.animatedValue as Int
-                        setColor(ColorUtils.blendARGB(oldColor, newClipColor, it.animatedFraction))
-                        baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor,
-                                newBaseColor, it.animatedFraction))
+                        if (this is GradientDrawable) {
+                            this.setColor(ColorUtils.blendARGB(oldColor, newClipColor,
+                                it.animatedFraction))
+                        }
+                        baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, newBaseColor,
+                                it.animatedFraction))
                         layout.alpha = MathUtils.lerp(oldAlpha, 1f, it.animatedFraction)
                     }
                     addListener(object : AnimatorListenerAdapter() {
@@ -345,7 +360,9 @@
                 }
             } else {
                 alpha = newAlpha
-                setColor(newClipColor)
+                if (this is GradientDrawable) {
+                    this.setColor(newClipColor)
+                }
                 baseLayer.setColor(newBaseColor)
                 layout.alpha = 1f
             }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 3f17a4f..ad2b785 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -92,7 +92,9 @@
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to
         Pair(R.color.thermo_cool_foreground, R.color.control_enabled_thermo_cool_background),
     DeviceTypes.TYPE_LIGHT
-        to Pair(R.color.light_foreground, R.color.control_enabled_light_background)
+        to Pair(R.color.light_foreground, R.color.control_enabled_light_background),
+    DeviceTypes.TYPE_CAMERA
+        to Pair(R.color.camera_foreground, R.color.control_enabled_default_background)
 ).withDefault {
         Pair(R.color.control_foreground, R.color.control_enabled_default_background)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
new file mode 100644
index 0000000..c2168aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.graphics.BlendMode
+import android.graphics.BlendModeColorFilter
+import android.graphics.drawable.ClipDrawable
+import android.graphics.drawable.LayerDrawable
+import android.view.View
+import android.service.controls.Control
+import android.service.controls.templates.ThumbnailTemplate
+import android.util.TypedValue
+
+import com.android.systemui.R
+import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
+import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
+
+/**
+ * Supports display of static images on the background of the tile. When marked active, the title
+ * and subtitle will not be visible. To be used with {@link Thumbnailtemplate} only.
+ */
+class ThumbnailBehavior : Behavior {
+    lateinit var template: ThumbnailTemplate
+    lateinit var control: Control
+    lateinit var cvh: ControlViewHolder
+    private var shadowOffsetX: Float = 0f
+    private var shadowOffsetY: Float = 0f
+    private var shadowRadius: Float = 0f
+    private var shadowColor: Int = 0
+
+    private val enabled: Boolean
+        get() = template.isActive()
+
+    override fun initialize(cvh: ControlViewHolder) {
+        this.cvh = cvh
+
+        val outValue = TypedValue()
+        cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_x, outValue, true)
+        shadowOffsetX = outValue.getFloat()
+
+        cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_y, outValue, true)
+        shadowOffsetY = outValue.getFloat()
+
+        cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_radius, outValue, true)
+        shadowRadius = outValue.getFloat()
+
+        shadowColor = cvh.context.resources.getColor(R.color.control_thumbnail_shadow_color)
+        cvh.layout.setOnClickListener(View.OnClickListener() {
+            cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
+        })
+    }
+
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
+        this.control = cws.control!!
+        cvh.setStatusText(control.getStatusText())
+        template = control.getControlTemplate() as ThumbnailTemplate
+
+        val ld = cvh.layout.getBackground() as LayerDrawable
+        val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
+
+        clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL)
+
+        if (template.isActive()) {
+            cvh.title.visibility = View.INVISIBLE
+            cvh.subtitle.visibility = View.INVISIBLE
+            cvh.status.setShadowLayer(shadowOffsetX, shadowOffsetY, shadowRadius, shadowColor)
+
+            cvh.bgExecutor.execute {
+                val drawable = template.getThumbnail().loadDrawable(cvh.context)
+                cvh.uiExecutor.execute {
+                    val radius = cvh.context.getResources()
+                        .getDimensionPixelSize(R.dimen.control_corner_radius).toFloat()
+                    clipLayer.setDrawable(CornerDrawable(drawable, radius))
+                    clipLayer.setColorFilter(BlendModeColorFilter(cvh.context.resources
+                        .getColor(R.color.control_thumbnail_tint), BlendMode.LUMINOSITY))
+                    cvh.applyRenderInfo(enabled, colorOffset)
+                }
+            }
+        } else {
+            cvh.title.visibility = View.VISIBLE
+            cvh.subtitle.visibility = View.VISIBLE
+            cvh.status.setShadowLayer(0f, 0f, 0f, shadowColor)
+        }
+
+        cvh.applyRenderInfo(enabled, colorOffset)
+    }
+}
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/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index f470a6b..c26cc44 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -298,6 +298,22 @@
         mLogger.logDozeSuppressed(suppressedState);
     }
 
+    /**
+     * Appends new AOD sreen brightness to logs
+     * @param brightness display brightness setting
+     */
+    public void traceDozeScreenBrightness(int brightness) {
+        mLogger.logDozeScreenBrightness(brightness);
+    }
+
+    /**
+    * Appends new AOD dimming scrim opacity to logs
+    * @param scrimOpacity
+     */
+    public void traceSetAodDimmingScrim(float scrimOpacity) {
+        mLogger.logSetAodDimmingScrim((long) scrimOpacity);
+    }
+
     private class SummaryStats {
         private int mCount;
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index 0c9e143..fddefae 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -226,6 +226,22 @@
             "Doze state suppressed, state=$str1"
         })
     }
+
+    fun logDozeScreenBrightness(brightness: Int) {
+        buffer.log(TAG, INFO, {
+            int1 = brightness
+        }, {
+            "Doze screen brightness set, brightness=$int1"
+        })
+    }
+
+    fun logSetAodDimmingScrim(scrimOpacity: Long) {
+        buffer.log(TAG, INFO, {
+            long1 = scrimOpacity
+        }, {
+            "Doze aod dimming scrim opacity set, opacity=$long1"
+        })
+    }
 }
 
 private const val TAG = "DozeLog"
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index ebfce66..c542e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -34,6 +34,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.view.Display;
 
@@ -79,6 +80,7 @@
     private long mDebounceFrom;
     private boolean mSettingRegistered;
     private boolean mListening;
+    private boolean mListeningTouchScreenSensors;
 
     @VisibleForTesting
     public enum DozeSensorsUiEvent implements UiEventLogger.UiEventEnum {
@@ -232,22 +234,25 @@
     /**
      * If sensors should be registered and sending signals.
      */
-    public void setListening(boolean listen) {
-        if (mListening == listen) {
+    public void setListening(boolean listen, boolean includeTouchScreenSensors) {
+        if (mListening == listen && mListeningTouchScreenSensors == includeTouchScreenSensors) {
             return;
         }
         mListening = listen;
+        mListeningTouchScreenSensors = includeTouchScreenSensors;
         updateListening();
     }
 
     /**
      * Registers/unregisters sensors based on internal state.
      */
-    public void updateListening() {
+    private void updateListening() {
         boolean anyListening = false;
         for (TriggerSensor s : mSensors) {
-            s.setListening(mListening);
-            if (mListening) {
+            boolean listen = mListening
+                    && (!s.mRequiresTouchscreen || mListeningTouchScreenSensors);
+            s.setListening(listen);
+            if (listen) {
                 anyListening = true;
             }
         }
@@ -319,10 +324,14 @@
 
     /** Dump current state */
     public void dump(PrintWriter pw) {
+        pw.println("mListening=" + mListening);
+        pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors);
+        IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
+        idpw.increaseIndent();
         for (TriggerSensor s : mSensors) {
-            pw.println("  Sensor: " + s.toString());
+            idpw.println("Sensor: " + s.toString());
         }
-        pw.println("  ProxSensor: " + mProximitySensor.toString());
+        idpw.println("ProxSensor: " + mProximitySensor.toString());
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 6888d1ad..c617f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -29,6 +29,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.Formatter;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.view.Display;
 
@@ -434,15 +435,12 @@
                 break;
             case DOZE_PULSE_DONE:
                 mDozeSensors.requestTemporaryDisable();
-                // A pulse will temporarily disable sensors that require a touch screen.
-                // Let's make sure that they are re-enabled when the pulse is over.
-                mDozeSensors.updateListening();
                 break;
             case FINISH:
                 mBroadcastReceiver.unregister(mBroadcastDispatcher);
                 mDozeHost.removeCallback(mHostCallback);
                 mDockManager.removeListener(mDockEventListener);
-                mDozeSensors.setListening(false);
+                mDozeSensors.setListening(false, false);
                 mDozeSensors.setProxListening(false);
                 mWantSensors = false;
                 mWantProx = false;
@@ -450,20 +448,16 @@
                 break;
             default:
         }
+        mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors);
     }
 
     @Override
     public void onScreenState(int state) {
         mDozeSensors.onScreenState(state);
-        if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND
-                || state == Display.STATE_OFF) {
-            mDozeSensors.setProxListening(mWantProx);
-            mDozeSensors.setListening(mWantSensors);
-            mDozeSensors.setTouchscreenSensorsListening(mWantTouchScreenSensors);
-        } else {
-            mDozeSensors.setProxListening(false);
-            mDozeSensors.setListening(mWantSensors);
-        }
+        mDozeSensors.setProxListening(mWantProx && (state == Display.STATE_DOZE
+                || state == Display.STATE_DOZE_SUSPEND
+                || state == Display.STATE_OFF));
+        mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors);
     }
 
     private void checkTriggersAtInit() {
@@ -539,7 +533,9 @@
 
         pw.println(" pulsePending=" + mPulsePending);
         pw.println("DozeSensors:");
-        mDozeSensors.dump(pw);
+        IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
+        idpw.increaseIndent();
+        mDozeSensors.dump(idpw);
     }
 
     private class TriggerReceiver extends BroadcastReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 9c90510..ad4c447 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -50,6 +50,7 @@
 import android.content.SharedPreferences;
 import android.content.pm.UserInfo;
 import android.content.res.ColorStateList;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Color;
@@ -256,6 +257,7 @@
     private UserContextProvider mUserContextProvider;
     @VisibleForTesting
     boolean mShowLockScreenCardsAndControls = false;
+    private int mSmallestScreenWidthDp;
 
     @VisibleForTesting
     public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@@ -344,6 +346,7 @@
         mSysUiState = sysUiState;
         mMainHandler = handler;
         mUserContextProvider = userContextProvider;
+        mSmallestScreenWidthDp = mContext.getResources().getConfiguration().smallestScreenWidthDp;
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -760,6 +763,15 @@
         }
     }
 
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        if (mDialog != null && mDialog.isShowing()
+                && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) {
+            mSmallestScreenWidthDp = newConfig.smallestScreenWidthDp;
+            mDialog.refreshDialog();
+        }
+    }
+
     public void destroy() {
         mConfigurationController.removeCallback(this);
     }
@@ -2230,6 +2242,9 @@
                 return;
             }
 
+            boolean isLandscapeWalletViewShown = mContext.getResources().getBoolean(
+                    com.android.systemui.R.bool.global_actions_show_landscape_wallet_view);
+
             int rotation = RotationUtils.getRotation(mContext);
             boolean rotationLocked = RotationPolicy.isRotationLocked(mContext);
             if (rotation != RotationUtils.ROTATION_NONE) {
@@ -2246,6 +2261,10 @@
                     mGlobalActionsLayout.post(() ->
                             RotationPolicy.setRotationLockAtAngle(
                                     mContext, false, RotationUtils.ROTATION_NONE));
+
+                    if (!isLandscapeWalletViewShown) {
+                        return;
+                    }
                 }
             } else {
                 if (!rotationLocked) {
@@ -2253,44 +2272,48 @@
                         mResetOrientationData = new ResetOrientationData();
                         mResetOrientationData.locked = false;
                     }
+                }
 
-                    // Lock to portrait, so the user doesn't accidentally hide the panel.
+                boolean shouldLockRotation = !isLandscapeWalletViewShown;
+                if (rotationLocked != shouldLockRotation) {
+                    // Locks the screen to portrait if the landscape / seascape orientation does not
+                    // show the wallet view, so the user doesn't accidentally hide the panel.
                     // This call is posted so that the rotation does not change until post-layout,
                     // otherwise onConfigurationChanged() may not get invoked.
                     mGlobalActionsLayout.post(() ->
                             RotationPolicy.setRotationLockAtAngle(
-                                    mContext, true, RotationUtils.ROTATION_NONE));
+                            mContext, shouldLockRotation, RotationUtils.ROTATION_NONE));
                 }
+            }
 
-                // Disable rotation suggestions, if enabled
-                setRotationSuggestionsEnabled(false);
+            // Disable rotation suggestions, if enabled
+            setRotationSuggestionsEnabled(false);
 
-                FrameLayout panelContainer =
-                        findViewById(com.android.systemui.R.id.global_actions_wallet);
-                FrameLayout.LayoutParams panelParams =
-                        new FrameLayout.LayoutParams(
-                                FrameLayout.LayoutParams.MATCH_PARENT,
-                                FrameLayout.LayoutParams.MATCH_PARENT);
-                if (!mControlsAvailable) {
-                    panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
-                            com.android.systemui.R.dimen.global_actions_wallet_top_margin);
-                }
-                View walletView = mWalletViewController.getPanelContent();
-                panelContainer.addView(walletView, panelParams);
-                // Smooth transitions when wallet is resized, which can happen when a card is added
-                ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root);
-                if (root != null) {
-                    walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> {
-                        int oldHeight = ob - ot;
-                        int newHeight = b - t;
-                        if (oldHeight > 0 && oldHeight != newHeight) {
-                            TransitionSet transition = new AutoTransition()
-                                    .setDuration(250)
-                                    .setOrdering(TransitionSet.ORDERING_TOGETHER);
-                            TransitionManager.beginDelayedTransition(root, transition);
-                        }
-                    });
-                }
+            FrameLayout panelContainer =
+                    findViewById(com.android.systemui.R.id.global_actions_wallet);
+            FrameLayout.LayoutParams panelParams =
+                    new FrameLayout.LayoutParams(
+                            FrameLayout.LayoutParams.MATCH_PARENT,
+                            FrameLayout.LayoutParams.MATCH_PARENT);
+            if (!mControlsAvailable) {
+                panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
+                        com.android.systemui.R.dimen.global_actions_wallet_top_margin);
+            }
+            View walletView = mWalletViewController.getPanelContent();
+            panelContainer.addView(walletView, panelParams);
+            // Smooth transitions when wallet is resized, which can happen when a card is added
+            ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root);
+            if (root != null) {
+                walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> {
+                    int oldHeight = ob - ot;
+                    int newHeight = b - t;
+                    if (oldHeight > 0 && oldHeight != newHeight) {
+                        TransitionSet transition = new AutoTransition()
+                                .setDuration(250)
+                                .setOrdering(TransitionSet.ORDERING_TOGETHER);
+                        TransitionManager.beginDelayedTransition(root, transition);
+                    }
+                });
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index a330be6..ce5795c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -103,7 +103,7 @@
 
         d.setOnShowListener(dialog -> {
             if (mBlurUtils.supportsBlursOnWindows()) {
-                background.setAlpha((int) (ScrimController.BLUR_SCRIM_ALPHA * 255));
+                background.setAlpha((int) (ScrimController.BUSY_SCRIM_ALPHA * 255));
                 mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
                         mBlurUtils.blurRadiusOfRatio(1));
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 451bd42..4f85192 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Icon;
 import android.media.MediaMetadata;
 import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
 import android.media.RoutingSessionInfo;
 import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
@@ -37,6 +38,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.drawable.IconCompat;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.Utils;
 import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -75,6 +77,7 @@
     private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
     private final boolean mAboveStatusbar;
     private final NotificationEntryManager mNotificationEntryManager;
+    private final MediaRouter2Manager mRouterManager;
     @VisibleForTesting
     final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
 
@@ -84,11 +87,15 @@
     @VisibleForTesting
     LocalMediaManager mLocalMediaManager;
 
+    private MediaOutputMetricLogger mMetricLogger;
+    private UiEventLogger mUiEventLogger;
+
     @Inject
     public MediaOutputController(@NonNull Context context, String packageName,
             boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
             lbm, ShadeController shadeController, ActivityStarter starter,
-            NotificationEntryManager notificationEntryManager) {
+            NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger,
+            MediaRouter2Manager routerManager) {
         mContext = context;
         mPackageName = packageName;
         mMediaSessionManager = mediaSessionManager;
@@ -98,6 +105,9 @@
         mNotificationEntryManager = notificationEntryManager;
         InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
         mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
+        mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
+        mUiEventLogger = uiEventLogger;
+        mRouterManager = routerManager;
     }
 
     void start(@NonNull Callback cb) {
@@ -128,6 +138,9 @@
         mLocalMediaManager.stopScan();
         mLocalMediaManager.registerCallback(this);
         mLocalMediaManager.startScan();
+        if (mRouterManager != null) {
+            mRouterManager.startScan();
+        }
     }
 
     void stop() {
@@ -138,6 +151,9 @@
             mLocalMediaManager.unregisterCallback(this);
             mLocalMediaManager.stopScan();
         }
+        if (mRouterManager != null) {
+            mRouterManager.stopScan();
+        }
         mMediaDevices.clear();
     }
 
@@ -151,6 +167,7 @@
     public void onSelectedDeviceStateChanged(MediaDevice device,
             @LocalMediaManager.MediaDeviceState int state) {
         mCallback.onRouteChanged();
+        mMetricLogger.logOutputSuccess(device.toString(), mMediaDevices);
     }
 
     @Override
@@ -161,6 +178,7 @@
     @Override
     public void onRequestFailed(int reason) {
         mCallback.onRouteChanged();
+        mMetricLogger.logOutputFailure(mMediaDevices, reason);
     }
 
     CharSequence getHeaderTitle() {
@@ -311,6 +329,8 @@
     }
 
     void connectDevice(MediaDevice device) {
+        mMetricLogger.updateOutputEndPoints(getCurrentConnectedMediaDevice(), device);
+
         ThreadUtils.postOnBackgroundThread(() -> {
             mLocalMediaManager.connectDevice(device);
         });
@@ -439,7 +459,7 @@
 
     void launchMediaOutputDialog() {
         mCallback.dismissDialog();
-        new MediaOutputDialog(mContext, mAboveStatusbar, this);
+        new MediaOutputDialog(mContext, mAboveStatusbar, this, mUiEventLogger);
     }
 
     void launchMediaOutputGroupDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index a892a12..53029bd0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -23,6 +23,9 @@
 
 import androidx.core.graphics.drawable.IconCompat;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 
@@ -31,10 +34,12 @@
  */
 @SysUISingleton
 public class MediaOutputDialog extends MediaOutputBaseDialog {
+    final UiEventLogger mUiEventLogger;
 
     MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController
-            mediaOutputController) {
+            mediaOutputController, UiEventLogger uiEventLogger) {
         super(context, mediaOutputController);
+        mUiEventLogger = uiEventLogger;
         mAdapter = new MediaOutputAdapter(mMediaOutputController);
         if (!aboveStatusbar) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
@@ -45,6 +50,7 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW);
     }
 
     @Override
@@ -78,4 +84,21 @@
         return mMediaOutputController.isActiveRemoteDevice(
                 mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE;
     }
+
+    @VisibleForTesting
+    public enum MediaOutputEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "The MediaOutput dialog became visible on the screen.")
+        MEDIA_OUTPUT_DIALOG_SHOW(655);
+
+        private final int mId;
+
+        MediaOutputEvent(int id) {
+            mId = id;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 7d1a7ce..e1a504c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -18,6 +18,8 @@
 
 import android.content.Context
 import android.media.session.MediaSessionManager
+import android.media.MediaRouter2Manager
+import com.android.internal.logging.UiEventLogger
 import com.android.settingslib.bluetooth.LocalBluetoothManager
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.statusbar.notification.NotificationEntryManager
@@ -33,7 +35,9 @@
     private val lbm: LocalBluetoothManager?,
     private val shadeController: ShadeController,
     private val starter: ActivityStarter,
-    private val notificationEntryManager: NotificationEntryManager
+    private val notificationEntryManager: NotificationEntryManager,
+    private val uiEventLogger: UiEventLogger,
+    private val routerManager: MediaRouter2Manager
 ) {
     companion object {
         var mediaOutputDialog: MediaOutputDialog? = null
@@ -43,8 +47,10 @@
     fun create(packageName: String, aboveStatusBar: Boolean) {
         mediaOutputDialog?.dismiss()
         mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
-                mediaSessionManager, lbm, shadeController, starter, notificationEntryManager).run {
-            MediaOutputDialog(context, aboveStatusBar, this) }
+                mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
+                uiEventLogger, routerManager).run {
+            MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger)
+        }
     }
 
     /** dismiss [MediaOutputDialog] if exist. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
new file mode 100644
index 0000000..ac0295e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.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 com.android.systemui.media.dialog;
+
+import static android.media.MediaRoute2ProviderService.REASON_INVALID_COMMAND;
+import static android.media.MediaRoute2ProviderService.REASON_NETWORK_ERROR;
+import static android.media.MediaRoute2ProviderService.REASON_REJECTED;
+import static android.media.MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE;
+import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.util.Log;
+
+import com.android.settingslib.media.MediaDevice;
+import com.android.systemui.shared.system.SysUiStatsLog;
+
+import java.util.List;
+
+/**
+ * Metric logger for media output features
+ */
+public class MediaOutputMetricLogger {
+
+    private static final String TAG = "MediaOutputMetricLogger";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final Context mContext;
+    private final String mPackageName;
+    private MediaDevice mSourceDevice, mTargetDevice;
+    private int mWiredDeviceCount;
+    private int mConnectedBluetoothDeviceCount;
+    private int mRemoteDeviceCount;
+    private int mAppliedDeviceCountWithinRemoteGroup;
+
+    public MediaOutputMetricLogger(Context context, String packageName) {
+        mContext = context;
+        mPackageName = packageName;
+    }
+
+    /**
+     * Update the endpoints of a content switching operation.
+     * This method should be called before a switching operation, so the metric logger can track
+     * source and target devices.
+     * @param source the current connected media device
+     * @param target the target media device for content switching to
+     */
+    public void updateOutputEndPoints(MediaDevice source, MediaDevice target) {
+        mSourceDevice = source;
+        mTargetDevice = target;
+
+        if (DEBUG) {
+            Log.d(TAG, "updateOutputEndPoints -"
+                    + " source:" + mSourceDevice.toString()
+                    + " target:" + mTargetDevice.toString());
+        }
+    }
+
+    /**
+     * Do the metric logging of content switching success.
+     * @param selectedDeviceType string representation of the target media device
+     * @param deviceList media device list for device count updating
+     */
+    public void logOutputSuccess(String selectedDeviceType, List<MediaDevice> deviceList) {
+        if (DEBUG) {
+            Log.d(TAG, "logOutputSuccess - selected device: " + selectedDeviceType);
+        }
+
+        updateLoggingDeviceCount(deviceList);
+
+        SysUiStatsLog.write(
+                SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
+                getLoggingDeviceType(mSourceDevice, true),
+                getLoggingDeviceType(mTargetDevice, false),
+                SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__OK,
+                SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NO_ERROR,
+                getLoggingPackageName(),
+                mWiredDeviceCount,
+                mConnectedBluetoothDeviceCount,
+                mRemoteDeviceCount,
+                mAppliedDeviceCountWithinRemoteGroup);
+    }
+
+    /**
+     * Do the metric logging of content switching failure.
+     * @param deviceList media device list for device count updating
+     * @param reason the reason of content switching failure
+     */
+    public void logOutputFailure(List<MediaDevice> deviceList, int reason) {
+        if (DEBUG) {
+            Log.e(TAG, "logRequestFailed - " + reason);
+        }
+
+        updateLoggingDeviceCount(deviceList);
+
+        SysUiStatsLog.write(
+                SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
+                getLoggingDeviceType(mSourceDevice, true),
+                getLoggingDeviceType(mTargetDevice, false),
+                SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__ERROR,
+                getLoggingSwitchOpSubResult(reason),
+                getLoggingPackageName(),
+                mWiredDeviceCount,
+                mConnectedBluetoothDeviceCount,
+                mRemoteDeviceCount,
+                mAppliedDeviceCountWithinRemoteGroup);
+    }
+
+    private void updateLoggingDeviceCount(List<MediaDevice> deviceList) {
+        mWiredDeviceCount = mConnectedBluetoothDeviceCount = mRemoteDeviceCount = 0;
+        mAppliedDeviceCountWithinRemoteGroup = 0;
+
+        for (MediaDevice mediaDevice : deviceList) {
+            if (mediaDevice.isConnected()) {
+                switch (mediaDevice.getDeviceType()) {
+                    case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE:
+                    case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE:
+                        mWiredDeviceCount++;
+                        break;
+                    case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE:
+                        mConnectedBluetoothDeviceCount++;
+                        break;
+                    case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE:
+                    case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE:
+                        mRemoteDeviceCount++;
+                        break;
+                    default:
+                }
+            }
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, "connected devices:" + " wired: " + mWiredDeviceCount
+                    + " bluetooth: " + mConnectedBluetoothDeviceCount
+                    + " remote: " + mRemoteDeviceCount);
+        }
+    }
+
+    private int getLoggingDeviceType(MediaDevice device, boolean isSourceDevice) {
+        switch (device.getDeviceType()) {
+            case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BUILTIN_SPEAKER
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BUILTIN_SPEAKER;
+            case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog
+                        .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__WIRED_3POINT5_MM_AUDIO
+                        : SysUiStatsLog
+                                .MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__WIRED_3POINT5_MM_AUDIO;
+            case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__USB_C_AUDIO
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__USB_C_AUDIO;
+            case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BLUETOOTH
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BLUETOOTH;
+            case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_SINGLE
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_SINGLE;
+            case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_GROUP
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_GROUP;
+            default:
+                return isSourceDevice
+                        ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE
+                        : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__UNKNOWN_TYPE;
+        }
+    }
+
+    private int getLoggingSwitchOpSubResult(int reason) {
+        switch (reason) {
+            case REASON_REJECTED:
+                return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__REJECTED;
+            case REASON_NETWORK_ERROR:
+                return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NETWORK_ERROR;
+            case REASON_ROUTE_NOT_AVAILABLE:
+                return SysUiStatsLog
+                        .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__ROUTE_NOT_AVAILABLE;
+            case REASON_INVALID_COMMAND:
+                return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__INVALID_COMMAND;
+            case REASON_UNKNOWN_ERROR:
+            default:
+                return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__UNKNOWN_ERROR;
+        }
+    }
+
+    private String getLoggingPackageName() {
+        if (mPackageName != null && !mPackageName.isEmpty()) {
+            try {
+                final ApplicationInfo applicationInfo = mContext.getPackageManager()
+                        .getApplicationInfo(mPackageName, /* default flag */ 0);
+                if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
+                        || (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+                    return mPackageName;
+                }
+            } catch (Exception ex) {
+                Log.e(TAG, mPackageName + " is invalid.");
+            }
+        }
+
+        return "";
+    }
+}
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 5cd3b33..2ad12b9 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -16,22 +16,34 @@
 
 package com.android.systemui.people;
 
+import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
+import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID;
+
 import android.app.Activity;
 import android.app.INotificationManager;
 import android.app.people.IPeopleManager;
 import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.ViewGroup;
 
+import androidx.preference.PreferenceManager;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.systemui.R;
+import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * Shows the user their tiles for their priority People (go/live-status).
@@ -46,6 +58,10 @@
     private PackageManager mPackageManager;
     private LauncherApps mLauncherApps;
     private Context mContext;
+    private AppWidgetManager mAppWidgetManager;
+    private int mAppWidgetId;
+    private boolean mShowSingleConversation;
+    private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -59,7 +75,18 @@
         mPeopleManager = IPeopleManager.Stub.asInterface(
                 ServiceManager.getService(Context.PEOPLE_SERVICE));
         mLauncherApps = mContext.getSystemService(LauncherApps.class);
+        mAppWidgetManager = AppWidgetManager.getInstance(mContext);
         setTileViewsWithPriorityConversations();
+        mAppWidgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID,
+                INVALID_APPWIDGET_ID);
+        mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        // Finish the configuration activity immediately if a widget is added for multiple
+        // conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a
+        // widget configuration activity.
+        if (!mShowSingleConversation && mAppWidgetId != INVALID_APPWIDGET_ID) {
+            finishActivity();
+        }
     }
 
     /**
@@ -68,13 +95,12 @@
      */
     private void setTileViewsWithPriorityConversations() {
         try {
-            List<Map.Entry<Long, PeopleSpaceTile>> tiles = PeopleSpaceUtils.getTiles(
+            List<PeopleSpaceTile> tiles = PeopleSpaceUtils.getTiles(
                     mContext, mNotificationManager, mPeopleManager, mLauncherApps);
-            for (Map.Entry<Long, PeopleSpaceTile> entry : tiles) {
-                PeopleSpaceTile tile = entry.getValue();
+            for (PeopleSpaceTile tile : tiles) {
                 PeopleSpaceTileView tileView = new PeopleSpaceTileView(mContext, mPeopleSpaceLayout,
                         tile.getId());
-                setTileView(tileView, tile, entry.getKey());
+                setTileView(tileView, tile);
             }
         } catch (Exception e) {
             Log.e(TAG, "Couldn't retrieve conversations", e);
@@ -82,23 +108,56 @@
     }
 
     /** Sets {@code tileView} with the data in {@code conversation}. */
-    private void setTileView(PeopleSpaceTileView tileView, PeopleSpaceTile tile,
-            long lastInteraction) {
+    private void setTileView(PeopleSpaceTileView tileView, PeopleSpaceTile tile) {
         try {
             String pkg = tile.getPackageName();
             String status =
-                    PeopleSpaceUtils.getLastInteractionString(mContext, lastInteraction);
+                    PeopleSpaceUtils.getLastInteractionString(mContext,
+                            tile.getLastInteractionTimestamp(), true);
             tileView.setStatus(status);
 
             tileView.setName(tile.getUserName().toString());
             tileView.setPackageIcon(mPackageManager.getApplicationIcon(pkg));
             tileView.setPersonIcon(tile.getUserIcon());
-            tileView.setOnClickListener(mLauncherApps, tile);
+            tileView.setOnClickListener(v -> storeWidgetConfiguration(tile));
         } catch (Exception e) {
             Log.e(TAG, "Couldn't retrieve shortcut information", e);
         }
     }
 
+    /** Stores the user selected configuration for {@code mAppWidgetId}. */
+    private void storeWidgetConfiguration(PeopleSpaceTile tile) {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        SharedPreferences.Editor editor = sp.edit();
+        if (PeopleSpaceUtils.DEBUG) {
+            Log.d(TAG, "Put " + tile.getUserName() + "'s shortcut ID: "
+                    + tile.getId() + " for widget ID: "
+                    + mAppWidgetId);
+        }
+        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();
+    }
+
+    /** Finish activity with a successful widget configuration result. */
+    private void finishActivity() {
+        if (PeopleSpaceUtils.DEBUG) Log.d(TAG, "Widget added!");
+        mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
+        Intent resultValue = new Intent();
+        resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
+        setResult(RESULT_OK, resultValue);
+        finish();
+    }
+
     @Override
     protected void onResume() {
         super.onResume();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
index 4aea5b8..9ae7847 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceTileView.java
@@ -84,4 +84,9 @@
                 launcherApps.startShortcut(tile.getPackageName(), tile.getId(), null, null,
                         UserHandle.getUserHandleForUid(tile.getUid())));
     }
+
+    /** Sets the click listener of the tile directly. */
+    public void setOnClickListener(OnClickListener onClickListener) {
+        mTileView.setOnClickListener(onClickListener);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index fe262b4..f1a57bf 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -16,12 +16,21 @@
 
 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;
 import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.LauncherApps;
+import android.database.Cursor;
+import android.database.SQLException;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
@@ -29,17 +38,43 @@
 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.provider.ContactsContract;
 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.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.R;
+import com.android.systemui.people.widget.LaunchConversationActivity;
+import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 
+import java.text.SimpleDateFormat;
 import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -51,39 +86,344 @@
     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";
+
+    private static final Pattern DOUBLE_EXCLAMATION_PATTERN = Pattern.compile("[!][!]+");
+    private static final Pattern DOUBLE_QUESTION_PATTERN = Pattern.compile("[?][?]+");
+    private static final Pattern ANY_DOUBLE_MARK_PATTERN = Pattern.compile("[!?][!?]+");
+    private static final Pattern MIXED_MARK_PATTERN = Pattern.compile("![?].*|.*[?]!");
+
+    /** Represents whether {@link StatusBarNotification} was posted or removed. */
+    public enum NotificationAction {
+        POSTED,
+        REMOVED
+    }
+
+    /**
+     * The UiEvent enums that this class can log.
+     */
+    public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "People space widget deleted")
+        PEOPLE_SPACE_WIDGET_DELETED(666),
+        @UiEvent(doc = "People space widget added")
+        PEOPLE_SPACE_WIDGET_ADDED(667),
+        @UiEvent(doc = "People space widget clicked to launch conversation")
+        PEOPLE_SPACE_WIDGET_CLICKED(668);
+
+        private final int mId;
+
+        PeopleSpaceWidgetEvent(int id) {
+            mId = id;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
 
     /** Returns a list of map entries corresponding to user's conversations. */
-    public static List<Map.Entry<Long, PeopleSpaceTile>> getTiles(
+    public static List<PeopleSpaceTile> getTiles(
             Context context, INotificationManager notificationManager, IPeopleManager peopleManager,
             LauncherApps launcherApps)
             throws Exception {
-        boolean showAllConversations = Settings.Global.getInt(context.getContentResolver(),
-                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        boolean showOnlyPriority = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1;
         List<ConversationChannelWrapper> conversations = notificationManager.getConversations(
                 true).getList();
-        List<Map.Entry<Long, PeopleSpaceTile>> tiles = getSortedTiles(peopleManager,
-                conversations.stream().map(c ->
-                        new PeopleSpaceTile.Builder(c.getShortcutInfo(), launcherApps).build()));
-        if (showAllConversations) {
+        List<PeopleSpaceTile> tiles = getSortedTiles(peopleManager,
+                conversations.stream().filter(c -> c.getShortcutInfo() != null).map(
+                        c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
+                                launcherApps).build()));
+        if (!showOnlyPriority) {
+            if (DEBUG) Log.d(TAG, "Add recent conversations");
             List<ConversationChannel> recentConversations =
                     peopleManager.getRecentConversations().getList();
-            List<Map.Entry<Long, PeopleSpaceTile>> recentTiles =
-                    getSortedTiles(peopleManager, recentConversations.stream().map(c ->
-                            new PeopleSpaceTile
-                                    .Builder(c.getShortcutInfo(), launcherApps)
-                                    .build()));
+            List<PeopleSpaceTile> recentTiles =
+                    getSortedTiles(peopleManager,
+                            recentConversations
+                                    .stream()
+                                    .filter(
+                                            c -> c.getShortcutInfo() != null)
+                                    .map(
+                                            c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
+                                                    launcherApps).build()));
             tiles.addAll(recentTiles);
         }
         return tiles;
     }
 
+    /**
+     * Updates {@code appWidgetIds} with their associated conversation stored, handling a
+     * notification being posted or removed.
+     */
+    public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds,
+            AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
+        IPeopleManager peopleManager = IPeopleManager.Stub.asInterface(
+                ServiceManager.getService(Context.PEOPLE_SERVICE));
+        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+        Map<Integer, PeopleSpaceTile> widgetIdToTile = new HashMap<>();
+        try {
+            List<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, "Widget ID: " + appWidgetId + " Shortcut ID: " + shortcutId);
+                }
+
+                Optional<PeopleSpaceTile> entry = tiles.stream().filter(
+                        e -> e.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;
+                }
+                // Augment current tile based on stored fields.
+                PeopleSpaceTile tile = augmentTileFromStorage(entry.get(), appWidgetManager,
+                        appWidgetId);
+
+                RemoteViews views = createRemoteViews(context, tile, appWidgetId);
+
+                // Tell the AppWidgetManager to perform an update on the current app widget.
+                appWidgetManager.updateAppWidget(appWidgetId, views);
+
+                widgetIdToTile.put(appWidgetId, tile);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to retrieve conversations to set tiles: " + e);
+        }
+        getBirthdaysOnBackgroundThread(context, appWidgetManager, widgetIdToTile, appWidgetIds);
+    }
+
+    /** 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()
+                .setStatusText(storedTile.getStatusText())
+                .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();
+        }
+        updateAppWidgetOptions(appWidgetManager, appWidgetId, storedTile);
+    }
+
+    private static void updateAppWidgetOptions(AppWidgetManager appWidgetManager, int appWidgetId,
+            PeopleSpaceTile tile) {
+        Bundle newOptions = new Bundle();
+        newOptions.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, tile);
+        appWidgetManager.updateAppWidgetOptions(appWidgetId, newOptions);
+    }
+
+    /** Creates a {@link RemoteViews} for {@code tile}. */
+    private static RemoteViews createRemoteViews(Context context,
+            PeopleSpaceTile tile, int appWidgetId) {
+        RemoteViews views;
+        if (tile.getNotificationKey() != null) {
+            views = createNotificationRemoteViews(context, tile);
+        } else if (tile.getStatusText() != null) {
+            views = createStatusRemoteViews(context, tile);
+        } else {
+            views = createLastInteractionRemoteViews(context, tile);
+        }
+        return setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+    }
+
+    private static RemoteViews setCommonRemoteViewsFields(Context context, RemoteViews views,
+            PeopleSpaceTile tile, int appWidgetId) {
+        try {
+            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;
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to set common fields: " + e);
+        }
+        return null;
+    }
+
+    private static RemoteViews createNotificationRemoteViews(Context context,
+            PeopleSpaceTile tile) {
+        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 {
+            CharSequence content = tile.getNotificationContent();
+            views = setPunctuationRemoteViewsFields(views, content);
+            views.setTextViewText(R.id.content, content);
+            views.setViewVisibility(R.id.content, View.VISIBLE);
+            views.setViewVisibility(R.id.image, View.GONE);
+        }
+        views.setTextViewText(R.id.time, PeopleSpaceUtils.getLastInteractionString(
+                context, tile.getLastInteractionTimestamp(), false));
+        return views;
+    }
+
+    private static RemoteViews createStatusRemoteViews(Context context,
+            PeopleSpaceTile tile) {
+        RemoteViews views = new RemoteViews(
+                context.getPackageName(), R.layout.people_space_large_avatar_tile);
+        views.setTextViewText(R.id.status, tile.getStatusText());
+        return views;
+    }
+
+    private static RemoteViews createLastInteractionRemoteViews(Context context,
+            PeopleSpaceTile tile) {
+        RemoteViews views = new RemoteViews(
+                context.getPackageName(), R.layout.people_space_large_avatar_tile);
+        String status = PeopleSpaceUtils.getLastInteractionString(
+                context, tile.getLastInteractionTimestamp(), true);
+        views.setTextViewText(R.id.status, status);
+        return views;
+    }
+
+    private static RemoteViews setPunctuationRemoteViewsFields(
+            RemoteViews views, CharSequence content) {
+        String punctuation = getBackgroundTextFromMessage(content.toString());
+        int visibility = View.GONE;
+        if (punctuation != null) {
+            visibility = View.VISIBLE;
+        }
+        views.setTextViewText(R.id.punctuation1, punctuation);
+        views.setTextViewText(R.id.punctuation2, punctuation);
+        views.setTextViewText(R.id.punctuation3, punctuation);
+        views.setTextViewText(R.id.punctuation4, punctuation);
+        views.setTextViewText(R.id.punctuation5, punctuation);
+        views.setTextViewText(R.id.punctuation6, punctuation);
+
+        views.setViewVisibility(R.id.punctuation1, visibility);
+        views.setViewVisibility(R.id.punctuation2, visibility);
+        views.setViewVisibility(R.id.punctuation3, visibility);
+        views.setViewVisibility(R.id.punctuation4, visibility);
+        views.setViewVisibility(R.id.punctuation5, visibility);
+        views.setViewVisibility(R.id.punctuation6, visibility);
+
+        return views;
+    }
+
+    /** Gets character for tile background decoration based on notification content. */
+    @VisibleForTesting
+    static String getBackgroundTextFromMessage(String message) {
+        if (!ANY_DOUBLE_MARK_PATTERN.matcher(message).find()) {
+            return null;
+        }
+        if (MIXED_MARK_PATTERN.matcher(message).find()) {
+            return "!?";
+        }
+        Matcher doubleQuestionMatcher = DOUBLE_QUESTION_PATTERN.matcher(message);
+        if (!doubleQuestionMatcher.find()) {
+            return "!";
+        }
+        Matcher doubleExclamationMatcher = DOUBLE_EXCLAMATION_PATTERN.matcher(message);
+        if (!doubleExclamationMatcher.find()) {
+            return "?";
+        }
+        // If we have both "!!" and "??", return the one that comes first.
+        if (doubleQuestionMatcher.start() < doubleExclamationMatcher.start()) {
+            return "?";
+        }
+        return "!";
+    }
+
+    /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
+    @VisibleForTesting
+    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 a list sorted by ascending last interaction time from {@code stream}. */
-    private static List<Map.Entry<Long, PeopleSpaceTile>> getSortedTiles(
-            IPeopleManager peopleManager, Stream<PeopleSpaceTile> stream) {
+    private static List<PeopleSpaceTile> getSortedTiles(IPeopleManager peopleManager,
+            Stream<PeopleSpaceTile> stream) {
         return stream
                 .filter(c -> shouldKeepConversation(c))
-                .map(c -> Map.entry(getLastInteraction(peopleManager, c), c))
-                .sorted((c1, c2) -> (c2.getKey().compareTo(c1.getKey())))
+                .map(c -> c.toBuilder().setLastInteractionTimestamp(
+                        getLastInteraction(peopleManager, c)).build())
+                .sorted((c1, c2) -> new Long(c2.getLastInteractionTimestamp()).compareTo(
+                        new Long(c1.getLastInteractionTimestamp())))
                 .collect(Collectors.toList());
     }
 
@@ -129,7 +469,8 @@
     }
 
     /** Returns a readable status describing the {@code lastInteraction}. */
-    public static String getLastInteractionString(Context context, long lastInteraction) {
+    public static String getLastInteractionString(Context context, long lastInteraction,
+            boolean includeLastChatted) {
         if (lastInteraction == 0L) {
             Log.e(TAG, "Could not get valid last interaction");
             return context.getString(R.string.basic_status);
@@ -139,18 +480,25 @@
         MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
                 MeasureFormat.FormatWidth.WIDE);
         if (durationSinceLastInteraction.toHours() < MIN_HOUR) {
-            return context.getString(R.string.last_interaction_status_less_than,
+            return context.getString(includeLastChatted ? R.string.last_interaction_status_less_than
+                            : R.string.less_than_timestamp,
                     formatter.formatMeasures(new Measure(MIN_HOUR, MeasureUnit.HOUR)));
         } else if (durationSinceLastInteraction.toDays() < ONE_DAY) {
-            return context.getString(R.string.last_interaction_status, formatter.formatMeasures(
-                    new Measure(durationSinceLastInteraction.toHours(), MeasureUnit.HOUR)));
+            return context.getString(
+                    includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
+                    formatter.formatMeasures(
+                            new Measure(durationSinceLastInteraction.toHours(), MeasureUnit.HOUR)));
         } else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
-            return context.getString(R.string.last_interaction_status, formatter.formatMeasures(
-                    new Measure(durationSinceLastInteraction.toDays(), MeasureUnit.DAY)));
+            return context.getString(
+                    includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
+                    formatter.formatMeasures(
+                            new Measure(durationSinceLastInteraction.toDays(), MeasureUnit.DAY)));
         } else {
             return context.getString(durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK
-                            ? R.string.last_interaction_status :
-                            R.string.last_interaction_status_over,
+                            ? (includeLastChatted ? R.string.last_interaction_status :
+                            R.string.timestamp) :
+                            (includeLastChatted ? R.string.last_interaction_status_over
+                                    : R.string.over_timestamp),
                     formatter.formatMeasures(
                             new Measure(durationSinceLastInteraction.toDays() / DAYS_IN_A_WEEK,
                                     MeasureUnit.WEEK)));
@@ -171,4 +519,139 @@
         return tile != null && tile.getUserName().length() != 0;
     }
 
+    private static boolean hasBirthdayStatus(PeopleSpaceTile tile, Context context) {
+        return tile.getStatusText() != null && tile.getStatusText().equals(
+                context.getString(R.string.birthday_status));
+    }
+
+
+    /** Calls to retrieve birthdays on a background thread. */
+    private static void getBirthdaysOnBackgroundThread(Context context,
+            AppWidgetManager appWidgetManager,
+            Map<Integer, PeopleSpaceTile> peopleSpaceTiles, int[] appWidgetIds) {
+        ThreadUtils.postOnBackgroundThread(
+                () -> getBirthdays(context, appWidgetManager, peopleSpaceTiles, appWidgetIds));
+    }
+
+    /** Queries the Contacts DB for any birthdays today. */
+    @VisibleForTesting
+    public static void getBirthdays(Context context, AppWidgetManager appWidgetManager,
+            Map<Integer, PeopleSpaceTile> widgetIdToTile, int[] appWidgetIds) {
+        if (DEBUG) Log.d(TAG, "Get birthdays");
+        if (appWidgetIds.length == 0) return;
+        List<String> lookupKeysWithBirthdaysToday = getContactLookupKeysWithBirthdaysToday(context);
+        for (int appWidgetId : appWidgetIds) {
+            PeopleSpaceTile storedTile = widgetIdToTile.get(appWidgetId);
+            if (storedTile == null || storedTile.getContactUri() == null) {
+                if (DEBUG) Log.d(TAG, "No contact uri for: " + storedTile);
+                removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+                continue;
+            }
+            if (lookupKeysWithBirthdaysToday.isEmpty()) {
+                if (DEBUG) Log.d(TAG, "No birthdays today");
+                removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+                continue;
+            }
+            updateTileWithBirthday(context, appWidgetManager, lookupKeysWithBirthdaysToday,
+                    storedTile,
+                    appWidgetId);
+        }
+    }
+
+    /** Removes the birthday status if present in {@code storedTile} and pushes the update. */
+    private static void removeBirthdayStatusIfPresent(AppWidgetManager appWidgetManager,
+            Context context, PeopleSpaceTile storedTile, int appWidgetId) {
+        if (hasBirthdayStatus(storedTile, context)) {
+            if (DEBUG) Log.d(TAG, "Remove " + storedTile.getUserName() + "'s birthday");
+            updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
+                    storedTile.toBuilder()
+                            .setStatusText(null)
+                            .build());
+        }
+    }
+
+    /**
+     * Update {@code storedTile} if the contact has a lookup key matched to any {@code
+     * lookupKeysWithBirthdays}.
+     */
+    private static void updateTileWithBirthday(Context context, AppWidgetManager appWidgetManager,
+            List<String> lookupKeysWithBirthdaysToday, PeopleSpaceTile storedTile,
+            int appWidgetId) {
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(storedTile.getContactUri(),
+                    null, null, null, null);
+            while (cursor != null && cursor.moveToNext()) {
+                String storedLookupKey = cursor.getString(
+                        cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY));
+                if (!storedLookupKey.isEmpty() && lookupKeysWithBirthdaysToday.contains(
+                        storedLookupKey)) {
+                    if (DEBUG) Log.d(TAG, storedTile.getUserName() + "'s birthday today!");
+                    updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
+                            storedTile.toBuilder()
+                                    .setStatusText(context.getString(R.string.birthday_status))
+                                    .build());
+                    return;
+                }
+            }
+        } catch (SQLException e) {
+            Log.e(TAG, "Failed to query contact: " + e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+    }
+
+    /** Update app widget options and the current view. */
+    private static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
+            Context context, int appWidgetId, PeopleSpaceTile tile) {
+        updateAppWidgetOptions(appWidgetManager, appWidgetId, tile);
+        RemoteViews views = createRemoteViews(context,
+                tile, appWidgetId);
+        appWidgetManager.updateAppWidget(appWidgetId, views);
+    }
+
+    /**
+     * Returns lookup keys for all contacts with a birthday today.
+     *
+     * <p>Birthdays are queried from a different table within the Contacts DB than the table for
+     * the Contact Uri provided by most messaging apps. Matching by the contact ID is then quite
+     * fragile as the row IDs across the different tables are not guaranteed to stay aligned, so we
+     * match the data by {@link ContactsContract.ContactsColumns#LOOKUP_KEY} key to ensure proper
+     * matching across all the Contacts DB tables.
+     */
+    private static List<String> getContactLookupKeysWithBirthdaysToday(Context context) {
+        List<String> lookupKeysWithBirthdaysToday = new ArrayList<>(1);
+        String today = new SimpleDateFormat("MM-dd").format(new Date());
+        String[] projection = new String[]{
+                ContactsContract.CommonDataKinds.Event.LOOKUP_KEY,
+                ContactsContract.CommonDataKinds.Event.START_DATE};
+        String where =
+                ContactsContract.Data.MIMETYPE
+                        + "= ? AND " + ContactsContract.CommonDataKinds.Event.TYPE + "="
+                        + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY + " AND substr("
+                        + ContactsContract.CommonDataKinds.Event.START_DATE + ",6) = ?";
+        String[] selection =
+                new String[]{ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, today};
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
+                    projection, where, selection, null);
+            while (cursor != null && cursor.moveToNext()) {
+                String lookupKey = cursor.getString(
+                        cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY));
+                lookupKeysWithBirthdaysToday.add(lookupKey);
+            }
+        } catch (SQLException e) {
+            Log.e(TAG, "Failed to query birthdays: " + e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return lookupKeysWithBirthdaysToday;
+    }
 }
+
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
index 0b0308f..358f311 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
@@ -23,12 +23,15 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.systemui.people.PeopleSpaceUtils;
 
 /** Proxy activity to launch ShortcutInfo's conversation. */
 public class LaunchConversationActivity extends Activity {
     private static final String TAG = "PeopleSpaceLaunchConv";
     private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+    private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -44,6 +47,7 @@
             if (DEBUG) {
                 Log.d(TAG, "Launching conversation with shortcutInfo id " + tileId);
             }
+            mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_CLICKED);
             try {
                 LauncherApps launcherApps =
                         getApplicationContext().getSystemService(LauncherApps.class);
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 9b7cf6e..ad6046b 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -16,11 +16,16 @@
 
 package com.android.systemui.people.widget;
 
+import android.app.INotificationManager;
 import android.app.NotificationChannel;
+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;
 import android.util.Log;
@@ -32,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;
 
@@ -42,13 +49,18 @@
     private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
 
     private final Context mContext;
-    private IAppWidgetService mAppWidgetManager;
+    private IAppWidgetService mAppWidgetService;
+    private AppWidgetManager mAppWidgetManager;
+    private INotificationManager mNotificationManager;
 
     @Inject
     public PeopleSpaceWidgetManager(Context context, IAppWidgetService appWidgetService) {
         if (DEBUG) Log.d(TAG, "constructor");
         mContext = context;
-        mAppWidgetManager = appWidgetService;
+        mAppWidgetService = appWidgetService;
+        mAppWidgetManager = AppWidgetManager.getInstance(context);
+        mNotificationManager = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
     }
 
     /** Constructor used for testing. */
@@ -56,33 +68,78 @@
     protected PeopleSpaceWidgetManager(Context context) {
         if (DEBUG) Log.d(TAG, "constructor");
         mContext = context;
-        mAppWidgetManager = IAppWidgetService.Stub.asInterface(
+        mAppWidgetService = IAppWidgetService.Stub.asInterface(
                 ServiceManager.getService(Context.APPWIDGET_SERVICE));
     }
 
     /** AppWidgetManager setter used for testing. */
     @VisibleForTesting
-    protected void setAppWidgetManager(IAppWidgetService appWidgetService) {
-        mAppWidgetManager = appWidgetService;
+    protected void setAppWidgetManager(IAppWidgetService appWidgetService,
+            AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
+        mAppWidgetService = appWidgetService;
+        mAppWidgetManager = appWidgetManager;
+        mNotificationManager = notificationManager;
     }
 
     /** Updates People Space widgets. */
     public void updateWidgets() {
         try {
             if (DEBUG) Log.d(TAG, "updateWidgets called");
-            int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
+            int[] widgetIds = mAppWidgetService.getAppWidgetIds(
                     new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
             );
-
             if (widgetIds.length == 0) {
                 if (DEBUG) Log.d(TAG, "no widgets to update");
                 return;
             }
 
             if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
-            mAppWidgetManager
-                    .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds,
-                            R.id.widget_list_view);
+            boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+
+            if (showSingleConversation) {
+                PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
+                        mAppWidgetManager, mNotificationManager);
+            } else {
+                mAppWidgetService
+                        .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds,
+                                R.id.widget_list_view);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception: " + e);
+        }
+    }
+
+    /**
+     * 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);
         }
@@ -102,6 +159,7 @@
         public void onNotificationPosted(
                 StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
             if (DEBUG) Log.d(TAG, "onNotificationPosted");
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
             updateWidgets();
         }
 
@@ -111,6 +169,7 @@
                 NotificationListenerService.RankingMap rankingMap
         ) {
             if (DEBUG) Log.d(TAG, "onNotificationRemoved");
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
             updateWidgets();
         }
 
@@ -120,12 +179,14 @@
                 NotificationListenerService.RankingMap rankingMap,
                 int reason) {
             if (DEBUG) Log.d(TAG, "onNotificationRemoved with reason " + reason);
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
             updateWidgets();
         }
 
         @Override
         public void onNotificationRankingUpdate(
-                NotificationListenerService.RankingMap rankingMap) { }
+                NotificationListenerService.RankingMap rankingMap) {
+        }
 
         @Override
         public void onNotificationsInitialized() {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 9f84514..7f204cc 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -16,14 +16,19 @@
 
 package com.android.systemui.people.widget;
 
+import android.app.INotificationManager;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProvider;
 import android.content.Context;
 import android.content.Intent;
+import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 import android.widget.RemoteViews;
 
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.systemui.R;
 import com.android.systemui.people.PeopleSpaceUtils;
 
@@ -36,11 +41,22 @@
     public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
     public static final String EXTRA_UID = "extra_uid";
 
+    public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+
     /** Called when widget updates. */
+    @Override
     public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
         super.onUpdate(context, appWidgetManager, appWidgetIds);
 
         if (DEBUG) Log.d(TAG, "onUpdate called");
+        boolean showSingleConversation = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        if (showSingleConversation) {
+            PeopleSpaceUtils.updateSingleConversationWidgets(context, appWidgetIds,
+                    appWidgetManager, INotificationManager.Stub.asInterface(
+                            ServiceManager.getService(Context.NOTIFICATION_SERVICE)));
+            return;
+        }
         // Perform this loop procedure for each App Widget that belongs to this provider
         for (int appWidgetId : appWidgetIds) {
             RemoteViews views =
@@ -68,4 +84,14 @@
             appWidgetManager.updateAppWidget(appWidgetId, views);
         }
     }
+
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds) {
+        super.onDeleted(context, appWidgetIds);
+        for (int widgetId : appWidgetIds) {
+            if (DEBUG) Log.d(TAG, "Widget removed");
+            mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_DELETED);
+        }
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
index 1e6c213..fb33aff 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
@@ -34,7 +34,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /** People Space Widget RemoteViewsFactory class. */
 public class PeopleSpaceWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
@@ -45,7 +44,7 @@
     private INotificationManager mNotificationManager;
     private PackageManager mPackageManager;
     private LauncherApps mLauncherApps;
-    private List<Map.Entry<Long, PeopleSpaceTile>> mTiles = new ArrayList<>();
+    private List<PeopleSpaceTile> mTiles = new ArrayList<>();
     private Context mContext;
 
     public PeopleSpaceWidgetRemoteViewsFactory(Context context, Intent intent) {
@@ -100,11 +99,10 @@
         RemoteViews personView = new RemoteViews(mContext.getPackageName(),
                 R.layout.people_space_widget_item);
         try {
-            Map.Entry<Long, PeopleSpaceTile> entry = mTiles.get(i);
-            PeopleSpaceTile tile = entry.getValue();
-            long lastInteraction = entry.getKey();
+            PeopleSpaceTile tile = mTiles.get(i);
 
-            String status = PeopleSpaceUtils.getLastInteractionString(mContext, lastInteraction);
+            String status = PeopleSpaceUtils.getLastInteractionString(mContext,
+                    tile.getLastInteractionTimestamp(), true);
 
             personView.setTextViewText(R.id.status, status);
             personView.setTextViewText(R.id.name, tile.getUserName().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 87ffbd4..b2c2aa3 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -262,8 +262,11 @@
             privacyList = emptyList()
             return
         }
-        val list = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
-                .mapNotNull { toPrivacyItem(it) }.distinct()
+        val list = appOpsController.getActiveAppOpsForUser(UserHandle.USER_ALL).filter {
+            UserHandle.getUserId(it.uid) in currentUserIds ||
+                    it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE ||
+                    it.code == AppOpsManager.OP_PHONE_CALL_CAMERA
+        }.mapNotNull { toPrivacyItem(it) }.distinct()
         logger.logUpdatedPrivacyItemsList(
                 list.joinToString(separator = ", ", transform = PrivacyItem::toLog))
         privacyList = list
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..d3adc9b 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 = newValue == null || "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/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 5afe526..3866382 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -143,8 +143,6 @@
     }
 
     public void showDeviceMonitoringDialog() {
-        mHost.collapsePanels();
-        // TODO: Delay dialog creation until after panels are collapsed.
         createDialog();
     }
 
@@ -291,6 +289,7 @@
         if (which == DialogInterface.BUTTON_NEGATIVE) {
             final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
             mDialog.dismiss();
+            // This dismisses the shade on opening the activity
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
     }
@@ -605,6 +604,7 @@
         public void onClick(View widget) {
             final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
             mDialog.dismiss();
+            // This dismisses the shade on opening the activity
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index c89f8e5..6074ef61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -252,11 +252,9 @@
 
             final int availableWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
             final int leftoverWhitespace = availableWidth - maxTiles * mCellWidth;
-            final int smallestHorizontalMarginNeeded;
-            smallestHorizontalMarginNeeded = leftoverWhitespace / Math.max(1, maxTiles - 1);
 
-            if (smallestHorizontalMarginNeeded > 0){
-                mCellMarginHorizontal = smallestHorizontalMarginNeeded;
+            if (leftoverWhitespace > 0) {
+                mCellMarginHorizontal = leftoverWhitespace / Math.max(1, maxTiles);
                 mColumns = maxTiles;
             } else{
                 mColumns = mCellWidth == 0 ? 1 :
@@ -266,7 +264,7 @@
                     mCellMarginHorizontal = (availableWidth - mCellWidth) / 2;
                 } else {
                     mCellMarginHorizontal =
-                            (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+                            (availableWidth - mColumns * mCellWidth) / mColumns;
                 }
 
             }
@@ -310,7 +308,8 @@
                 // Only one column/tile. Use the margin to center the tile.
                 return getPaddingStart() + mCellMarginHorizontal;
             }
-            return getPaddingStart() + column *  (mCellWidth + mCellMarginHorizontal);
+            return getPaddingStart() + mCellMarginHorizontal / 2
+                    + column *  (mCellWidth + mCellMarginHorizontal);
         }
 
         @Override
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 dce081f..73ab9b0 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));
+        // Prototype menu item
+        toolbar.getMenu()
+                .add(Menu.NONE, MENU_REMOVE_LABELS, Menu.NONE, "Remove labels")
+                .setCheckable(true)
+                .setVisible(Build.IS_ENG || Build.IS_USERDEBUG);
         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..2dfac1b 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,20 @@
         }
     };
 
+    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            mToolbar.getMenu().findItem(MENU_REMOVE_LABELS)
+                    .setChecked(newValue != null && !("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 +127,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 +164,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 5c683f2..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;
@@ -133,7 +133,7 @@
 
         mColorActive = Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent);
         mColorDisabled = Utils.getDisabled(context,
-                Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary));
+                Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlActivated));
         mColorInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary);
 
         setPadding(0, 0, 0, 0);
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/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 6afc756..c2ba344 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
 
 import android.animation.ArgbEvaluator;
@@ -27,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Binder;
@@ -186,7 +188,7 @@
             DisplayMetrics metrics = new DisplayMetrics();
             mWindowManager.getDefaultDisplay().getMetrics(metrics);
             float density = metrics.density;
-            int rotation = RotationUtils.getRotation(mContext);
+            int rotation = getRotation(mContext);
 
             inflateView(rotation);
             int bgColor = mContext.getColor(
@@ -342,14 +344,23 @@
 
         protected void onConfigurationChanged() {
             removeAllViews();
-            inflateView(RotationUtils.getRotation(mContext));
+            inflateView(getRotation(mContext));
+        }
+
+        private int getRotation(Context context) {
+            Configuration config = context.getResources().getConfiguration();
+            if (config.smallestScreenWidthDp >= 600) {
+                return ROTATION_NONE;
+            }
+
+            return RotationUtils.getRotation(context);
         }
 
         private final Runnable mUpdateLayoutRunnable = new Runnable() {
             @Override
             public void run() {
                 if (mLayout != null && mLayout.getParent() != null) {
-                    mLayout.setLayoutParams(getRequestLayoutParams(RotationUtils.getRotation(mContext)));
+                    mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
                 }
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index f4ce77a..3346935 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -34,7 +34,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
-import android.media.ExifInterface;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -52,10 +51,13 @@
 import android.text.format.DateUtils;
 import android.util.Log;
 
+import androidx.exifinterface.media.ExifInterface;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
 
 import java.io.File;
 import java.io.IOException;
@@ -74,11 +76,12 @@
 import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
 
 /**
  * An AsyncTask that saves an image to the media store in the background.
  */
-class  SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
     private static final String TAG = logTag(SaveImageInBackgroundTask.class);
 
     private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
@@ -95,12 +98,15 @@
     private final String mScreenshotId;
     private final boolean mSmartActionsEnabled;
     private final Random mRandom = new Random();
+    private final Supplier<ShareTransition> mSharedElementTransition;
 
     SaveImageInBackgroundTask(Context context, ScreenshotSmartActions screenshotSmartActions,
-            ScreenshotController.SaveImageInBackgroundData data) {
+            ScreenshotController.SaveImageInBackgroundData data,
+            Supplier<ShareTransition> sharedElementTransition) {
         mContext = context;
         mScreenshotSmartActions = screenshotSmartActions;
         mImageData = new ScreenshotController.SavedImageData();
+        mSharedElementTransition = sharedElementTransition;
 
         // Prepare all the output metadata
         mParams = data;
@@ -135,7 +141,6 @@
 
         ContentResolver resolver = mContext.getContentResolver();
         Bitmap image = mParams.image;
-        Resources r = mContext.getResources();
 
         try {
             // Save the screenshot to the MediaStore
@@ -233,7 +238,7 @@
 
             mImageData.uri = uri;
             mImageData.smartActions = smartActions;
-            mImageData.shareAction = createShareAction(mContext, mContext.getResources(), uri);
+            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
             mImageData.editAction = createEditAction(mContext, mContext.getResources(), uri);
             mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
 
@@ -284,61 +289,68 @@
         mParams.clearImage();
     }
 
+    /**
+     * Assumes that the action intent is sent immediately after being supplied.
+     */
     @VisibleForTesting
-    Notification.Action createShareAction(Context context, Resources r, Uri uri) {
-        // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
-        // order to do some common work like dismissing the keyguard and sending
-        // closeSystemWindows
+    Supplier<ShareTransition> createShareAction(Context context, Resources r, Uri uri) {
+        return () -> {
+            ShareTransition transition = mSharedElementTransition.get();
 
-        // Create a share intent, this will always go through the chooser activity first
-        // which should not trigger auto-enter PiP
-        String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
-        String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
-        Intent sharingIntent = new Intent(Intent.ACTION_SEND);
-        sharingIntent.setType("image/png");
-        sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
-        // Include URI in ClipData also, so that grantPermission picks it up.
-        // We don't use setData here because some apps interpret this as "to:".
-        ClipData clipdata = new ClipData(new ClipDescription("content",
-                new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
-                new ClipData.Item(uri));
-        sharingIntent.setClipData(clipdata);
-        sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
-        sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+            // order to do some common work like dismissing the keyguard and sending
+            // closeSystemWindows
 
-        // Make sure pending intents for the system user are still unique across users
-        // by setting the (otherwise unused) request code to the current user id.
-        int requestCode = context.getUserId();
+            // Create a share intent, this will always go through the chooser activity first
+            // which should not trigger auto-enter PiP
+            String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+            String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+            sharingIntent.setType("image/png");
+            sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+            // Include URI in ClipData also, so that grantPermission picks it up.
+            // We don't use setData here because some apps interpret this as "to:".
+            ClipData clipdata = new ClipData(new ClipDescription("content",
+                    new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+                    new ClipData.Item(uri));
+            sharingIntent.setClipData(clipdata);
+            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+            sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-        Intent sharingChooserIntent =
-                Intent.createChooser(sharingIntent, null)
-                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
-                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            // Make sure pending intents for the system user are still unique across users
+            // by setting the (otherwise unused) request code to the current user id.
+            int requestCode = context.getUserId();
 
-        // cancel current pending intent (if any) since clipData isn't used for matching
-        PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
-                context, 0, sharingChooserIntent,
-                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
-                null, UserHandle.CURRENT);
+            Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null)
+                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-        // Create a share action for the notification
-        PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
-                new Intent(context, ActionProxyReceiver.class)
-                        .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
-                        .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
-                        .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
-                        .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
-                                mSmartActionsEnabled)
-                        .setAction(Intent.ACTION_SEND)
-                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
-                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
-                UserHandle.SYSTEM);
+            // cancel current pending intent (if any) since clipData isn't used for matching
+            PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+                    context, 0, sharingChooserIntent,
+                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+                    transition.bundle, UserHandle.CURRENT);
 
-        Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
-                Icon.createWithResource(r, R.drawable.ic_screenshot_share),
-                r.getString(com.android.internal.R.string.share), shareAction);
+            // Create a share action for the notification
+            PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+                    new Intent(context, ActionProxyReceiver.class)
+                            .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
+                            .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
+                            .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
+                            .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
+                                    mSmartActionsEnabled)
+                            .setAction(Intent.ACTION_SEND)
+                            .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+                    UserHandle.SYSTEM);
 
-        return shareActionBuilder.build();
+            Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+                    Icon.createWithResource(r, R.drawable.ic_screenshot_share),
+                    r.getString(com.android.internal.R.string.share), shareAction);
+
+            transition.shareAction = shareActionBuilder.build();
+            return transition;
+        };
     }
 
     @VisibleForTesting
@@ -354,8 +366,7 @@
         if (!TextUtils.isEmpty(editorPackage)) {
             editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
         }
-        editIntent.setType("image/png");
-        editIntent.setData(uri);
+        editIntent.setDataAndType(uri, "image/png");
         editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
         editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 6a4e93b..d2fe5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -34,6 +34,9 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.app.ExitTransitionCoordinator;
+import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
 import android.app.Notification;
 import android.content.ComponentName;
 import android.content.Context;
@@ -46,6 +49,7 @@
 import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -54,6 +58,7 @@
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.Pair;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -67,15 +72,18 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
+import com.android.internal.app.ChooserActivity;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.policy.PhoneWindow;
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.R;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
 import com.android.systemui.util.DeviceConfigProxy;
 
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 import javax.inject.Inject;
 
@@ -84,6 +92,7 @@
  */
 public class ScreenshotController {
     private static final String TAG = logTag(ScreenshotController.class);
+
     /**
      * POD used in the AsyncTask which saves an image in the background.
      */
@@ -102,17 +111,26 @@
      */
     static class SavedImageData {
         public Uri uri;
-        public Notification.Action shareAction;
+        public Supplier<ShareTransition> shareTransition;
         public Notification.Action editAction;
         public Notification.Action deleteAction;
         public List<Notification.Action> smartActions;
 
         /**
+         * POD for shared element transition to share sheet.
+         */
+        static class ShareTransition {
+            public Bundle bundle;
+            public Notification.Action shareAction;
+            public Runnable onCancelRunnable;
+        }
+
+        /**
          * Used to reset the return data on error
          */
         public void reset() {
             uri = null;
-            shareAction = null;
+            shareTransition = null;
             editAction = null;
             deleteAction = null;
             smartActions = null;
@@ -350,10 +368,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 +460,7 @@
             }
             if (DEBUG_WINDOW) {
                 Log.d(TAG, "saveScreenshot: screenshotView is already attached, resetting. "
-                        + "(dismissing=" + mScreenshotView.isDismissing()  + ")");
+                        + "(dismissing=" + mScreenshotView.isDismissing() + ")");
             }
             mScreenshotView.reset();
         }
@@ -576,15 +604,13 @@
             mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
         }
 
-        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+                getShareTransitionSupplier());
         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 +618,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(() -> {
@@ -617,6 +656,35 @@
     }
 
     /**
+     * Supplies the necessary bits for the shared element transition to share sheet.
+     * Note that once supplied, the action intent to share must be sent immediately after.
+     */
+    private Supplier<ShareTransition> getShareTransitionSupplier() {
+        return () -> {
+            ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
+                @Override
+                public boolean isReturnTransitionAllowed() {
+                    return false;
+                }
+
+                @Override
+                public void onFinish() { }
+            };
+
+            Pair<ActivityOptions, ExitTransitionCoordinator> transition =
+                    ActivityOptions.startSharedElementAnimation(mWindow, cb, null,
+                            Pair.create(mScreenshotView.getScreenshotPreview(),
+                                    ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
+            transition.second.startExit();
+
+            ShareTransition supply = new ShareTransition();
+            supply.bundle = transition.first.toBundle();
+            supply.onCancelRunnable = () -> ActivityOptions.stopSharedElementAnimation(mWindow);
+            return supply;
+        };
+    }
+
+    /**
      * Logs success/failure of the screenshot saving task, and shows an error if it failed.
      */
     private void logSuccessOnActionsReady(ScreenshotController.SavedImageData imageData) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index cce60f9..357702a 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;
@@ -72,6 +73,7 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.util.ArrayList;
@@ -83,6 +85,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;
@@ -97,8 +105,10 @@
     private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
     private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
     private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
+    private static final long SCREENSHOT_DISMISS_SHARE_OFFSET_MS = 300; // delay after share clicked
     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 +125,7 @@
     private boolean mDirectionLTR;
 
     private ScreenshotSelectorView mScreenshotSelectorView;
+    private View mScreenshotStatic;
     private ImageView mScreenshotPreview;
     private ImageView mScreenshotFlash;
     private ImageView mActionsContainerBackground;
@@ -127,8 +138,9 @@
     private ScreenshotActionChip mScrollChip;
 
     private UiEventLogger mUiEventLogger;
-    private Runnable mOnDismissRunnable;
+    private ScreenshotViewCallback mCallbacks;
     private Animator mDismissAnimation;
+    private boolean mIgnoreDismiss;
 
     private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
     private PendingInteraction mPendingInteraction;
@@ -195,8 +207,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 +229,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 +254,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 +298,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 +440,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);
             }
         });
 
@@ -497,13 +529,31 @@
         });
         return animator;
     }
+    protected View getScreenshotPreview() {
+        return mScreenshotPreview;
+    }
 
     void setChipIntents(ScreenshotController.SavedImageData imageData) {
-        mShareChip.setPendingIntent(imageData.shareAction.actionIntent,
-                () -> {
-                    mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
+        mShareChip.setOnClickListener(v -> {
+            ShareTransition transition = imageData.shareTransition.get();
+            try {
+                mIgnoreDismiss = true;
+                transition.shareAction.actionIntent.send();
+                mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
+
+                // Ensures that we delay dismissing until transition has started.
+                postDelayed(() -> {
+                    mIgnoreDismiss = false;
                     animateDismissal();
-                });
+                }, SCREENSHOT_DISMISS_SHARE_OFFSET_MS);
+            } catch (PendingIntent.CanceledException e) {
+                mIgnoreDismiss = false;
+                if (transition.onCancelRunnable != null) {
+                    transition.onCancelRunnable.run();
+                }
+                Log.e(TAG, "Share intent cancelled", e);
+            }
+        });
         mEditChip.setPendingIntent(imageData.editAction.actionIntent,
                 () -> {
                     mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED);
@@ -544,6 +594,7 @@
                             mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
                             animateDismissal();
                         });
+                actionChip.setAlpha(1);
                 mActionsView.addView(actionChip);
                 mSmartChips.add(actionChip);
             }
@@ -559,6 +610,9 @@
     }
 
     private void animateDismissal(Animator dismissAnimation) {
+        if (mIgnoreDismiss) {
+            return;
+        }
         if (DEBUG_WINDOW) {
             Log.d(TAG, "removing OnComputeInternalInsetsListener");
         }
@@ -583,7 +637,7 @@
                     if (DEBUG_ANIM) {
                         Log.d(TAG, "after dismiss animation, calling onDismissRunnable.run()");
                     }
-                    mOnDismissRunnable.run();
+                    mCallbacks.onDismiss();
                 }
             }
         });
@@ -617,7 +671,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 +729,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 +751,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 +765,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);
@@ -719,11 +783,17 @@
         }
 
         @Override
-        public boolean onTouch(View v, MotionEvent event) {
+        public boolean onTouch(View view, 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) {
@@ -743,20 +813,51 @@
                         createSwipeReturnAnimation().start();
                     }
                     return true;
+                } else {
+                    if (view == mScreenshotPreview) {
+                        mScreenshotPreview.performClick();
+                    }
                 }
             }
-            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 +873,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 +897,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/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index 6c4f808..53ff1df 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -17,6 +17,9 @@
 package com.android.systemui.settings.brightness;
 
 import android.content.Context;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -27,6 +30,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.util.ViewController;
@@ -269,14 +273,45 @@
 
         private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
             BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
+
+            // TODO(175026098) Workaround. Remove when b/175026098 is fixed
+            applyTheme(v);
+
             return new BrightnessSlider(root, v, useMirror);
         }
 
         /** Get the layout to inflate based on what slider to use */
-        public int getLayout() {
+        private int getLayout() {
             return mSettings.useThickSlider()
                     ? R.layout.quick_settings_brightness_dialog_thick
                     : R.layout.quick_settings_brightness_dialog;
         }
+
+        private LayerDrawable findProgressClippableDrawable(BrightnessSliderView v) {
+            SeekBar b = v.requireViewById(R.id.slider);
+            if (b.getProgressDrawable() instanceof LayerDrawable) {
+                Drawable progress = ((LayerDrawable) b.getProgressDrawable())
+                        .findDrawableByLayerId(com.android.internal.R.id.progress);
+                if (progress instanceof ClipDrawable) {
+                    Drawable inner = ((ClipDrawable) progress).getDrawable();
+                    if (inner instanceof LayerDrawable) {
+                        return (LayerDrawable) inner;
+                    }
+                }
+            }
+            return null;
+        }
+
+        private void applyTheme(BrightnessSliderView v) {
+            LayerDrawable layer = findProgressClippableDrawable(v);
+            if (layer != null) {
+                layer.findDrawableByLayerId(R.id.slider_foreground).setTintList(
+                        Utils.getColorAttr(v.getContext(),
+                                com.android.internal.R.attr.colorControlActivated));
+                layer.findDrawableByLayerId(R.id.slider_icon).setTintList(
+                        Utils.getColorAttr(v.getContext(),
+                                com.android.internal.R.attr.colorBackground));
+            }
+        }
     }
 }
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..3c549f9 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.getFeedbackResources(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..0465ebf 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;
@@ -26,9 +27,11 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.Pair;
 
 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 +50,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 +90,92 @@
     }
 
     /**
-     * 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 and content description resources according to assistant's
+     * changes on this notification's rank or importance.
+     *
+     * @param entry Notification Entry to show feedback for
+     */
+    public Pair<Integer, Integer> getFeedbackResources(NotificationEntry entry) {
+        int feedbackStatus = getFeedbackStatus(entry);
+        switch (feedbackStatus) {
+            case STATUS_ALERTED:
+                return new Pair(R.drawable.ic_feedback_alerted,
+                        R.string.notification_feedback_indicator_alerted);
+            case STATUS_SILENCED:
+                return new Pair(R.drawable.ic_feedback_silenced,
+                        R.string.notification_feedback_indicator_silenced);
+            case STATUS_PROMOTED:
+                return new Pair(R.drawable.ic_feedback_uprank,
+                        R.string.notification_feedback_indicator_promoted);
+            case STATUS_DEMOTED:
+                return new Pair(R.drawable.ic_feedback_downrank,
+                        R.string.notification_feedback_indicator_demoted);
+            default:
+                return new Pair(0, 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/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 10118e4..3c437d1 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
@@ -49,6 +49,7 @@
 import android.util.FloatProperty;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.Pair;
 import android.util.Property;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -1672,12 +1673,12 @@
         requestLayout();
     }
 
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
         if (mIsSummaryWithChildren) {
-            mChildrenContainer.showFeedbackIcon(show);
+            mChildrenContainer.showFeedbackIcon(show, resIds);
         }
-        mPrivateLayout.showFeedbackIcon(show);
-        mPublicLayout.showFeedbackIcon(show);
+        mPrivateLayout.showFeedbackIcon(show, resIds);
+        mPublicLayout.showFeedbackIcon(show, resIds);
     }
 
     /** 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 4c78e62..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,11 +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 static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
-
 import android.annotation.SuppressLint;
 import android.app.Notification;
 import android.content.Context;
@@ -31,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;
@@ -43,6 +39,7 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -64,6 +61,9 @@
     private NotificationEntryManager mNotificationEntryManager;
     private IStatusBarService mStatusBarService;
     private AssistantFeedbackController mFeedbackController;
+    private NotificationGutsManager mNotificationGutsManager;
+    private NotificationMenuRowPlugin mMenuRowPlugin;
+    private ExpandableNotificationRow mExpandableNotificationRow;
 
     public FeedbackInfo(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -73,19 +73,21 @@
             final PackageManager pm,
             final StatusBarNotification sbn,
             final NotificationEntry entry,
+            final ExpandableNotificationRow row,
             final AssistantFeedbackController controller) {
         mPkg = sbn.getPackageName();
         mPm = pm;
         mEntry = entry;
+        mExpandableNotificationRow = row;
         mRanking = entry.getRanking();
         mFeedbackController = controller;
         mAppName = mPkg;
         mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
         mStatusBarService = Dependency.get(IStatusBarService.class);
+        mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
 
         bindHeader();
         bindPrompt();
-        bindButton();
     }
 
     private void bindHeader() {
@@ -133,55 +135,52 @@
         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();
     }
 
-    private void bindButton() {
-        TextView ok = findViewById(R.id.ok);
-        ok.setOnClickListener(this::closeControls);
-    }
-
     private void positiveFeedback(View v) {
+        mGutsContainer.closeControls(v, false);
         handleFeedback(true);
     }
 
     private void negativeFeedback(View v) {
+        mMenuRowPlugin = mExpandableNotificationRow.getProvider();
+        NotificationMenuRowPlugin.MenuItem menuItem = null;
+        if (mMenuRowPlugin != null) {
+            menuItem = mMenuRowPlugin.getLongpressMenuItem(mContext);
+        }
+
+        mGutsContainer.closeControls(v, false);
+        mNotificationGutsManager.openGuts(mExpandableNotificationRow, 0, 0, menuItem);
         handleFeedback(false);
     }
 
     private void handleFeedback(boolean positive) {
-        TextView prompt = findViewById(R.id.prompt);
-        prompt.setText(mContext.getString(R.string.feedback_response));
-        TextView yes = findViewById(R.id.yes);
-        yes.setVisibility(View.GONE);
-        TextView no = findViewById(R.id.no);
-        no.setVisibility(View.GONE);
-
         Bundle feedback = new Bundle();
         feedback.putBoolean(FEEDBACK_KEY, positive);
         sendFeedbackToAssistant(feedback);
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..d2774df 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
@@ -33,6 +33,7 @@
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.NotificationHeaderView;
@@ -1586,15 +1587,15 @@
         return null;
     }
 
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
         if (mContractedChild != null) {
-            mContractedWrapper.showFeedbackIcon(show);
+            mContractedWrapper.showFeedbackIcon(show, resIds);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.showFeedbackIcon(show);
+            mExpandedWrapper.showFeedbackIcon(show, resIds);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.showFeedbackIcon(show);
+            mHeadsUpWrapper.showFeedbackIcon(show, resIds);
         }
     }
 
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 d2cfb29..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
@@ -324,7 +324,7 @@
                 userHandle.getIdentifier());
 
         if (mAssistantFeedbackController.showFeedbackIndicator(row.getEntry())) {
-            feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), mAssistantFeedbackController);
+            feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController);
         }
     }
 
@@ -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/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 1034b1f..596aea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
 
 import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
 
@@ -113,6 +114,8 @@
 
     private boolean mIsUserTouching;
 
+    private boolean mSnappingToDismiss;
+
     private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     public NotificationMenuRow(Context context,
@@ -175,6 +178,11 @@
         return mSnapping;
     }
 
+    @VisibleForTesting
+    protected boolean isSnappingToDismiss() {
+        return mSnappingToDismiss;
+    }
+
     @Override
     public void setMenuClickListener(OnMenuEventListener listener) {
         mMenuListener = listener;
@@ -346,6 +354,14 @@
             mCheckForDrag = new CheckForDrag();
             mHandler.postDelayed(mCheckForDrag, SHOW_MENU_DELAY);
         }
+        if (canBeDismissed()) {
+            final float dismissThreshold = getDismissThreshold();
+            final boolean snappingToDismiss = delta < -dismissThreshold || delta > dismissThreshold;
+            if (mSnappingToDismiss != snappingToDismiss) {
+                getMenuView().performHapticFeedback(CLOCK_TICK);
+            }
+            mSnappingToDismiss = snappingToDismiss;
+        }
     }
 
     @VisibleForTesting
@@ -361,7 +377,8 @@
 
     @Override
     public void onTouchStart() {
-       beginDrag();
+        beginDrag();
+        mSnappingToDismiss = false;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 4c9c2f9..414d620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -47,6 +47,10 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         super.onContentUpdated(row);
 
+        // Custom views will most likely use just white or black as their text color.
+        // We need to scan through and replace these colors by Material NEXT colors.
+        ensureThemeOnChildren();
+
         // Let's invert the notification colors when we're in night mode and
         // the notification background isn't colorized.
         if (needsInversion(mBackgroundColor, mView)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
index 49a8d56..7964845 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -43,6 +43,11 @@
         if (childIndex != null && childIndex != -1) {
             mWrappedView = container.getChildAt(childIndex);
         }
+
+        // Custom views will most likely use just white or black as their text color.
+        // We need to scan through and replace these colors by Material NEXT colors.
+        ensureThemeOnChildren();
+
         if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
             invertViewLuminosity(mWrappedView);
         }
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..28ee935 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
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.util.ArraySet;
+import android.util.Pair;
 import android.view.NotificationHeaderView;
 import android.view.NotificationTopLineView;
 import android.view.View;
@@ -29,6 +30,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 +133,14 @@
 
     /** Shows or hides feedback indicator */
     @Override
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
         mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+        if (show) {
+            if (mFeedbackIcon instanceof ImageButton) {
+                ((ImageButton) mFeedbackIcon).setImageResource(resIds.first);
+            }
+            mFeedbackIcon.setContentDescription(mView.getContext().getString(resIds.second));
+        }
     }
 
     @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 416c5af..7b5c5f6 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
@@ -29,11 +29,14 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.util.Pair;
+import android.view.ContextThemeWrapper;
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.internal.util.ContrastColorUtil;
@@ -55,6 +58,9 @@
     private final Rect mTmpRect = new Rect();
 
     protected int mBackgroundColor = 0;
+    private int mLightTextColor;
+    private int mDarkTextColor;
+    private int mDefaultTextColor;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -98,7 +104,7 @@
     /**
      * Shows or hides feedback icon.
      */
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
     }
 
     public void onReinflated() {
@@ -110,6 +116,15 @@
             mBackgroundColor = backgroundColor;
             mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
         }
+        mLightTextColor = mView.getContext().getColor(
+                com.android.internal.R.color.notification_primary_text_color_light);
+        mDarkTextColor = mView.getContext().getColor(
+                R.color.notification_primary_text_color_dark);
+
+        Context themedContext = new ContextThemeWrapper(mView.getContext(),
+                R.style.Theme_DeviceDefault_DayNight);
+        mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
+                .getDefaultColor();
     }
 
     protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -187,6 +202,42 @@
         return false;
     }
 
+    protected void ensureThemeOnChildren() {
+        if (mView == null) {
+            return;
+        }
+
+        // Notifications with custom backgrounds should not be adjusted
+        if (mBackgroundColor != Color.TRANSPARENT
+                || getBackgroundColor(mView) != Color.TRANSPARENT) {
+            return;
+        }
+
+        // Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
+        if (!(mView instanceof ViewGroup)) {
+            return;
+        }
+        processChildrenTextColor((ViewGroup) mView);
+    }
+
+    private void processChildrenTextColor(ViewGroup viewGroup) {
+        if (viewGroup == null) {
+            return;
+        }
+
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            View child = viewGroup.getChildAt(i);
+            if (child instanceof TextView) {
+                int foreground = ((TextView) child).getCurrentTextColor();
+                if (foreground == mLightTextColor || foreground == mDarkTextColor) {
+                    ((TextView) child).setTextColor(mDefaultTextColor);
+                }
+            } else if (child instanceof ViewGroup) {
+                processChildrenTextColor((ViewGroup) child);
+            }
+        }
+    }
+
     protected int getBackgroundColor(View view) {
         if (view == null) {
             return Color.TRANSPARENT;
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..3833637 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
@@ -23,6 +23,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -1300,12 +1301,12 @@
     /**
      * Shows or hides feedback icon.
      */
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
         if (mNotificationHeaderWrapper != null) {
-            mNotificationHeaderWrapper.showFeedbackIcon(show);
+            mNotificationHeaderWrapper.showFeedbackIcon(show, resIds);
         }
         if (mNotificationHeaderWrapperLowPriority != null) {
-            mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show);
+            mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resIds);
         }
     }
 
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..079cf77 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
@@ -20,12 +20,9 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
 import java.util.HashSet;
 
@@ -48,6 +45,11 @@
     private ExpandableNotificationRow mTrackedHeadsUp;
     private float mAppearFraction;
 
+    // Radius for notification corners WITH adjacent notifications
+    // as percent of radius WITHOUT adjacent notifications.
+    // TODO(b/175710408) pull from dimens and hide from beta builds.
+    static final float SMALL_CORNER_RADIUS = 4f/28;
+
     @Inject
     NotificationRoundnessManager(
             KeyguardBypassController keyguardBypassController,
@@ -67,7 +69,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 +109,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) {
@@ -124,7 +128,7 @@
         if (view.showingPulsing() && !mBypassController.getBypassEnabled()) {
             return 1.0f;
         }
-        return 0.0f;
+        return SMALL_CORNER_RADIUS;
     }
 
     public void setExpanded(float expandedHeight, float appearFraction) {
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/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index a5667bb..e1eaf3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -390,17 +390,17 @@
     }
 
     @Override
-    public void setDozeScreenBrightness(int value) {
-        mNotificationShadeWindowController.setDozeScreenBrightness(value);
+    public void setDozeScreenBrightness(int brightness) {
+        mDozeLog.traceDozeScreenBrightness(brightness);
+        mNotificationShadeWindowController.setDozeScreenBrightness(brightness);
     }
 
     @Override
     public void setAodDimmingScrim(float scrimOpacity) {
+        mDozeLog.traceSetAodDimmingScrim(scrimOpacity);
         mScrimController.setAodFrontScrimAlpha(scrimOpacity);
     }
 
-
-
     @Override
     public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
         if (mPendingScreenOffCallback != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1a2d1cf..b9e8d74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -116,6 +116,11 @@
      */
     private float mDarkAmount;
 
+    /**
+     * How visible the quick settings panel is.
+     */
+    private float mQsExpansion;
+
     private float mEmptyDragAmount;
 
     /**
@@ -159,7 +164,8 @@
     public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
             float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
             boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
-            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled) {
+            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled,
+            float qsExpansion) {
         mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon :
                 mContainerTopPaddingWithLockIcon);
         mMaxShadeBottom = maxShadeBottom;
@@ -174,6 +180,7 @@
         mEmptyDragAmount = emptyDragAmount;
         mBypassEnabled = bypassEnabled;
         mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
+        mQsExpansion = qsExpansion;
     }
 
     public void run(Result result) {
@@ -274,6 +281,7 @@
      */
     private float getClockAlpha(int y) {
         float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f)));
+        alphaKeyguard *= (1f - mQsExpansion);
         alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index c54fa29..30c951a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -16,18 +16,32 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Interpolators;
+
+import java.util.LinkedList;
+
 /**
  * A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
  */
 public class KeyguardIndicationTextView extends TextView {
 
-    private CharSequence mText = "";
+    private static final int FADE_OUT_MILLIS = 200;
+    private static final int FADE_IN_MILLIS = 250;
+    private static final long MSG_DURATION_MILLIS = 600;
+    private long mNextAnimationTime = 0;
+    private boolean mAnimationsEnabled = true;
+    private LinkedList<CharSequence> mMessages = new LinkedList<>();
 
     public KeyguardIndicationTextView(Context context) {
         super(context);
@@ -52,15 +66,68 @@
      * @param text The text to show.
      */
     public void switchIndication(CharSequence text) {
+        if (text == null) text = "";
 
-        // TODO: Animation, make sure that we will show one indication long enough.
-        if (TextUtils.isEmpty(text)) {
-            mText = "";
-            setVisibility(View.INVISIBLE);
-        } else if (!TextUtils.equals(text, mText)) {
-            mText = text;
-            setVisibility(View.VISIBLE);
-            setText(mText);
+        CharSequence lastPendingMessage = mMessages.peekLast();
+        if (TextUtils.equals(lastPendingMessage, text)
+                || (lastPendingMessage == null && TextUtils.equals(text, getText()))) {
+            return;
+        }
+        mMessages.add(text);
+
+        Animator fadeOut = ObjectAnimator.ofFloat(this, View.ALPHA, 0f);
+        fadeOut.setDuration(getFadeOutMillis());
+        fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+
+        final CharSequence nextText = text;
+        fadeOut.addListener(new AnimatorListenerAdapter() {
+                public void onAnimationEnd(Animator animator) {
+                    setText(mMessages.poll());
+                }
+            });
+
+        final AnimatorSet animSet = new AnimatorSet();
+        final AnimatorSet.Builder animSetBuilder = animSet.play(fadeOut);
+
+        // Make sure each animation is visible for a minimum amount of time, while not worrying
+        // about fading in blank text
+        long timeInMillis = System.currentTimeMillis();
+        long delay = Math.max(0, mNextAnimationTime - timeInMillis);
+        setNextAnimationTime(timeInMillis + delay + getFadeOutMillis());
+
+        if (!text.equals("")) {
+            setNextAnimationTime(mNextAnimationTime + MSG_DURATION_MILLIS);
+
+            ObjectAnimator fadeIn = ObjectAnimator.ofFloat(this, View.ALPHA, 1f);
+            fadeIn.setDuration(getFadeInMillis());
+            fadeIn.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            animSetBuilder.before(fadeIn);
+        }
+
+        animSet.setStartDelay(delay);
+        animSet.start();
+    }
+
+    @VisibleForTesting
+    public void setAnimationsEnabled(boolean enabled) {
+        mAnimationsEnabled = enabled;
+    }
+
+    private long getFadeInMillis() {
+        if (mAnimationsEnabled) return FADE_IN_MILLIS;
+        return 0L;
+    }
+
+    private long getFadeOutMillis() {
+        if (mAnimationsEnabled) return FADE_OUT_MILLIS;
+        return 0L;
+    }
+
+    private void setNextAnimationTime(long time) {
+        if (mAnimationsEnabled) {
+            mNextAnimationTime = time;
+        } else {
+            mNextAnimationTime = 0L;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 547a370..6bdc303 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -37,6 +37,7 @@
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.settingslib.Utils;
@@ -78,6 +79,7 @@
     private final KeyguardStateController mKeyguardStateController;
     private final Resources mResources;
     private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+    private final KeyguardSecurityModel mKeyguardSecurityModel;
     private boolean mKeyguardShowing;
     private boolean mKeyguardJustShown;
     private boolean mBlockUpdates;
@@ -326,7 +328,8 @@
             @Nullable DockManager dockManager,
             KeyguardStateController keyguardStateController,
             @Main Resources resources,
-            HeadsUpManagerPhone headsUpManagerPhone) {
+            HeadsUpManagerPhone headsUpManagerPhone,
+            KeyguardSecurityModel keyguardSecurityModel) {
         mLockscreenGestureLogger = lockscreenGestureLogger;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockPatternUtils = lockPatternUtils;
@@ -341,6 +344,7 @@
         mKeyguardStateController = keyguardStateController;
         mResources = resources;
         mHeadsUpManagerPhone = headsUpManagerPhone;
+        mKeyguardSecurityModel = keyguardSecurityModel;
 
         mKeyguardIndicationController.setLockIconController(this);
     }
@@ -541,13 +545,20 @@
      * @return true if the visibility changed
      */
     private boolean updateIconVisibility() {
+        if (mLockIcon == null) {
+            return false;
+        }
+
         if (mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
             boolean changed = mLockIcon.getVisibility() == GONE;
             mLockIcon.setVisibility(GONE);
             return changed;
         }
+
         boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked;
-        boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance;
+        boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance
+                || (mKeyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser())
+                == KeyguardSecurityModel.SecurityMode.None);
         boolean fingerprintOrBypass = mFingerprintUnlock
                 || mKeyguardBypassController.getBypassEnabled();
         if (fingerprintOrBypass && !mBouncerShowingScrimmed) {
@@ -559,11 +570,6 @@
                 invisible = true;
             }
         }
-
-        if (mLockIcon == null) {
-            return false;
-        }
-
         return mLockIcon.updateIconVisibility(!invisible);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 84eacdc..8d3b128 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -292,6 +292,7 @@
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
     private final QSDetailDisplayer mQSDetailDisplayer;
+    private final ScrimController mScrimController;
     // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
     // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
     private final int mMaxKeyguardNotifications;
@@ -549,6 +550,7 @@
             NotificationIconAreaController notificationIconAreaController,
             AuthController authController,
             QSDetailDisplayer qsDetailDisplayer,
+            ScrimController scrimController,
             MediaDataManager mediaDataManager) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
@@ -579,6 +581,7 @@
         mPulseExpansionHandler = pulseExpansionHandler;
         mDozeParameters = dozeParameters;
         mBiometricUnlockController = biometricUnlockController;
+        mScrimController = scrimController;
         mMediaDataManager = mediaDataManager;
         pulseExpansionHandler.setPulseExpandAbortListener(() -> {
             if (mQs != null) {
@@ -909,7 +912,7 @@
                     clockPreferredY, hasCustomClock(),
                     hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
                     bypassEnabled, getUnlockedStackScrollerPadding(),
-                    mUpdateMonitor.isUdfpsEnrolled());
+                    mUpdateMonitor.isUdfpsEnrolled(), getQsExpansionFraction());
             mClockPositionAlgorithm.run(mClockPositionResult);
             mKeyguardStatusViewController.updatePosition(
                     mClockPositionResult.clockX, mClockPositionResult.clockY,
@@ -1137,6 +1140,7 @@
         if (isFullyCollapsed()) {
             expand(true /* animate */);
         } else {
+            traceQsJank(true /* startTracing */, false /* wasCancelled */);
             flingSettings(0 /* velocity */, FLING_EXPAND);
         }
     }
@@ -1756,6 +1760,7 @@
         updateHeaderKeyguardAlpha();
         if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == KEYGUARD) {
             updateKeyguardBottomAreaAlpha();
+            positionClockAndNotifications();
             updateBigClockAlpha();
         }
 
@@ -1782,6 +1787,7 @@
         float qsExpansionFraction = getQsExpansionFraction();
         mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
         mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
+        mScrimController.setQsExpansion(qsExpansionFraction);
         mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
     }
 
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/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index ba4fbb8..2ac9f30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -238,7 +238,7 @@
                 if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
                     return false;
                 }
-                mFalsingCollector.onTouchEvent(ev, mView.getWidth(), mView.getHeight());
+                mFalsingCollector.onTouchEvent(ev);
                 mGestureDetector.onTouchEvent(ev);
                 if (mBrightnessMirror != null
                         && mBrightnessMirror.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 5a01f47..8ed9710 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -862,6 +862,8 @@
                             mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                             if (mAnimateAfterExpanding) {
                                 notifyExpandingStarted();
+                                InteractionJankMonitor.getInstance().begin(
+                                        CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
                                 fling(0, true /* expand */);
                             } else {
                                 setExpandedFraction(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 9e7efc1..f8e361f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -125,11 +125,6 @@
      */
     public static final float BUSY_SCRIM_ALPHA = 1f;
 
-    /**
-     * Same as above, but when blur is supported.
-     */
-    public static final float BLUR_SCRIM_ALPHA = 0.80f;
-
     static final int TAG_KEY_ANIM = R.id.scrim;
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
@@ -161,6 +156,7 @@
 
     // Assuming the shade is expanded during initialization
     private float mExpansionFraction = 1f;
+    private float mQsExpansion;
 
     private boolean mDarkenWhileDragging;
     private boolean mExpansionAffectsAlpha = true;
@@ -206,8 +202,7 @@
             BlurUtils blurUtils, ConfigurationController configurationController) {
 
         mScrimStateListener = lightBarController::setScrimState;
-        mDefaultScrimAlpha = blurUtils.supportsBlursOnWindows()
-                ? BLUR_SCRIM_ALPHA : BUSY_SCRIM_ALPHA;
+        mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
         mBlurUtils = blurUtils;
 
         mKeyguardStateController = keyguardStateController;
@@ -464,6 +459,31 @@
 
             boolean relevantState = (mState == ScrimState.UNLOCKED
                     || mState == ScrimState.KEYGUARD
+                    || mState == ScrimState.SHADE_LOCKED
+                    || mState == ScrimState.PULSING
+                    || mState == ScrimState.BUBBLE_EXPANDED);
+            if (!(relevantState && mExpansionAffectsAlpha)) {
+                return;
+            }
+            applyAndDispatchExpansion();
+        }
+    }
+
+    /**
+     * Current state of the QuickSettings expansion when pulling it from the top.
+     *
+     * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded.
+     */
+    public void setQsExpansion(float fraction) {
+        if (isNaN(fraction)) {
+            return;
+        }
+        if (mQsExpansion != fraction) {
+            mQsExpansion = fraction;
+            Log.d(TAG, "set qs fraction");
+
+            boolean relevantState = (mState == ScrimState.SHADE_LOCKED
+                    || mState == ScrimState.KEYGUARD
                     || mState == ScrimState.PULSING
                     || mState == ScrimState.BUBBLE_EXPANDED);
             if (!(relevantState && mExpansionAffectsAlpha)) {
@@ -506,7 +526,8 @@
             behindFraction = (float) Math.pow(behindFraction, 0.8f);
             mBehindAlpha = behindFraction * mDefaultScrimAlpha;
             mInFrontAlpha = 0;
-        } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) {
+        } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
+                || mState == ScrimState.PULSING) {
             // Either darken of make the scrim transparent when you
             // pull down the shade
             float interpolatedFract = getInterpolatedFraction();
@@ -522,6 +543,11 @@
             }
             mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
                     mState.getBehindTint(), interpolatedFract);
+            if (mQsExpansion > 0) {
+                mBehindAlpha = MathUtils.lerp(mBehindAlpha, mDefaultScrimAlpha, mQsExpansion);
+                mBehindTint = ColorUtils.blendARGB(mBehindTint,
+                        ScrimState.SHADE_LOCKED.getBehindTint(), mQsExpansion);
+            }
         }
         if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha)) {
             throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index fc91c16..994da79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -112,6 +112,15 @@
         }
     },
 
+    SHADE_LOCKED {
+        @Override
+        public void prepare(ScrimState previousState) {
+            mBehindAlpha = mDefaultScrimAlpha;
+            mBubbleAlpha = 0f;
+            mFrontAlpha = 0f;
+        }
+    },
+
     /**
      * Changing screen brightness from quick settings.
      */
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 981f9a6..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);
             }
@@ -4099,6 +4099,8 @@
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+        } else if (mState == StatusBarState.SHADE_LOCKED) {
+            mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
         } else if (mDozeServiceHost.isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
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/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index d8710bf..8c67072 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -37,7 +37,6 @@
 import com.android.settingslib.fuelgauge.Estimate;
 import com.android.settingslib.utils.PowerUtil;
 import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.demomode.DemoMode;
@@ -49,13 +48,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.inject.Inject;
-
 /**
  * Default implementation of a {@link BatteryController}. This controller monitors for battery
  * level change events that are broadcasted by the system.
  */
-@SysUISingleton
 public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
     private static final String TAG = "BatteryController";
 
@@ -89,7 +85,6 @@
     private boolean mFetchingEstimate = false;
 
     @VisibleForTesting
-    @Inject
     public BatteryControllerImpl(
             Context context,
             EnhancedEstimates enhancedEstimates,
@@ -155,8 +150,11 @@
             mChangeCallbacks.add(cb);
         }
         if (!mHasReceivedBattery) return;
+
+        // Make sure new callbacks get the correct initial state
         cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
         cb.onPowerSaveChanged(mPowerSave);
+        cb.onBatteryUnknownStateChanged(mStateUnknown);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
index 92e5b78..27e40e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
@@ -56,7 +56,8 @@
 
             val intent = Intent(Intent.ACTION_VIEW,
                     Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl)))
-            val pi = PendingIntent.getActivity(context, 0, intent, 0)
+            val pi = PendingIntent.getActivity(context, 0, intent,
+                    PendingIntent.FLAG_IMMUTABLE)
 
             val builder = Notification.Builder(context, channel.id)
                     .setAutoCancel(false)
@@ -87,4 +88,4 @@
 
 private const val TAG = "BatteryStateNotifier"
 private const val ID = 666
-private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
\ No newline at end of file
+private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
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 49be648..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,6 +15,10 @@
  */
 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.mapIconSets;
+
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
@@ -22,10 +26,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings.Global;
-import android.telephony.Annotation;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthCdma;
-import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
@@ -37,38 +39,37 @@
 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 com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
 
-
-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;
     private final String mNetworkNameSeparator;
     private final ContentObserver mObserver;
-    @VisibleForTesting
-    final PhoneStateListener mPhoneStateListener;
     // 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
@@ -83,6 +84,9 @@
     private Config mConfig;
     @VisibleForTesting
     boolean mInflateSignalStrengths = false;
+    private MobileStatusTracker.Callback mCallback;
+    @VisibleForTesting
+    MobileStatusTracker mMobileStatusTracker;
 
     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
     // need listener lists anymore.
@@ -93,18 +97,17 @@
         super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
                 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
                 networkController);
-        mNetworkToIconLookup = new HashMap<>();
         mConfig = config;
         mPhone = phone;
         mDefaults = defaults;
         mSubscriptionInfo = info;
-        mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post);
         mNetworkNameSeparator = getTextIfExists(R.string.status_bar_network_name_separator)
                 .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;
@@ -112,20 +115,38 @@
         mLastState.networkNameData = mCurrentState.networkNameData = networkName;
         mLastState.enabled = mCurrentState.enabled = hasMobileData;
         mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
-        // Get initial data sim state.
-        updateDataSim();
         mObserver = new ContentObserver(new Handler(receiverLooper)) {
             @Override
             public void onChange(boolean selfChange) {
                 updateTelephony();
             }
         };
+        mCallback = new MobileStatusTracker.Callback() {
+            @Override
+            public void onMobileStatusChanged(boolean updateTelephony,
+                    MobileStatusTracker.MobileStatus mobileStatus) {
+                if (Log.isLoggable(mTag, Log.DEBUG)) {
+                    Log.d(mTag, "onMobileStatusChanged="
+                            + " updateTelephony=" + updateTelephony
+                            + " mobileStatus=" + mobileStatus.toString());
+                }
+                updateMobileStatus(mobileStatus);
+                if (updateTelephony) {
+                    updateTelephony();
+                } else {
+                    notifyListenersIfNecessary();
+                }
+            }
+        };
+        mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper,
+                info, mDefaults, mCallback);
     }
 
     public void setConfiguration(Config config) {
         mConfig = config;
         updateInflateSignalStrength();
-        mapIconSets();
+        mNetworkToIconLookup = mapIconSets(mConfig);
+        mDefaultIcons = getDefaultIcons(mConfig);
         updateTelephony();
     }
 
@@ -157,15 +178,7 @@
      * Start listening for phone state changes.
      */
     public void registerListener() {
-        mPhone.listen(mPhoneStateListener,
-                PhoneStateListener.LISTEN_SERVICE_STATE
-                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                        | PhoneStateListener.LISTEN_CALL_STATE
-                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                        | PhoneStateListener.LISTEN_DATA_ACTIVITY
-                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE
-                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE
-                        | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED);
+        mMobileStatusTracker.setListening(true);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
                 true, mObserver);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(
@@ -177,145 +190,10 @@
      * Stop listening for phone state changes.
      */
     public void unregisterListener() {
-        mPhone.listen(mPhoneStateListener, 0);
+        mMobileStatusTracker.setListening(false);
         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 String getIconKey() {
-        if (mTelephonyDisplayInfo.getOverrideNetworkType()
-                == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
-            return toIconKey(mTelephonyDisplayInfo.getNetworkType());
-        } else {
-            return toDisplayIconKey(mTelephonyDisplayInfo.getOverrideNetworkType());
-        }
-    }
-
-    private String toIconKey(@Annotation.NetworkType int networkType) {
-        return Integer.toString(networkType);
-    }
-
-    private String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) {
-        switch (displayNetworkType) {
-            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA:
-                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA";
-            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO:
-                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus";
-            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA:
-                return toIconKey(TelephonyManager.NETWORK_TYPE_NR);
-            case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE:
-                return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus";
-            default:
-                return "unsupported";
-        }
-    }
-
     private void updateInflateSignalStrength() {
         mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
                 mSubscriptionInfo.getSubscriptionId());
@@ -361,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
@@ -385,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;
@@ -397,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);
     }
 
@@ -521,13 +399,24 @@
         return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
     }
 
+    private void updateMobileStatus(MobileStatusTracker.MobileStatus mobileStatus) {
+        mCurrentState.activityIn = mobileStatus.activityIn;
+        mCurrentState.activityOut = mobileStatus.activityOut;
+        mCurrentState.dataSim = mobileStatus.dataSim;
+        mCurrentState.carrierNetworkChangeMode = mobileStatus.carrierNetworkChangeMode;
+        mDataState = mobileStatus.dataState;
+        mServiceState = mobileStatus.serviceState;
+        mSignalStrength = mobileStatus.signalStrength;
+        mTelephonyDisplayInfo = mobileStatus.telephonyDisplayInfo;
+    }
+
     /**
      * Updates the current state based on mServiceState, mSignalStrength, mDataState,
      * mTelephonyDisplayInfo, and mSimState.  It should be called any time one of these is updated.
      * This will call listeners if necessary.
      */
     private final void updateTelephony() {
-        if (DEBUG) {
+        if (Log.isLoggable(mTag, Log.DEBUG)) {
             Log.d(mTag, "updateTelephonySignalStrength: hasService=" +
                     Utils.isInService(mServiceState) + " ss=" + mSignalStrength
                     + " displayInfo=" + mTelephonyDisplayInfo);
@@ -542,7 +431,7 @@
             }
         }
 
-        String iconKey = getIconKey();
+        String iconKey = getIconKey(mTelephonyDisplayInfo);
         if (mNetworkToIconLookup.get(iconKey) != null) {
             mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
         } else {
@@ -621,156 +510,4 @@
         pw.println("  mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
         pw.println("  isDataDisabled=" + isDataDisabled() + ",");
     }
-
-    class MobilePhoneStateListener extends PhoneStateListener {
-        public MobilePhoneStateListener(Executor executor) {
-            super(executor);
-        }
-
-        @Override
-        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            if (DEBUG) {
-                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
-                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
-            }
-            mSignalStrength = signalStrength;
-            updateTelephony();
-        }
-
-        @Override
-        public void onServiceStateChanged(ServiceState state) {
-            if (DEBUG) {
-                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState()
-                        + " dataState=" + state.getDataRegistrationState());
-            }
-            mServiceState = state;
-            updateTelephony();
-        }
-
-        @Override
-        public void onDataConnectionStateChanged(int state, int networkType) {
-            if (DEBUG) {
-                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
-                        + " type=" + networkType);
-            }
-            mDataState = state;
-            updateTelephony();
-        }
-
-        @Override
-        public void onDataActivity(int direction) {
-            if (DEBUG) {
-                Log.d(mTag, "onDataActivity: direction=" + direction);
-            }
-            setActivity(direction);
-        }
-
-        @Override
-        public void onCarrierNetworkChange(boolean active) {
-            if (DEBUG) {
-                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
-            }
-            mCurrentState.carrierNetworkChangeMode = active;
-            updateTelephony();
-        }
-
-        @Override
-        public void onActiveDataSubscriptionIdChanged(int subId) {
-            if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId);
-            updateDataSim();
-            updateTelephony();
-        }
-
-        @Override
-        public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
-            if (DEBUG) {
-                Log.d(mTag, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
-            }
-            mTelephonyDisplayInfo = telephonyDisplayInfo;
-            updateTelephony();
-        }
-    }
-
-    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 62b922e..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,6 +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;
@@ -391,7 +392,6 @@
                 }
             }
         });
-
         updateMobileControllers();
 
         // Initial setup of emergency information. Handled as if we had received a sticky broadcast
@@ -1201,59 +1201,4 @@
             registerListeners();
         }
     };
-
-    public static class SubscriptionDefaults {
-        public int getDefaultVoiceSubId() {
-            return SubscriptionManager.getDefaultVoiceSubscriptionId();
-        }
-
-        public int getDefaultDataSubId() {
-            return SubscriptionManager.getDefaultDataSubscriptionId();
-        }
-
-        public int getActiveDataSubId() {
-            return SubscriptionManager.getActiveDataSubscriptionId();
-        }
-    }
-
-    @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/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index e7f84a5..34c7881 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -102,8 +102,7 @@
         mHeightUpperLimit = NotificationUtils.getFontScaledHeight(mContext,
             R.dimen.smart_reply_button_max_height);
 
-        mCurrentBackgroundColor = context.getColor(R.color.smart_reply_button_background);
-        mDefaultBackgroundColor = mCurrentBackgroundColor;
+        mDefaultBackgroundColor = context.getColor(R.color.smart_reply_button_background);
         mDefaultTextColor = mContext.getColor(R.color.smart_reply_button_text);
         mDefaultTextColorDarkBg = mContext.getColor(R.color.smart_reply_button_text_dark_bg);
         mDefaultStrokeColor = mContext.getColor(R.color.smart_reply_button_stroke);
@@ -142,8 +141,9 @@
         mSingleToDoubleLineButtonWidthIncrease =
                 2 * (doubleLineButtonPaddingHorizontal - singleLineButtonPaddingHorizontal);
 
-
         mBreakIterator = BreakIterator.getLineInstance();
+
+        setBackgroundTintColor(mDefaultBackgroundColor);
         reallocateCandidateButtonQueueForSqueezing();
     }
 
@@ -182,7 +182,7 @@
     public void resetSmartSuggestions(View newSmartReplyContainer) {
         mSmartReplyContainer = newSmartReplyContainer;
         removeAllViews();
-        mCurrentBackgroundColor = mDefaultBackgroundColor;
+        setBackgroundTintColor(mDefaultBackgroundColor);
     }
 
     /** Add buttons to the {@link SmartReplyView} */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
deleted file mode 100644
index d9591cf..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class TelephonyIcons {
-    //***** Data connection icons
-    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;
-
-    static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
-            "CARRIER_NETWORK_CHANGE",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.carrier_network_change_mode,
-            0,
-            false);
-
-    static final MobileIconGroup THREE_G = new MobileIconGroup(
-            "3G",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_3g,
-            TelephonyIcons.ICON_3G,
-            true);
-
-    static final MobileIconGroup WFC = new MobileIconGroup(
-            "WFC",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            0, 0, false);
-
-    static final MobileIconGroup UNKNOWN = new MobileIconGroup(
-            "Unknown",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            0, 0, false);
-
-    static final MobileIconGroup E = new MobileIconGroup(
-            "E",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_edge,
-            TelephonyIcons.ICON_E,
-            false);
-
-    static final MobileIconGroup ONE_X = new MobileIconGroup(
-            "1X",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_cdma,
-            TelephonyIcons.ICON_1X,
-            true);
-
-    static final MobileIconGroup G = new MobileIconGroup(
-            "G",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_gprs,
-            TelephonyIcons.ICON_G,
-            false);
-
-    static final MobileIconGroup H = new MobileIconGroup(
-            "H",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_3_5g,
-            TelephonyIcons.ICON_H,
-            false);
-
-    static final MobileIconGroup H_PLUS = new MobileIconGroup(
-            "H+",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_3_5g_plus,
-            TelephonyIcons.ICON_H_PLUS,
-            false);
-
-    static final MobileIconGroup FOUR_G = new MobileIconGroup(
-            "4G",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_4g,
-            TelephonyIcons.ICON_4G,
-            true);
-
-    static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
-            "4G+",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0,0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_4g_plus,
-            TelephonyIcons.ICON_4G_PLUS,
-            true);
-
-    static final MobileIconGroup LTE = new MobileIconGroup(
-            "LTE",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_lte,
-            TelephonyIcons.ICON_LTE,
-            true);
-
-    static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
-            "LTE+",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_lte_plus,
-            TelephonyIcons.ICON_LTE_PLUS,
-            true);
-
-    static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
-            "5Ge",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_5ge_html,
-            TelephonyIcons.ICON_5G_E,
-            true);
-
-    static final MobileIconGroup NR_5G = new MobileIconGroup(
-            "5G",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0,
-            0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_5g,
-            TelephonyIcons.ICON_5G,
-            true);
-
-    static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
-            "5G_PLUS",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0,
-            0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.data_connection_5g_plus,
-            TelephonyIcons.ICON_5G_PLUS,
-            true);
-
-    static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
-            "DataDisabled",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.cell_data_off_content_description,
-            0,
-            false);
-
-    static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
-            "NotDefaultData",
-            null,
-            null,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            0,
-            0,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.not_default_data_content_description,
-            0,
-            false);
-
-    // When adding a new MobileIconGround, check if the dataContentDescription has to be filtered
-    // in QSCarrier#hasValidTypeContentDescription
-
-    /** Mapping icon name(lower case) to the icon object. */
-    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);
-        ICON_NAME_TO_ICON.put("3g", THREE_G);
-        ICON_NAME_TO_ICON.put("wfc", WFC);
-        ICON_NAME_TO_ICON.put("unknown", UNKNOWN);
-        ICON_NAME_TO_ICON.put("e", E);
-        ICON_NAME_TO_ICON.put("1x", ONE_X);
-        ICON_NAME_TO_ICON.put("g", G);
-        ICON_NAME_TO_ICON.put("h", H);
-        ICON_NAME_TO_ICON.put("h+", H_PLUS);
-        ICON_NAME_TO_ICON.put("4g", FOUR_G);
-        ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
-        ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
-        ICON_NAME_TO_ICON.put("lte", LTE);
-        ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
-        ICON_NAME_TO_ICON.put("5g", NR_5G);
-        ICON_NAME_TO_ICON.put("5g_plus", NR_5G_PLUS);
-        ICON_NAME_TO_ICON.put("datadisable", DATA_DISABLED);
-        ICON_NAME_TO_ICON.put("notdefaultdata", NOT_DEFAULT_DATA);
-    }
-}
-
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..d9f4744 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,16 +239,40 @@
     }
 
     /**
+     * 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];
 
         ColorUtils.RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hslMain);
         hslMain[0] /= 360f;
 
+        // To close to white or black, let's use the default system theme instead of
+        // applying a colorized one.
+        if (hslMain[2] < 0.05 || hslMain[2] > 0.95) {
+            return Color.TRANSPARENT;
+        }
+
         float minDistance = Float.MAX_VALUE;
         int closestColor = Color.TRANSPARENT;
         for (int candidate: candidates) {
@@ -281,7 +300,7 @@
         final String overlayPackageJson = mSecureSettings.getStringForUser(
                 Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
                 currentUser);
-        if (DEBUG) Log.d(TAG, "updateThemeOverlays: " + overlayPackageJson);
+        if (DEBUG) Log.d(TAG, "updateThemeOverlays. Setting: " + overlayPackageJson);
         boolean hasSystemPalette = false;
         boolean hasAccentColor = false;
         final Map<String, String> categoryToPackage = new ArrayMap<>();
@@ -330,6 +349,10 @@
         while (colorString.length() < 6) {
             colorString = "0" + colorString;
         }
+        // Remove alpha component
+        if (colorString.length() > 6) {
+            colorString = colorString.substring(colorString.length() - 6);
+        }
         return colorString;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
new file mode 100644
index 0000000..79a197d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java
@@ -0,0 +1,112 @@
+/*
+ * 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.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.drawable.DrawableWrapper;
+import android.util.AttributeSet;
+
+import com.android.systemui.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * An extension of {@link DrawableWrapper} that supports alpha and tint XML properties.
+ *
+ * {@link DrawableWrapper} supports setting these properties programmatically, but doesn't expose
+ * corresponding XML properties for some reason. This class allows to set these values in the XML,
+ * supporting theming.
+ *
+ * This class should only be used in XML.
+ *
+ * @attr ref android.R.styleable#DrawableWrapper_drawable
+ * @attr ref R.styleable#AlphaTintDrawableWrapper_tint
+ * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha
+ */
+public class AlphaTintDrawableWrapper extends DrawableWrapper {
+    private ColorStateList mTint;
+    private int[] mThemeAttrs;
+
+    /** No-arg constructor used by drawable inflation. */
+    public AlphaTintDrawableWrapper() {
+        super(null);
+    }
+
+    @Override
+    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+            @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws XmlPullParserException, IOException {
+        final TypedArray a = obtainAttributes(r, theme, attrs,
+                R.styleable.AlphaTintDrawableWrapper);
+
+        super.inflate(r, parser, attrs, theme);
+
+        mThemeAttrs = a.extractThemeAttrs();
+        updateStateFromTypedArray(a);
+        a.recycle();
+
+        applyTint();
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        super.applyTheme(t);
+
+        if (mThemeAttrs != null) {
+            final TypedArray a = t.resolveAttributes(mThemeAttrs,
+                    R.styleable.AlphaTintDrawableWrapper);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
+
+        // Ensure tint is reapplied after applying the theme to ensure this drawables'
+        // tint overrides the underlying drawables' tint.
+        applyTint();
+    }
+
+    @Override
+    public boolean canApplyTheme() {
+        return (mThemeAttrs != null && mThemeAttrs.length > 0) || super.canApplyTheme();
+    }
+
+    private void updateStateFromTypedArray(@NonNull TypedArray a) {
+        if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_drawable)) {
+            setDrawable(a.getDrawable(R.styleable.AlphaTintDrawableWrapper_android_drawable));
+        }
+        if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_tint)) {
+            mTint = a.getColorStateList(R.styleable.AlphaTintDrawableWrapper_android_tint);
+        }
+        if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_alpha)) {
+            float alpha = a.getFloat(R.styleable.AlphaTintDrawableWrapper_android_alpha, 1);
+            setAlpha(Math.round(alpha * 255));
+        }
+    }
+
+    private void applyTint() {
+        if (getDrawable() != null && mTint != null) {
+            getDrawable().mutate().setTintList(mTint);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
index 11c72c4..e44981e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -15,7 +15,6 @@
 package com.android.systemui.util.leak;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.view.Surface;
 
 public class RotationUtils {
@@ -26,30 +25,26 @@
     public static final int ROTATION_UPSIDE_DOWN = 3;
 
     public static int getRotation(Context context) {
-        Configuration config = context.getResources().getConfiguration();
         int rot = context.getDisplay().getRotation();
-        if (config.smallestScreenWidthDp < 600) {
-            if (rot == Surface.ROTATION_90) {
-                return ROTATION_LANDSCAPE;
-            } else if (rot == Surface.ROTATION_270) {
-                return ROTATION_SEASCAPE;
-            }
+        if (rot == Surface.ROTATION_90) {
+            return ROTATION_LANDSCAPE;
+        } else if (rot == Surface.ROTATION_270) {
+            return ROTATION_SEASCAPE;
+        } else {
+            return ROTATION_NONE;
         }
-        return ROTATION_NONE;
     }
 
     public static int getExactRotation(Context context) {
-        Configuration config = context.getResources().getConfiguration();
         int rot = context.getDisplay().getRotation();
-        if (config.smallestScreenWidthDp < 600) {
-            if (rot == Surface.ROTATION_90) {
-                return ROTATION_LANDSCAPE;
-            } else if (rot == Surface.ROTATION_270) {
-                return ROTATION_SEASCAPE;
-            } else if (rot == Surface.ROTATION_180) {
-                return ROTATION_UPSIDE_DOWN;
-            }
+        if (rot == Surface.ROTATION_90) {
+            return ROTATION_LANDSCAPE;
+        } else if (rot == Surface.ROTATION_270) {
+            return ROTATION_SEASCAPE;
+        } else if (rot == Surface.ROTATION_180) {
+            return ROTATION_UPSIDE_DOWN;
+        } else {
+            return ROTATION_NONE;
         }
-        return ROTATION_NONE;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 735338f..df54eab 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -259,6 +259,7 @@
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mWindow.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY);
         mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
         WindowManager.LayoutParams lp = mWindow.getAttributes();
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 a879a1e..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,
@@ -168,6 +168,11 @@
 
         mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
             @Override
+            public void onConfigChanged(Configuration newConfig) {
+                pip.onConfigurationChanged(newConfig);
+            }
+
+            @Override
             public void onDensityOrFontScaleChanged() {
                 pip.onDensityOrFontScaleChanged();
             }
@@ -185,7 +190,7 @@
     }
 
     @VisibleForTesting
-    void initSplitScreen(SplitScreen splitScreen) {
+    void initSplitScreen(LegacySplitScreen legacySplitScreen) {
         mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() {
             @Override
             public void onKeyguardVisibilityChanged(boolean showing) {
@@ -193,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 71a883d..bcb2a8c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -34,9 +34,11 @@
 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;
+import com.android.wm.shell.Transitions;
 import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.apppairs.AppPairs;
 import com.android.wm.shell.bubbles.BubbleController;
@@ -56,8 +58,6 @@
 import com.android.wm.shell.draganddrop.DragAndDropController;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
-import com.android.wm.shell.letterbox.LetterboxConfigController;
-import com.android.wm.shell.letterbox.LetterboxTaskListener;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.pip.Pip;
@@ -66,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;
@@ -170,17 +170,17 @@
     static ShellInit provideShellInit(DisplayImeController displayImeController,
             DragAndDropController dragAndDropController,
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<AppPairs> appPairsOptional,
-            LetterboxTaskListener letterboxTaskListener,
-            FullscreenTaskListener fullscreenTaskListener) {
+            FullscreenTaskListener fullscreenTaskListener,
+            Transitions transitions) {
         return new ShellInit(displayImeController,
                 dragAndDropController,
                 shellTaskOrganizer,
-                splitScreenOptional,
+                legacySplitScreenOptional,
                 appPairsOptional,
-                letterboxTaskListener,
-                fullscreenTaskListener);
+                fullscreenTaskListener,
+                transitions);
     }
 
     /**
@@ -191,15 +191,13 @@
     @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,
-            LetterboxConfigController letterboxConfigController) {
-        return Optional.of(new ShellCommandHandler(shellTaskOrganizer, splitScreenOptional,
-                pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional,
-                letterboxConfigController));
+            Optional<AppPairs> appPairsOptional) {
+        return Optional.of(new ShellCommandHandler(shellTaskOrganizer, legacySplitScreenOptional,
+                pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional));
     }
 
     @WMSingleton
@@ -278,12 +276,16 @@
 
     @WMSingleton
     @Provides
-    static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue,
-            @ShellMainThread ShellExecutor shellMainExecutor,
-            @ShellAnimationThread ShellExecutor shellAnimationExecutor,
-            TransactionPool transactionPool, Context context) {
-        return new ShellTaskOrganizer(syncQueue, transactionPool, shellMainExecutor,
-                shellAnimationExecutor, context);
+    static ShellTaskOrganizer provideShellTaskOrganizer(@ShellMainThread ShellExecutor mainExecutor,
+            Context context) {
+        return new ShellTaskOrganizer(mainExecutor, context);
+    }
+
+    @WMSingleton
+    @Provides
+    static RootTaskDisplayAreaOrganizer provideRootTaskDisplayAreaOrganizer(
+            @ShellMainThread ShellExecutor mainExecutor, Context context) {
+        return new RootTaskDisplayAreaOrganizer(mainExecutor);
     }
 
     @WMSingleton
@@ -293,7 +295,7 @@
     }
 
     @BindsOptionalOf
-    abstract SplitScreen optionalSplitScreen();
+    abstract LegacySplitScreen optionalLegacySplitScreen();
 
     @BindsOptionalOf
     abstract AppPairs optionalAppPairs();
@@ -317,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
@@ -338,16 +342,9 @@
 
     @WMSingleton
     @Provides
-    static LetterboxTaskListener provideLetterboxTaskListener(
-            SyncTransactionQueue syncQueue,
-            LetterboxConfigController letterboxConfigController,
-            WindowManager windowManager) {
-        return new LetterboxTaskListener(syncQueue, letterboxConfigController, windowManager);
-    }
-
-    @WMSingleton
-    @Provides
-    static LetterboxConfigController provideLetterboxConfigController(Context context) {
-        return new LetterboxConfigController(context);
+    static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
+            @ShellMainThread ShellExecutor mainExecutor,
+            @ShellAnimationThread ShellExecutor animExecutor) {
+        return new Transitions(organizer, pool, mainExecutor, animExecutor);
     }
 }
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/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index 1115043..96f3c15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -33,6 +33,7 @@
 
 import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -91,6 +92,7 @@
     private MagnificationModeSwitch mMagnificationModeSwitch;
     private View.OnTouchListener mTouchListener;
     private List<MotionEvent> mMotionEvents = new ArrayList<>();
+    private Runnable mFadeOutAnimation;
 
     @Before
     public void setUp() throws Exception {
@@ -119,6 +121,7 @@
             event.recycle();
         }
         mMotionEvents.clear();
+        mFadeOutAnimation = null;
     }
 
     @Test
@@ -143,6 +146,13 @@
     }
 
     @Test
+    public void showButton_excludeSystemGestureArea() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
+    }
+
+    @Test
     public void showMagnificationButton_setA11yTimeout_postDelayedAnimationWithA11yTimeout() {
         final int a11yTimeout = 12345;
         when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
@@ -157,15 +167,9 @@
     }
 
     @Test
-    public void showMagnificationButton_windowMode_verifyAnimationEndAction() {
-        // Execute the runnable immediately to run the animation.
-        doAnswer((invocation) -> {
-            final Runnable action = invocation.getArgument(0);
-            action.run();
-            return null;
-        }).when(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), anyLong());
-
+    public void showMagnificationButton_windowModeAndFadingOut_verifyAnimationEndAction() {
         mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        executeFadeOutAnimation();
 
         // Verify the end action after fade-out.
         final ArgumentCaptor<Runnable> endActionCaptor = ArgumentCaptor.forClass(Runnable.class);
@@ -178,14 +182,17 @@
     }
 
     @Test
-    public void onConfigurationChanged_buttonIsShowing_setImageResource() {
+    public void onConfigurationChanged_buttonIsShowing_updateResourcesAndLayout() {
         mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
         resetAndStubMockImageViewAndAnimator();
 
         mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
 
+        verify(mSpyImageView).setPadding(anyInt(), anyInt(), anyInt(), anyInt());
         verify(mSpyImageView).setImageResource(
                 getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+        verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any());
+        verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
     }
 
     @Test
@@ -197,9 +204,6 @@
         final long downTime = SystemClock.uptimeMillis();
         mTouchListener.onTouch(mSpyImageView,
                 obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
-
-        verify(mViewPropertyAnimator).cancel();
-
         resetAndStubMockImageViewAndAnimator();
         mTouchListener.onTouch(mSpyImageView,
                 obtainMotionEvent(downTime, downTime, ACTION_UP, 100, 100));
@@ -208,6 +212,31 @@
     }
 
     @Test
+    public void sendDownEvent_fullscreenMode_fadeOutAnimationIsNull() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+        resetAndStubMockImageViewAndAnimator();
+
+        final long downTime = SystemClock.uptimeMillis();
+        mTouchListener.onTouch(mSpyImageView,
+                obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
+
+        assertNull(mFadeOutAnimation);
+    }
+
+    @Test
+    public void sendDownEvent_fullscreenModeAndFadingOut_cancelAnimation() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+        executeFadeOutAnimation();
+        resetAndStubMockImageViewAndAnimator();
+
+        final long downTime = SystemClock.uptimeMillis();
+        mTouchListener.onTouch(mSpyImageView,
+                obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
+
+        verify(mViewPropertyAnimator).cancel();
+    }
+
+    @Test
     public void performDragging_showMagnificationButton_updateViewLayout() {
         mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
         resetAndStubMockImageViewAndAnimator();
@@ -219,7 +248,6 @@
         final long downTime = SystemClock.uptimeMillis();
         mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
                 downTime, 0, ACTION_DOWN, 100, 100));
-        verify(mViewPropertyAnimator).cancel();
 
         mTouchListener.onTouch(mSpyImageView,
                 obtainMotionEvent(downTime, downTime, ACTION_MOVE, 100 + offset,
@@ -368,7 +396,22 @@
     private void resetAndStubMockImageViewAndAnimator() {
         resetAndStubMockAnimator();
         Mockito.reset(mSpyImageView);
+        doAnswer(invocation -> {
+            final Runnable runnable = invocation.getArgument(0);
+            runnable.run();
+            return null;
+        }).when(mSpyImageView).post(any(Runnable.class));
         doReturn(mViewPropertyAnimator).when(mSpyImageView).animate();
+        doAnswer((invocation) -> {
+            mFadeOutAnimation = invocation.getArgument(0);
+            return null;
+        }).when(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), anyLong());
+        doAnswer((invocation) -> {
+            if (mFadeOutAnimation == invocation.getArgument(0)) {
+                mFadeOutAnimation = null;
+            }
+            return null;
+        }).when(mSpyImageView).removeCallbacks(any(Runnable.class));
     }
 
     private void resetAndStubMockAnimator() {
@@ -397,4 +440,10 @@
         mMotionEvents.add(event);
         return event;
     }
+
+    private void executeFadeOutAnimation() {
+        assertNotNull(mFadeOutAnimation);
+        mFadeOutAnimation.run();
+        mFadeOutAnimation = null;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index ade3290..02143a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -150,7 +150,7 @@
         mController.onOpActiveChanged(
                 AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mTestableLooper.processAllMessages();
         verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
                 TEST_UID, TEST_PACKAGE_NAME, true);
@@ -204,7 +204,8 @@
         mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
                 TEST_UID, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
-                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
+                AppOpsManager.MODE_ALLOWED);
         assertEquals(3, mController.getActiveAppOps().size());
     }
 
@@ -215,7 +216,8 @@
         mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
                 TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
-                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+                TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
+                AppOpsManager.MODE_ALLOWED);
         assertEquals(2,
                 mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
         assertEquals(1,
@@ -246,7 +248,7 @@
     public void opNotedScheduledForRemoval() {
         mController.setBGHandler(mMockHandler);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
     }
 
@@ -258,7 +260,7 @@
         mController.onOpActiveChanged(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                 true);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         assertFalse(mController.getActiveAppOps().isEmpty());
 
         mController.setListening(false);
@@ -272,9 +274,9 @@
         mController.setBGHandler(mMockHandler);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Only one post to notify subscribers
         verify(mMockHandler, times(1)).post(any());
@@ -288,9 +290,9 @@
         mController.setBGHandler(mMockHandler);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Only one post to notify subscribers
         verify(mMockHandler, times(2)).scheduleRemoval(any(), anyLong());
@@ -308,7 +310,7 @@
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         // Check that we "scheduled" the removal. Don't actually schedule until we are ready to
         // process messages at a later time.
@@ -337,7 +339,7 @@
         mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mController.onOpActiveChanged(
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -366,7 +368,7 @@
         mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mController.onOpActiveChanged(
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -384,7 +386,7 @@
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
 
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
-                AppOpsManager.MODE_ALLOWED);
+                AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
 
         mTestableLooper.processAllMessages();
         verify(mCallback).onActiveStateChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 19f0a15..8c547b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -20,6 +20,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyDouble;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -31,15 +33,19 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingDataProvider.GestureCompleteListener;
 import com.android.systemui.dock.DockManagerFake;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -62,16 +68,25 @@
     @Mock
     private FalsingClassifier mClassifierB;
     private final List<MotionEvent> mMotionEventList = new ArrayList<>();
+    @Mock
+    private HistoryTracker mHistoryTracker;
+    private FakeSystemClock mSystemClock = new FakeSystemClock();
+
+    private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, "");
+    private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult);
+        when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult);
         mClassifiers.add(mClassifierA);
         mClassifiers.add(mClassifierB);
         when(mFalsingDataProvider.isDirty()).thenReturn(true);
         when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
         mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager,
-                mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, false);
+                mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier,
+                mHistoryTracker, mSystemClock, false);
     }
 
     @Test
@@ -98,20 +113,20 @@
 
     @Test
     public void testIsFalseTouch_ClassifierARejects() {
-        when(mClassifierA.isFalseTouch()).thenReturn(true);
+        when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult);
         assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue();
     }
 
     @Test
     public void testIsFalseTouch_ClassifierBRejects() {
-        when(mClassifierB.isFalseTouch()).thenReturn(true);
+        when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult);
         assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue();
     }
 
     @Test
     public void testIsFalseTouch_FaceAuth() {
         // Even when the classifiers report a false, we should allow.
-        when(mClassifierA.isFalseTouch()).thenReturn(true);
+        when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult);
         when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
 
         assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
@@ -120,7 +135,7 @@
     @Test
     public void testIsFalseTouch_Docked() {
         // Even when the classifiers report a false, we should allow.
-        when(mClassifierA.isFalseTouch()).thenReturn(true);
+        when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult);
         mDockManager.setIsDocked(true);
 
         assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
@@ -128,37 +143,51 @@
 
     @Test
     public void testIsFalseTap_BasicCheck() {
-        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(false);
+        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult);
 
         assertThat(mBrightLineFalsingManager.isFalseTap(false)).isTrue();
 
-        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true);
+        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
 
         assertThat(mBrightLineFalsingManager.isFalseTap(false)).isFalse();
     }
 
     @Test
     public void testIsFalseTap_RobustCheck_NoFaceAuth() {
-        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true);
+        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
         mFalsingDataProvider.setJustUnlockedWithFace(false);
         assertThat(mBrightLineFalsingManager.isFalseTap(true)).isTrue();
     }
 
     @Test
     public void testIsFalseTap_RobustCheck_FaceAuth() {
-        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true);
+        when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
         when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
         assertThat(mBrightLineFalsingManager.isFalseTap(true)).isFalse();
     }
 
     @Test
     public void testIsFalseDoubleTap() {
-        when(mDoubleTapClassifier.isFalseTouch()).thenReturn(false);
+        when(mDoubleTapClassifier.classifyGesture()).thenReturn(mPassedResult);
 
         assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
 
-        when(mDoubleTapClassifier.isFalseTouch()).thenReturn(true);
+        when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalsedResult);
 
         assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue();
     }
+
+    @Test
+    public void testHistory() {
+        ArgumentCaptor<GestureCompleteListener> gestureCompleteListenerCaptor =
+                ArgumentCaptor.forClass(GestureCompleteListener.class);
+
+        verify(mFalsingDataProvider).addGestureCompleteListener(
+                gestureCompleteListenerCaptor.capture());
+
+        GestureCompleteListener gestureCompleteListener = gestureCompleteListenerCaptor.getValue();
+        gestureCompleteListener.onGestureComplete();
+
+        verify(mHistoryTracker).addResults(any(Collection.class), eq(mSystemClock.uptimeMillis()));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java
index 7659db8..dafc871 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java
@@ -69,93 +69,93 @@
     @Test
     public void testPass_UnknownAngle() {
         when(mDataProvider.getAngle()).thenReturn(Float.MAX_VALUE);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_VerticalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_MostlyVerticalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_BarelyVerticalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(
                 UP_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 DOWN_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_HorizontalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_MostlyHorizontalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_BarelyHorizontalSwipe() {
         when(mDataProvider.getAngle()).thenReturn(
                 RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getAngle()).thenReturn(
                 RIGHT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS * 2);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -163,12 +163,12 @@
         when(mDataProvider.getInteractionType()).thenReturn(LEFT_AFFORDANCE);
         when(mDataProvider.getAngle()).thenReturn(
                 RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.getInteractionType()).thenReturn(RIGHT_AFFORDANCE);
         when(mDataProvider.getAngle()).thenReturn(
                 LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         // This classifier may return false for other angles, but these are the only
         // two that actually matter, as affordances generally only travel in these two directions.
@@ -182,37 +182,37 @@
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.getAngle()).thenReturn(
                 RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.getAngle()).thenReturn(
                 UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.getAngle()).thenReturn(
                 LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.getAngle()).thenReturn(
                 DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         // Vertical Swipes
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.getAngle()).thenReturn(
                 RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.getAngle()).thenReturn(
                 UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
 
         when(mDataProvider.getAngle()).thenReturn(
                 LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.getAngle()).thenReturn(
                 DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
index 013fa36..f6c1424 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
@@ -51,32 +51,32 @@
 
     @Test
     public void testPass_noPointer() {
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
     public void testPass_fling() {
 
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendMoveEvent(1, 40));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendUpEvent(1, 80));
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testFail_flingShort() {
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendMoveEvent(1, 2));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendUpEvent(1, 10));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -84,26 +84,26 @@
         // These events, in testing, result in a fling that falls just short of the threshold.
 
         mClassifier.onTouchEvent(appendDownEvent(1, 1, 1));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendMoveEvent(1, 15, 2));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
         mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
         mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
         mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
     public void testPass_swipe() {
 
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3));
         mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300));
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java
index 4c4108a0..17c2700 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java
@@ -55,6 +55,9 @@
     private SingleTapClassifier mSingleTapClassifier;
     private DoubleTapClassifier mClassifier;
 
+    private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, "");
+    private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
+
     @Before
     public void setup() {
         super.setup();
@@ -77,17 +80,17 @@
 
     @Test
     public void testSingleTap() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
 
-        boolean result = mClassifier.isFalseTouch();
+        boolean result = mClassifier.classifyGesture().isFalse();
         assertThat("Single tap recognized as a valid double tap", result,  is(true));
     }
 
     @Test
     public void testDoubleTap() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult);
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
@@ -97,13 +100,13 @@
         addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP, TOUCH_SLOP);
         addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP);
 
-        boolean result = mClassifier.isFalseTouch();
-        assertThat(mClassifier.getReason(), result, is(false));
+        FalsingClassifier.Result result = mClassifier.classifyGesture();
+        assertThat(result.getReason(), result.isFalse(), is(false));
     }
 
     @Test
     public void testBadFirstTap() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(false, true);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult, mFalsedResult);
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
@@ -113,13 +116,13 @@
         addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
 
-        boolean result = mClassifier.isFalseTouch();
+        boolean result = mClassifier.classifyGesture().isFalse();
         assertThat("Bad first touch allowed", result, is(true));
     }
 
     @Test
     public void testBadSecondTap() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(true, false);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult, mPassedResult);
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
@@ -129,13 +132,13 @@
         addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
 
-        boolean result = mClassifier.isFalseTouch();
+        boolean result = mClassifier.classifyGesture().isFalse();
         assertThat("Bad second touch allowed", result, is(true));
     }
 
     @Test
     public void testBadTouchSlop() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
@@ -145,13 +148,13 @@
         addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP + 1, TOUCH_SLOP);
         addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP + 1);
 
-        boolean result = mClassifier.isFalseTouch();
+        boolean result = mClassifier.classifyGesture().isFalse();
         assertThat("Sloppy second touch allowed", result, is(true));
     }
 
     @Test
     public void testBadTouchSlow() {
-        when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+        when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
@@ -163,7 +166,7 @@
         addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 2,
                 MotionEvent.ACTION_UP, 1, 1);
 
-        boolean result = mClassifier.isFalseTouch();
+        boolean result = mClassifier.classifyGesture().isFalse();
         assertThat("Slow second tap allowed", result, is(true));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java
new file mode 100644
index 0000000..01cce35
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.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.systemui.classifier;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class HistoryTrackerTest extends SysuiTestCase {
+
+    private FakeSystemClock mSystemClock = new FakeSystemClock();
+
+    private HistoryTracker mHistoryTracker;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mHistoryTracker = new HistoryTracker(mSystemClock);
+    }
+
+    @Test
+    public void testNoDataNoPenalty() {
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
+    }
+
+    @Test
+    public void testOneResultFullConfidence() {
+        addResult(true, 1);
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
+    }
+
+    @Test
+    public void testMultipleResultsSameTimestamp() {
+        addResult(true, 1);
+        addResult(false, 1);
+
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.5);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.5);
+    }
+
+    @Test
+    public void testMultipleConfidences() {
+        addResult(true, 1);
+        addResult(true, 0);
+
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.75);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(.75);
+    }
+
+    @Test
+    public void testDecay() {
+        addResult(true, 1);
+
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
+
+        mSystemClock.advanceTime(1000);
+
+        assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.1);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
+    }
+
+    @Test
+    public void testMultipleResultsDifferentTimestamp() {
+        addResult(true, 1);
+        mSystemClock.advanceTime(1000);
+        addResult(false, .5);
+
+        assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.17);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.625);
+    }
+
+    @Test
+    public void testCompleteDecay() {
+        addResult(true, 1);
+
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
+
+        mSystemClock.advanceTime(2999);
+
+        assertThat(mHistoryTracker.falsePenalty()).isGreaterThan(0);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
+
+        mSystemClock.advanceTime(1);
+
+        assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
+        assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
+    }
+
+    private void addResult(boolean falsed, double confidence) {
+        mHistoryTracker.addResults(Collections.singletonList(
+                falsed
+                        ? FalsingClassifier.Result.falsed(confidence, "test")
+                        : FalsingClassifier.Result.passed(confidence)),
+                mSystemClock.uptimeMillis());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java
index ee289b5..76802f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java
@@ -50,13 +50,13 @@
 
     @Test
     public void testPass_noPointer() {
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_singlePointer() {
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -72,7 +72,7 @@
                 0, 0);
         mClassifier.onTouchEvent(motionEvent);
         motionEvent.recycle();
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -89,6 +89,6 @@
         mClassifier.onTouchEvent(motionEvent);
         motionEvent.recycle();
         getDataProvider().setInteractionType(QUICK_SETTINGS);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
index 38b025f..ba8ca9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java
@@ -50,12 +50,16 @@
     private DistanceClassifier mDistanceClassifier;
     private FalsingClassifier mClassifier;
 
+    private final FalsingClassifier.Result mFalsedResult =
+            FalsingClassifier.Result.falsed(1, "test");
+    private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
+
     @Before
     public void setup() {
         super.setup();
         MockitoAnnotations.initMocks(this);
         when(mDataProvider.getInteractionType()).thenReturn(GENERIC);
-        when(mDistanceClassifier.isLongSwipe()).thenReturn(false);
+        when(mDistanceClassifier.isLongSwipe()).thenReturn(mFalsedResult);
         mClassifier = new ProximityClassifier(
                 mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake());
     }
@@ -69,7 +73,7 @@
     public void testPass_uncovered() {
         touchDown();
         touchUp(10);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -78,7 +82,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 2));
         touchUp(20);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -88,7 +92,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -97,7 +101,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -108,7 +112,7 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 96));
         mClassifier.onProximityEvent(createSensorEvent(false, 100));
         touchUp(100);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -117,8 +121,8 @@
         mClassifier.onProximityEvent(createSensorEvent(true, 1));
         mClassifier.onProximityEvent(createSensorEvent(false, 11));
         touchUp(10);
-        when(mDistanceClassifier.isLongSwipe()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult);
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     private void touchDown() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java
index 941e12e..62c876f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java
@@ -70,14 +70,14 @@
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         mMotionEvents.clear();
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP + 2, 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
     }
 
@@ -86,14 +86,14 @@
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP);
 
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         mMotionEvents.clear();
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP + 2);
 
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
 
@@ -102,14 +102,14 @@
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP + 1, 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mMotionEvents.clear();
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP - 1, 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
     }
 
@@ -118,14 +118,14 @@
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         mMotionEvents.clear();
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP - 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -134,7 +134,7 @@
         addMotionEvent(0, 1, MotionEvent.ACTION_MOVE, 1, TOUCH_SLOP + 1);
         addMotionEvent(0, 2, MotionEvent.ACTION_UP, 1, 1);
 
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -142,12 +142,12 @@
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
 
-        assertThat(mClassifier.isTap(mMotionEvents), is(true));
+        assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(false));
 
         addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
         addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
 
-        assertThat(mClassifier.isTap(mMotionEvents), is(false));
+        assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(true));
 
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
index 6b9bb4f..4a896a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java
@@ -61,10 +61,10 @@
         when(mDataProvider.isUp()).thenReturn(false);
 
         when(mDataProvider.isRight()).thenReturn(false);  // right should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -73,11 +73,11 @@
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -87,10 +87,10 @@
         when(mDataProvider.isUp()).thenReturn(false);
 
         when(mDataProvider.isRight()).thenReturn(false);  // right should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -99,11 +99,11 @@
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -113,10 +113,10 @@
         when(mDataProvider.isUp()).thenReturn(false);
 
         when(mDataProvider.isRight()).thenReturn(false);  // right should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -125,11 +125,11 @@
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -139,19 +139,19 @@
 
         when(mDataProvider.isUp()).thenReturn(false);  // up and right should cause no effect.
         when(mDataProvider.isRight()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isUp()).thenReturn(true);
         when(mDataProvider.isRight()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isUp()).thenReturn(false);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isUp()).thenReturn(true);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -161,19 +161,19 @@
 
         when(mDataProvider.isUp()).thenReturn(false);  // up and right should cause no effect.
         when(mDataProvider.isRight()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isUp()).thenReturn(true);
         when(mDataProvider.isRight()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isUp()).thenReturn(false);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isUp()).thenReturn(true);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
 
@@ -185,10 +185,10 @@
 
 
         when(mDataProvider.isRight()).thenReturn(false);  // right should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -197,15 +197,15 @@
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -216,10 +216,10 @@
 
 
         when(mDataProvider.isRight()).thenReturn(false);  // right should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -228,15 +228,15 @@
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isVertical()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -247,10 +247,10 @@
 
 
         when(mDataProvider.isVertical()).thenReturn(false);  // vertical should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isVertical()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -259,15 +259,15 @@
 
         when(mDataProvider.isRight()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isRight()).thenReturn(true);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isRight()).thenReturn(false);
         when(mDataProvider.isUp()).thenReturn(false);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -278,10 +278,10 @@
 
 
         when(mDataProvider.isVertical()).thenReturn(false);  // vertical should cause no effect.
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         when(mDataProvider.isVertical()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -290,14 +290,14 @@
 
         when(mDataProvider.isUp()).thenReturn(true);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isUp()).thenReturn(false);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
 
         when(mDataProvider.isUp()).thenReturn(false);
         when(mDataProvider.isRight()).thenReturn(true);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
index 339dd9e..09bee12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
@@ -51,11 +51,11 @@
 
     @Test
     public void testPass_fewTouchesVertical() {
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
         appendMoveEvent(0, 0);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
         appendMoveEvent(0, 100);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -63,16 +63,16 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(0, 100);
         appendMoveEvent(0, 200);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
     public void testPass_fewTouchesHorizontal() {
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
         appendMoveEvent(0, 0);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
         appendMoveEvent(100, 0);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -80,7 +80,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 0);
         appendMoveEvent(200, 0);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
 
@@ -89,7 +89,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(0, 100);
         appendMoveEvent(0, 1);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -97,7 +97,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 0);
         appendMoveEvent(1, 0);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -105,7 +105,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(10, 10);
         appendMoveEvent(20, 20);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -115,7 +115,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(5, 100);
         appendMoveEvent(-5, 200);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -125,7 +125,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 5);
         appendMoveEvent(200, -5);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
     }
 
     @Test
@@ -135,7 +135,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(6, 10);
         appendMoveEvent(-6, 20);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -145,7 +145,7 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(10, 5);
         appendMoveEvent(20, -5);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -153,25 +153,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 5);
         appendMoveEvent(200, 10);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 0);
         appendMoveEvent(200, 10);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(100, -10);
         appendMoveEvent(200, 10);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(100, -10);
         appendMoveEvent(200, 50);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -179,25 +179,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(10, 50);
         appendMoveEvent(8, 100);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(1, 800);
         appendMoveEvent(2, 900);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-10, 600);
         appendMoveEvent(30, 700);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(40, 100);
         appendMoveEvent(0, 101);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -205,25 +205,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(-10, 50);
         appendMoveEvent(-24, 100);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-20, 800);
         appendMoveEvent(-20, 900);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(30, 600);
         appendMoveEvent(-10, 700);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-80, 100);
         appendMoveEvent(-10, 101);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -231,25 +231,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(-120, 10);
         appendMoveEvent(-200, 20);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-20, 8);
         appendMoveEvent(-40, 2);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-500, -2);
         appendMoveEvent(-600, 70);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-80, 100);
         appendMoveEvent(-100, 1);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -257,25 +257,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(-120, -10);
         appendMoveEvent(-200, -20);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-20, -8);
         appendMoveEvent(-40, -2);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-500, 2);
         appendMoveEvent(-600, -70);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-80, -100);
         appendMoveEvent(-100, -1);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -283,25 +283,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(-12, -20);
         appendMoveEvent(-20, -40);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-20, -130);
         appendMoveEvent(-40, -260);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(1, -100);
         appendMoveEvent(-6, -200);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-80, -100);
         appendMoveEvent(-10, -110);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -309,25 +309,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(12, -20);
         appendMoveEvent(20, -40);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(20, -130);
         appendMoveEvent(40, -260);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(-1, -100);
         appendMoveEvent(6, -200);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(80, -100);
         appendMoveEvent(10, -110);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
@@ -335,25 +335,25 @@
         appendMoveEvent(0, 0);
         appendMoveEvent(120, -20);
         appendMoveEvent(200, -40);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(200, -13);
         appendMoveEvent(400, -30);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(100, 10);
         appendMoveEvent(600, -20);
-        assertThat(mClassifier.isFalseTouch(), is(false));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(false));
 
         resetDataProvider();
         appendMoveEvent(0, 0);
         appendMoveEvent(80, -100);
         appendMoveEvent(100, -1);
-        assertThat(mClassifier.isFalseTouch(), is(true));
+        assertThat(mClassifier.classifyGesture().isFalse(), is(true));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 0059881..2320f4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -31,7 +31,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.AlarmManager;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.display.AmbientDisplayConfiguration;
@@ -65,8 +64,6 @@
 public class DozeSensorsTest extends SysuiTestCase {
 
     @Mock
-    private AlarmManager mAlarmManager;
-    @Mock
     private AsyncSensorManager mSensorManager;
     @Mock
     private DozeParameters mDozeParameters;
@@ -79,8 +76,6 @@
     @Mock
     private Consumer<Boolean> mProxCallback;
     @Mock
-    private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
-    @Mock
     private TriggerSensor mTriggerSensor;
     @Mock
     private DozeLog mDozeLog;
@@ -115,7 +110,7 @@
 
     @Test
     public void testSensorDebounce() {
-        mDozeSensors.setListening(true);
+        mDozeSensors.setListening(true, true);
 
         mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
         mTestableLooper.processAllMessages();
@@ -133,7 +128,7 @@
     @Test
     public void testSetListening_firstTrue_registerSettingsObserver() {
         verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
-        mDozeSensors.setListening(true);
+        mDozeSensors.setListening(true, true);
 
         verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
     }
@@ -141,8 +136,8 @@
     @Test
     public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() {
         verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
-        mDozeSensors.setListening(true);
-        mDozeSensors.setListening(true);
+        mDozeSensors.setListening(true, true);
+        mDozeSensors.setListening(true, true);
 
         verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 4bbba56..27187a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -154,6 +154,7 @@
 
         clearInvocations(mSensors);
         mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE);
+        mTriggers.transitionTo(DozeMachine.State.DOZE_PULSE_DONE, DozeMachine.State.DOZE_AOD);
         waitForSensorManager();
         verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index c897d8a..c00b394 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.media.MediaRouter2Manager;
 import android.media.session.MediaSessionManager;
 import android.os.Bundle;
 import android.testing.AndroidTestingRunner;
@@ -35,6 +36,7 @@
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
@@ -61,6 +63,8 @@
     private ActivityStarter mStarter = mock(ActivityStarter.class);
     private NotificationEntryManager mNotificationEntryManager =
             mock(NotificationEntryManager.class);
+    private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+    private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
 
     private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
     private MediaOutputController mMediaOutputController;
@@ -73,7 +77,7 @@
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouterManager);
         mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
                 mMediaOutputController);
         mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 0d352c1..c1a3994 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Icon;
 import android.media.MediaDescription;
 import android.media.MediaMetadata;
+import android.media.MediaRouter2Manager;
 import android.media.RoutingSessionInfo;
 import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
@@ -42,6 +43,7 @@
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.media.LocalMediaManager;
@@ -89,6 +91,8 @@
     private ActivityStarter mStarter = mock(ActivityStarter.class);
     private NotificationEntryManager mNotificationEntryManager =
             mock(NotificationEntryManager.class);
+    private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+    private final MediaRouter2Manager mRouter2Manager = mock(MediaRouter2Manager.class);
 
     private Context mSpyContext;
     private MediaOutputController mMediaOutputController;
@@ -111,7 +115,7 @@
 
         mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
         mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -155,7 +159,7 @@
     public void start_withoutPackageName_verifyMediaControllerInit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
 
         mMediaOutputController.start(mCb);
 
@@ -176,7 +180,7 @@
     public void stop_withoutPackageName_verifyMediaControllerDeinit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
 
         mMediaOutputController.start(mCb);
 
@@ -200,8 +204,10 @@
 
     @Test
     public void onSelectedDeviceStateChanged_verifyCallback() {
+        when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
         mMediaOutputController.start(mCb);
         reset(mCb);
+        mMediaOutputController.connectDevice(mMediaDevice1);
 
         mMediaOutputController.onSelectedDeviceStateChanged(mMediaDevice1,
                 LocalMediaManager.MediaDeviceState.STATE_CONNECTED);
@@ -221,8 +227,10 @@
 
     @Test
     public void onRequestFailed_verifyCallback() {
+        when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1);
         mMediaOutputController.start(mCb);
         reset(mCb);
+        mMediaOutputController.connectDevice(mMediaDevice2);
 
         mMediaOutputController.onRequestFailed(0 /* reason */);
 
@@ -268,6 +276,8 @@
 
     @Test
     public void connectDevice_verifyConnect() {
+        when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
+
         mMediaOutputController.connectDevice(mMediaDevice1);
 
         // Wait for background thread execution
@@ -441,7 +451,7 @@
     public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
 
         assertThat(mMediaOutputController.getNotificationIcon()).isNull();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index c1e7db1..e47a5e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -19,9 +19,12 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
 import android.media.session.MediaSessionManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -29,6 +32,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
@@ -53,26 +57,29 @@
     private static final String TEST_PACKAGE = "test_package";
 
     // Mock
-    private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
-    private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
-    private ShadeController mShadeController = mock(ShadeController.class);
-    private ActivityStarter mStarter = mock(ActivityStarter.class);
-    private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
-    private MediaDevice mMediaDevice = mock(MediaDevice.class);
-    private NotificationEntryManager mNotificationEntryManager =
+    private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
+    private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
+    private final ShadeController mShadeController = mock(ShadeController.class);
+    private final ActivityStarter mStarter = mock(ActivityStarter.class);
+    private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
+    private final MediaDevice mMediaDevice = mock(MediaDevice.class);
+    private final NotificationEntryManager mNotificationEntryManager =
             mock(NotificationEntryManager.class);
+    private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+    private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
 
     private MediaOutputDialog mMediaOutputDialog;
     private MediaOutputController mMediaOutputController;
-    private List<String> mFeatures = new ArrayList<>();
+    private final List<String> mFeatures = new ArrayList<>();
 
     @Before
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouterManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
-        mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController);
+        mMediaOutputDialog = new MediaOutputDialog(mContext, false,
+                mMediaOutputController, mUiEventLogger);
 
         when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice);
         when(mMediaDevice.getFeatures()).thenReturn(mFeatures);
@@ -112,4 +119,16 @@
         assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE);
     }
 
+    @Test
+    // Check the visibility metric logging by creating a new MediaOutput dialog,
+    // and verify if the calling times increases.
+    public void onCreate_ShouldLogVisibility() {
+        MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false,
+                mMediaOutputController, mUiEventLogger);
+
+        testDialog.dismissDialog();
+
+        verify(mUiEventLogger, times(2))
+                .log(MediaOutputDialog.MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index 5813350..6111099 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.media.MediaRouter2Manager;
 import android.media.session.MediaSessionManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -28,6 +29,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
@@ -62,6 +64,8 @@
     private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
     private NotificationEntryManager mNotificationEntryManager =
             mock(NotificationEntryManager.class);
+    private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+    private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
 
     private MediaOutputGroupDialog mMediaOutputGroupDialog;
     private MediaOutputController mMediaOutputController;
@@ -71,7 +75,7 @@
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager);
+                mNotificationEntryManager, mUiEventLogger, mRouterManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
                 mMediaOutputController);
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..644373c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -0,0 +1,389 @@
+/*
+ * 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.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+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;
+
+import android.app.Notification;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.database.Cursor;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+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;
+
+import java.util.Map;
+
+@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";
+    private static final String TEST_LOOKUP_KEY = "lookup_key";
+    private static final int TEST_COLUMN_INDEX = 1;
+    private static final Uri URI = Uri.parse("fake_uri");
+    private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
+    private static final Person PERSON = new Person.Builder()
+            .setName("name")
+            .setKey("abc")
+            .setUri(URI.toString())
+            .setBot(false)
+            .build();
+    private static final PeopleSpaceTile PERSON_TILE =
+            new PeopleSpaceTile
+                    .Builder(SHORTCUT_ID, "username", ICON, new Intent())
+                    .setNotificationKey(NOTIFICATION_KEY)
+                    .setNotificationContent(NOTIFICATION_CONTENT)
+                    .setNotificationDataUri(URI)
+                    .build();
+
+    private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
+            SHORTCUT_ID).setLongLabel(
+            "name").setPerson(PERSON)
+            .build();
+    private final ShortcutInfo mShortcutInfoWithoutPerson = new ShortcutInfo.Builder(mContext,
+            SHORTCUT_ID).setLongLabel(
+            "name")
+            .build();
+
+    @Mock
+    private NotificationListener mListenerService;
+    @Mock
+    private IAppWidgetService mIAppWidgetService;
+    @Mock
+    private AppWidgetManager mAppWidgetManager;
+    @Mock
+    private Cursor mMockCursor;
+    @Mock
+    private ContentResolver mMockContentResolver;
+    @Mock
+    private Context mMockContext;
+
+    @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, PERSON_TILE);
+
+        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());
+
+        when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+        when(mMockContentResolver.query(any(Uri.class), any(), anyString(), any(),
+                isNull())).thenReturn(mMockCursor);
+        when(mMockContext.getString(R.string.birthday_status)).thenReturn(
+                mContext.getString(R.string.birthday_status));
+    }
+
+    @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 testGetBackgroundTextFromMessageNoPunctuation() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test");
+
+        assertThat(backgroundText).isNull();
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageSingleExclamation() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test!");
+
+        assertThat(backgroundText).isNull();
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageSingleQuestion() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("?test");
+
+        assertThat(backgroundText).isNull();
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageSeparatedMarks() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test! right!");
+
+        assertThat(backgroundText).isNull();
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageDoubleExclamation() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("!!test");
+
+        assertThat(backgroundText).isEqualTo("!");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageDoubleQuestion() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test??");
+
+        assertThat(backgroundText).isEqualTo("?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageMixed() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test?!");
+
+        assertThat(backgroundText).isEqualTo("!?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageMixedInTheMiddle() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+                "test!? in the middle");
+
+        assertThat(backgroundText).isEqualTo("!?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageMixedDifferentOrder() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+                "test!? in the middle");
+
+        assertThat(backgroundText).isEqualTo("!?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageMultiple() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+                "test!?!!? in the middle");
+
+        assertThat(backgroundText).isEqualTo("!?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageQuestionFirst() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+                "test?? in the middle!!");
+
+        assertThat(backgroundText).isEqualTo("?");
+    }
+
+    @Test
+    public void testGetBackgroundTextFromMessageExclamationFirst() {
+        String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+                "test!! in the middle??");
+
+        assertThat(backgroundText).isEqualTo("!");
+    }
+
+    @Test
+    public void testGetLastMessagingStyleMessage() {
+        Notification notification = new Notification.Builder(mContext, "test")
+                .setContentTitle("TEST_TITLE")
+                .setContentText("TEST_TEXT")
+                .setShortcutId(SHORTCUT_ID)
+                .setStyle(new Notification.MessagingStyle(PERSON)
+                        .addMessage(new Notification.MessagingStyle.Message("text1", 0, PERSON))
+                        .addMessage(new Notification.MessagingStyle.Message("text2", 20, PERSON))
+                        .addMessage(new Notification.MessagingStyle.Message("text3", 10, PERSON))
+                )
+                .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", ICON, 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(URI);
+    }
+
+    @Test
+    public void testAugmentTileFromStorageWithoutNotification() {
+        PeopleSpaceTile tile =
+                new PeopleSpaceTile
+                        .Builder("id", "userName", ICON, 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);
+    }
+
+    @Test
+    public void testDoNotUpdateSingleConversationAppWidgetWhenNotBirthday() {
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+        when(mMockCursor.moveToNext()).thenReturn(true, false);
+        when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+        when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+        )).thenReturn(TEST_COLUMN_INDEX);
+
+        // Existing tile does not have birthday status.
+        Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+                new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
+                        mContext.getSystemService(LauncherApps.class)).build());
+        PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+                widgetIdToTile, widgetIdsArray);
+
+        verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any());
+    }
+
+    @Test
+    public void testUpdateSingleConversationAppWidgetWithoutPersonContactUriToRemoveBirthday() {
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+        when(mMockCursor.moveToNext()).thenReturn(true, false);
+        when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+        when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+        )).thenReturn(TEST_COLUMN_INDEX);
+
+        // Existing tile has a birthday status.
+        Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+                new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
+                        mContext.getSystemService(LauncherApps.class)).setStatusText(
+                        mContext.getString(R.string.birthday_status)).build());
+        PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+                widgetIdToTile, widgetIdsArray);
+
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any());
+    }
+
+    @Test
+    public void testUpdateSingleConversationAppWidgetToRemoveBirthdayWhenNoLongerBirthday() {
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+        Cursor mockPersonUriCursor = mock(Cursor.class);
+        Cursor mockBirthdaysUriCursor = mock(Cursor.class);
+        when(mockPersonUriCursor.moveToNext()).thenReturn(true, false);
+        when(mockBirthdaysUriCursor.moveToNext()).thenReturn(true, false);
+        when(mockBirthdaysUriCursor.getColumnIndex(
+                eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+        )).thenReturn(TEST_COLUMN_INDEX);
+        when(mockPersonUriCursor.getColumnIndex(
+                eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+        )).thenReturn(TEST_COLUMN_INDEX);
+        // Return different cursors based on the Uri queried.
+        when(mMockContentResolver.query(eq(URI), any(), any(), any(),
+                any())).thenReturn(mockPersonUriCursor);
+        when(mMockContentResolver.query(eq(ContactsContract.Data.CONTENT_URI), any(), any(), any(),
+                any())).thenReturn(mockBirthdaysUriCursor);
+        // Each cursor returns a different lookup key.
+        when(mockBirthdaysUriCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+        when(mockPersonUriCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(
+                TEST_LOOKUP_KEY + "differentlookup");
+
+        // Existing tile has a birthday status.
+        Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+                new PeopleSpaceTile.Builder(mShortcutInfo,
+                        mContext.getSystemService(LauncherApps.class)).setStatusText(
+                        mContext.getString(R.string.birthday_status)).build());
+        PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+                widgetIdToTile, widgetIdsArray);
+
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any());
+    }
+
+    @Test
+    public void testUpdateSingleConversationAppWidgetWhenBirthday() {
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+        when(mMockCursor.moveToNext()).thenReturn(true, false, true, false);
+        when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+        when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+        )).thenReturn(TEST_COLUMN_INDEX);
+
+        // Existing tile has a birthday status.
+        Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+                new PeopleSpaceTile.Builder(mShortcutInfo,
+                        mContext.getSystemService(LauncherApps.class)).setStatusText(
+                        mContext.getString(R.string.birthday_status)).build());
+        PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+                widgetIdToTile, widgetIdsArray);
+
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any());
+    }
+}
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 477fe63..df07b12 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;
@@ -29,18 +31,36 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.app.INotificationManager;
+import android.app.Notification;
 import android.app.NotificationChannel;
-import android.content.Context;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+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;
 
+import androidx.preference.PreferenceManager;
 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;
@@ -54,6 +74,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@@ -65,14 +88,41 @@
     private static final String TEST_CHANNEL_NAME = "channel_name";
     private static final String TEST_PARENT_CHANNEL_ID = "parent_channel_id";
     private static final String TEST_CONVERSATION_ID = "conversation_id";
+    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 static final Uri URI = Uri.parse("fake_uri");
+    private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
+    private static final Person PERSON = new Person.Builder()
+            .setName("name")
+            .setKey("abc")
+            .setUri(URI.toString())
+            .setBot(false)
+            .build();
+    private static final PeopleSpaceTile PERSON_TILE =
+            new PeopleSpaceTile
+                    .Builder(SHORTCUT_ID, "username", ICON, new Intent())
+                    .setNotificationKey(NOTIFICATION_KEY)
+                    .setNotificationContent(NOTIFICATION_CONTENT)
+                    .setNotificationDataUri(URI)
+                    .build();
 
     private PeopleSpaceWidgetManager mManager;
 
-    @Mock private NotificationListener mListenerService;
-    @Mock private IAppWidgetService mIAppWidgetService;
-    @Mock private Context mContext;
+    @Mock
+    private NotificationListener mListenerService;
+    @Mock
+    private IAppWidgetService mIAppWidgetService;
+    @Mock
+    private AppWidgetManager mAppWidgetManager;
+    @Mock
+    private INotificationManager mINotificationManager;
 
-    @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor;
+    @Captor
+    private ArgumentCaptor<NotificationHandler> mListenerCaptor;
 
     private final NoManSimulator mNoMan = new NoManSimulator();
     private final FakeSystemClock mClock = new FakeSystemClock();
@@ -80,17 +130,29 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
         mManager =
                 new PeopleSpaceWidgetManager(mContext);
-        mManager.setAppWidgetManager(mIAppWidgetService);
+        mManager.setAppWidgetManager(mIAppWidgetService, mAppWidgetManager, mINotificationManager);
         mManager.attach(mListenerService);
 
         verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
         NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
         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.apply();
+        Bundle options = new Bundle();
+        options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
+
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
+                .thenReturn(options);
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
+                .thenReturn(new Bundle());
+    }
 
     @Test
     public void testDoNotNotifyAppWidgetIfNoWidgets() throws RemoteException {
@@ -103,9 +165,24 @@
                         .setPkg(TEST_PACKAGE_A));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
+    }
 
+    @Test
+    public void testDoNotNotifySingleConversationAppWidgetIfNoWidgets() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        int[] widgetIdsArray = {};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        NotifEvent notif1 = mNoMan.postNotif(
+                new NotificationEntryBuilder()
+                        .setId(0)
+                        .setPkg(TEST_PACKAGE_A));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any(RemoteViews.class));
+        verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
     }
 
     @Test
@@ -119,10 +196,58 @@
                         .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(),
+                any(RemoteViews.class));
+    }
 
+    @Test
+    public void testNotifySingleConversationAppWidgetOnceIfNotificationPosted()
+            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);
+
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+
+        verify(mIAppWidgetService, never())
+                .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any(RemoteViews.class));
+        verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT),
+                any(RemoteViews.class));
+    }
+
+    @Test
+    public void testNotifySingleConversationAppWidgetTwiceIfTwoNotificationsPosted()
+            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);
+
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(4);
+        NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_B)
+                .setId(2));
+
+        verify(mIAppWidgetService, never())
+                .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
+        verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+                any(RemoteViews.class));
+        verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITHOUT_SHORTCUT),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -138,9 +263,10 @@
                 .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(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -154,9 +280,10 @@
         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(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -171,9 +298,9 @@
                 UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, never()).getAppWidgetIds(any());
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
-
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+                any(RemoteViews.class));
     }
 
     @Test
@@ -189,9 +316,145 @@
                 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<>();
+        ConversationChannelWrapper convo1 = new ConversationChannelWrapper();
+        convo1.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID).setLongLabel(
+                "name").build());
+        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(PERSON)
+                        .addMessage(new Notification.MessagingStyle.Message("text3", 10, PERSON))
+                )
+                .build();
+        return new SbnBuilder()
+                .setNotification(notification)
+                .build();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 3e83498..a8b3056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -343,6 +343,83 @@
         assertTrue(values[values.size - 1].contains(expected.toLog()))
     }
 
+    @Test
+    fun testListRequestedForAllUsers() {
+        privacyItemController.addCallback(callback)
+        executor.runAllReady()
+        verify(appOpsController).getActiveAppOpsForUser(UserHandle.USER_ALL)
+    }
+
+    @Test
+    fun testListFilterCurrentUser() {
+        val otherUser = CURRENT_USER_ID + 1
+        val otherUserUid = otherUser * UserHandle.PER_USER_RANGE
+        `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0)))
+
+        doReturn(listOf(
+                AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
+                AppOpItem(AppOpsManager.OP_CAMERA, otherUserUid, TEST_PACKAGE_NAME, 0))
+        ).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+        privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
+        executor.runAllReady()
+
+        privacyItemController.addCallback(callback)
+        executor.runAllReady()
+
+        verify(callback).onPrivacyItemsChanged(capture(argCaptor))
+
+        assertEquals(1, argCaptor.value.size)
+        assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType)
+        assertEquals(otherUserUid, argCaptor.value[0].application.uid)
+    }
+
+    @Test
+    fun testAlwaysGetPhoneCameraOps() {
+        val otherUser = CURRENT_USER_ID + 1
+        `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0)))
+
+        doReturn(listOf(
+                AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
+                AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0),
+                AppOpItem(AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0))
+        ).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+        privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
+        executor.runAllReady()
+
+        privacyItemController.addCallback(callback)
+        executor.runAllReady()
+
+        verify(callback).onPrivacyItemsChanged(capture(argCaptor))
+
+        assertEquals(1, argCaptor.value.size)
+        assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType)
+    }
+
+    @Test
+    fun testAlwaysGetPhoneMicOps() {
+        val otherUser = CURRENT_USER_ID + 1
+        `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0)))
+
+        doReturn(listOf(
+                AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
+                AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0),
+                AppOpItem(AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, 0))
+        ).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+        privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
+        executor.runAllReady()
+
+        privacyItemController.addCallback(callback)
+        executor.runAllReady()
+
+        verify(callback).onPrivacyItemsChanged(capture(argCaptor))
+
+        assertEquals(1, argCaptor.value.size)
+        assertEquals(PrivacyType.TYPE_MICROPHONE, argCaptor.value[0].privacyType)
+    }
+
     private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
     private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value)
 
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/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 2374b82..6759c90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -43,6 +43,7 @@
 
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -175,10 +176,11 @@
         data.finisher = null;
         data.mActionsReadyListener = null;
         SaveImageInBackgroundTask task =
-                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+                        ShareTransition::new);
 
         Notification.Action shareAction = task.createShareAction(mContext, mContext.getResources(),
-                Uri.parse("Screenshot_123.png"));
+                Uri.parse("Screenshot_123.png")).get().shareAction;
 
         Intent intent = shareAction.actionIntent.getIntent();
         assertNotNull(intent);
@@ -202,7 +204,8 @@
         data.finisher = null;
         data.mActionsReadyListener = null;
         SaveImageInBackgroundTask task =
-                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+                        ShareTransition::new);
 
         Notification.Action editAction = task.createEditAction(mContext, mContext.getResources(),
                 Uri.parse("Screenshot_123.png"));
@@ -229,7 +232,8 @@
         data.finisher = null;
         data.mActionsReadyListener = null;
         SaveImageInBackgroundTask task =
-                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+                new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+                        ShareTransition::new);
 
         Notification.Action deleteAction = task.createDeleteAction(mContext,
                 mContext.getResources(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 91144be..2c96535 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -74,6 +74,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -131,6 +132,7 @@
         MockitoAnnotations.initMocks(this);
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mTextView = new KeyguardIndicationTextView(mContext);
+        mTextView.setAnimationsEnabled(false);
 
         mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
         mContext.addMockSystemService(UserManager.class, mUserManager);
@@ -153,6 +155,11 @@
         mWakeLockBuilder.setWakeLock(mWakeLock);
     }
 
+    @After
+    public void tearDown() throws Exception {
+        mTextView.setAnimationsEnabled(true);
+    }
+
     private void createController() {
         if (Looper.myLooper() == null) {
             Looper.prepare();
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..d131dce 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;
 
@@ -35,11 +41,14 @@
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
+import android.util.Pair;
 
 import com.android.systemui.SysuiTestCase;
 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 +85,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 testGetFeedbackResources_settingDisabled() {
+        switchSetting(OFF);
+        Assert.assertEquals(new Pair(0, 0), mAssistantFeedbackController.getFeedbackResources(
+                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/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index b0e17cd..5fc01cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -629,10 +629,8 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 "action",
-                // TODO(b/174935104) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
+                    PendingIntent.FLAG_IMMUTABLE)).build();
     }
 
     private static class FakeNotificationLifetimeExtender implements NotificationLifetimeExtender {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 01b3d8e..241451e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -233,10 +233,8 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 title,
-                // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED))
+                    PendingIntent.FLAG_IMMUTABLE))
                 .setContextual(true)
                 .build();
     }
@@ -245,10 +243,8 @@
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 title,
-                // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
+                    PendingIntent.FLAG_IMMUTABLE)).build();
     }
 
     private ArrayList<Notification.Action> createActions(String... titles) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index d606316..60c3bc8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -476,10 +476,8 @@
 
     private NotificationEntry createBubble() {
         Notification.BubbleMetadata data = new Notification.BubbleMetadata.Builder(
-                // TODO(b/174970399) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 PendingIntent.getActivity(mContext, 0, new Intent(),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED),
+                    PendingIntent.FLAG_MUTABLE),
                         Icon.createWithResource(mContext.getResources(), R.drawable.android))
                 .build();
         Notification n = new Notification.Builder(getContext(), "a")
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..2e0827f 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
@@ -39,10 +39,12 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.util.Pair;
 import android.view.View;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -210,7 +212,7 @@
         // public notification is custom layout - no header
         mGroupRow.setSensitive(true, true);
         mGroupRow.setOnFeedbackClickListener(null);
-        mGroupRow.showFeedbackIcon(false);
+        mGroupRow.showFeedbackIcon(false, null);
     }
 
     @Test
@@ -224,11 +226,13 @@
         mGroupRow.setChildrenContainer(mockContainer);
 
         final boolean show = true;
-        mGroupRow.showFeedbackIcon(show);
+        final Pair<Integer, Integer> resIds = new Pair(R.drawable.ic_feedback_alerted,
+                R.string.notification_feedback_indicator_alerted);
+        mGroupRow.showFeedbackIcon(show, resIds);
 
-        verify(mockContainer, times(1)).showFeedbackIcon(show);
-        verify(privateLayout, times(1)).showFeedbackIcon(show);
-        verify(publicLayout, times(1)).showFeedbackIcon(show);
+        verify(mockContainer, times(1)).showFeedbackIcon(show, resIds);
+        verify(privateLayout, times(1)).showFeedbackIcon(show, resIds);
+        verify(publicLayout, times(1)).showFeedbackIcon(show, resIds);
     }
 
     @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 738ce53..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,18 +17,17 @@
 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;
 
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.eq;
@@ -56,6 +55,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -65,8 +65,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-
-import java.util.concurrent.CountDownLatch;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -78,18 +77,26 @@
     private FeedbackInfo mFeedbackInfo;
     private final PackageManager mMockPackageManager = mock(PackageManager.class);
     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
     private NotificationEntryManager mNotificationEntryManager;
     @Mock
     private IStatusBarService mStatusBarService;
+    @Mock
+    private NotificationGutsManager mNotificationGutsManager;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
 
         mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
         mDependency.injectTestDependency(IStatusBarService.class, mStatusBarService);
+        mDependency.injectTestDependency(NotificationGutsManager.class, mNotificationGutsManager);
 
         // Inflate the layout
         final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
@@ -108,13 +115,14 @@
 
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
+
     }
 
     @Test
     public void testBindNotification_SetsTextApplicationName() {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mAssistantFeedbackController);
         final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
         assertTrue(textView.getText().toString().contains("App Name"));
     }
@@ -125,66 +133,84 @@
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
                 .thenReturn(iconDrawable);
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mAssistantFeedbackController);
         final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
 
     @Test
-    public void testOk() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mock(AssistantFeedbackController.class));
-
-        final View okButton = mFeedbackInfo.findViewById(R.id.ok);
-        okButton.performClick();
-        assertEquals(1, latch.getCount());
-        verify(mGutsParent, times(1)).closeControls(any(), anyBoolean());
-    }
-
-    @Test
     public void testPrompt_silenced() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_LOW, RANKING_UNCHANGED), 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), 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), 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), 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());
+        assertEquals("This notification was automatically ranked lower in your shade. "
+                        + "Was this correct?", prompt.getText().toString());
     }
 
     @Test
-    public void testPrompt_demoted_ranking() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_DEFAULT, RANKING_DEMOTED), mock(AssistantFeedbackController.class));
-        TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was demoted by the system. Was this correct?",
-                prompt.getText());
+    public void testPositiveFeedback() {
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
+
+        final View yes = mFeedbackInfo.findViewById(R.id.yes);
+        yes.performClick();
+        verify(mGutsParent, times(1)).closeControls(yes, false);
+    }
+
+    @Test
+    public void testNegativeFeedback() {
+        when(mNotificationGutsManager.openGuts(
+                any(View.class),
+                anyInt(),
+                anyInt(),
+                any(NotificationMenuRowPlugin.MenuItem.class)))
+                .thenReturn(true);
+
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
+
+        final View no = mFeedbackInfo.findViewById(R.id.no);
+        no.performClick();
+        verify(mGutsParent, times(1)).closeControls(no, false);
+        verify(mNotificationGutsManager, times(1)).openGuts(
+                eq(mMockNotificationRow), eq(0), eq(0),
+                any());
     }
 
     private NotificationEntry getEntry(int oldImportance, int newImportance,
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 d08b2b7..4183508 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
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.util.Pair;
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
@@ -33,6 +34,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.R;
 import com.android.internal.widget.NotificationExpandButton;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.media.dialog.MediaOutputDialogFactory;
@@ -81,18 +83,22 @@
         View mockContracted = mock(NotificationHeaderView.class);
         when(mockContracted.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockContracted);
+        when(mockContracted.getContext()).thenReturn(mContext);
         View mockExpanded = mock(NotificationHeaderView.class);
         when(mockExpanded.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockExpanded);
+        when(mockExpanded.getContext()).thenReturn(mContext);
         View mockHeadsUp = mock(NotificationHeaderView.class);
         when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback))
                 .thenReturn(mockHeadsUp);
+        when(mockHeadsUp.getContext()).thenReturn(mContext);
 
         mView.setContractedChild(mockContracted);
         mView.setExpandedChild(mockExpanded);
         mView.setHeadsUpChild(mockHeadsUp);
 
-        mView.showFeedbackIcon(true);
+        mView.showFeedbackIcon(true, new Pair(R.drawable.ic_feedback_alerted,
+                R.string.notification_feedback_indicator_alerted));
 
         verify(mockContracted, times(1)).setVisibility(View.VISIBLE);
         verify(mockExpanded, times(1)).setVisibility(View.VISIBLE);
@@ -107,18 +113,21 @@
         when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockContractedEB);
+        when(mockContracted.getContext()).thenReturn(mContext);
 
         View mockExpandedEB = mock(NotificationExpandButton.class);
         View mockExpanded = mock(NotificationHeaderView.class);
         when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockExpandedEB);
+        when(mockExpanded.getContext()).thenReturn(mContext);
 
         View mockHeadsUpEB = mock(NotificationExpandButton.class);
         View mockHeadsUp = mock(NotificationHeaderView.class);
         when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class));
         when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                 mockHeadsUpEB);
+        when(mockHeadsUp.getContext()).thenReturn(mContext);
 
         // Set up all 3 child forms
         mView.setContractedChild(mockContracted);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 1387a63..291b223 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -213,11 +213,9 @@
                 notification, UserHandle.CURRENT, null, 0);
         mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build();
 
-        // TODO(b/175005650) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0,
                 new Intent(mContext, BubblesTestActivity.class),
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_MUTABLE);
         mBubbleSbn = new SbnBuilder(mSbn).setBubbleMetadata(
                 new Notification.BubbleMetadata.Builder(bubbleIntent,
                         Icon.createWithResource(mContext, R.drawable.android)).build())
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/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index c426c87..e3516f97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -14,8 +14,9 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
 import static android.provider.Settings.Global.SHOW_NEW_NOTIF_DISMISS;
+import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -33,6 +34,7 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.ViewUtils;
+import android.view.View;
 import android.view.ViewGroup;
 
 import androidx.test.filters.SmallTest;
@@ -54,12 +56,14 @@
 public class NotificationMenuRowTest extends LeakCheckedTest {
 
     private ExpandableNotificationRow mRow;
+    private View mView;
     private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     @Before
     public void setup() {
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
         mRow = mock(ExpandableNotificationRow.class);
+        mView = mock(View.class);
         mPeopleNotificationIdentifier = mock(PeopleNotificationIdentifier.class);
         NotificationEntry entry = new NotificationEntryBuilder().build();
         when(mRow.getEntry()).thenReturn(entry);
@@ -409,4 +413,61 @@
         row.setMenuAlpha(0.5f);
         assertTrue("when alpha is .5, menu is visible", row.isMenuVisible());
     }
+
+    @Test
+    public void testOnTouchMove() {
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
+        row.createMenu(mRow, null);
+        doReturn(50f).when(row).getDismissThreshold();
+        doReturn(true).when(row).canBeDismissed();
+        doReturn(mView).when(row).getMenuView();
+        row.onTouchMove(30f);
+
+        assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(0)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(60f);
+
+        assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(1)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(70f);
+
+        assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(1)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(30f);
+
+        assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(2)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(-30f);
+
+        assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(2)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(-60f);
+
+        assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(3)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(-70f);
+
+        assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(3)).performHapticFeedback(CLOCK_TICK);
+
+        row.onTouchMove(-30f);
+
+        assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+                row.isSnappingToDismiss());
+        verify(mView, times(4)).performHapticFeedback(CLOCK_TICK);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 43ba844..6fcc7fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -455,10 +455,8 @@
 
     private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
         Intent target = new Intent(mContext, BubblesTestActivity.class);
-        // TODO(b/175014468) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target,
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_MUTABLE);
 
         return new BubbleMetadata.Builder(bubbleIntent,
                         Icon.createWithResource(mContext, R.drawable.android))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 085bd90..93a9e59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
@@ -49,6 +50,7 @@
     public void setup() throws Exception {
         allowTestableLooperAsMainThread();
         mView = mock(View.class);
+        when(mView.getContext()).thenReturn(mContext);
         NotificationTestHelper helper = new NotificationTestHelper(
                 mContext,
                 mDependency,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index cb3e5e26..63bfd6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import static com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager.SMALL_CORNER_RADIUS;
+
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -139,7 +141,7 @@
                 createSection(null, null)
         });
         Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mSecond.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
@@ -166,8 +168,8 @@
 
         row.setHeadsUp(false);
         mRoundnessManager.updateView(entry.getRow(), false);
-        Assert.assertEquals(0f, row.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0f, row.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, row.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, row.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
@@ -177,7 +179,7 @@
                 createSection(null, mSecond)
         });
         Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mSecond.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
@@ -186,7 +188,7 @@
                 createSection(mFirst, mFirst),
                 createSection(mSecond, null)
         });
-        Assert.assertEquals(0.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mSecond.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mSecond.getCurrentTopRoundness(), 0.0f);
     }
 
@@ -196,7 +198,7 @@
                 createSection(mFirst, null),
                 createSection(null, null)
         });
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
 
@@ -206,8 +208,8 @@
                 createSection(mSecond, mSecond),
                 createSection(null, null)
         });
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
@@ -253,8 +255,8 @@
                 createSection(mSecond, mSecond),
                 createSection(null, null)
         });
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
@@ -303,8 +305,8 @@
         });
         mFirst.setHeadsUpAnimatingAway(true);
         mFirst.setHeadsUpAnimatingAway(false);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(SMALL_CORNER_RADIUS, mFirst.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 83ef87a..c7c1823 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
@@ -31,7 +30,6 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
 public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
 
     private static final int SCREEN_HEIGHT = 2000;
@@ -53,6 +51,7 @@
     private int mPreferredClockY;
     private boolean mHasCustomClock;
     private boolean mHasVisibleNotifs;
+    private float mQsExpansion;
 
     @Before
     public void setUp() {
@@ -355,6 +354,17 @@
     }
 
     @Test
+    public void clockHiddenWhenQsIsExpanded() {
+        // GIVEN on the lock screen with a custom clock and visible notifications
+        givenLockScreen();
+        mQsExpansion = 1;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+    }
+
+    @Test
     public void preferredCustomClockPositionWithVisibleNotificationsOnAod() {
         // GIVEN on the lock screen with a custom clock and visible notifications
         givenAOD();
@@ -384,7 +394,7 @@
         mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
                 mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
                 mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
-                0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */);
+                0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */, mQsExpansion);
         mClockPositionAlgorithm.run(mClockPosition);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
index 291c039..0e77504 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
@@ -26,6 +26,7 @@
 
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -40,13 +41,18 @@
     @Before
     public void setup() {
         mKeyguardIndicationTextView = new KeyguardIndicationTextView(mContext);
+        mKeyguardIndicationTextView.setAnimationsEnabled(false);
+    }
+
+    @After
+    public void tearDown() {
+        mKeyguardIndicationTextView.setAnimationsEnabled(true);
     }
 
     @Test
     public void switchIndication_null_hideIndication() {
         mKeyguardIndicationTextView.switchIndication(null /* text */);
 
-        assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE);
         assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("");
     }
 
@@ -54,7 +60,6 @@
     public void switchIndication_emptyText_hideIndication() {
         mKeyguardIndicationTextView.switchIndication("" /* text */);
 
-        assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE);
         assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("");
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
index aca3424..1ac7937 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
@@ -30,6 +30,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dock.DockManager;
@@ -80,6 +81,8 @@
     private Resources mResources;
     @Mock
     private HeadsUpManagerPhone mHeadsUpManagerPhone;
+    @Mock
+    private KeyguardSecurityModel mKeyguardSecurityModel;
 
     private LockscreenLockIconController mLockIconController;
     private OnAttachStateChangeListener mOnAttachStateChangeListener;
@@ -94,7 +97,7 @@
                 mShadeController, mAccessibilityController, mKeyguardIndicationController,
                 mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator,
                 mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources,
-                mHeadsUpManagerPhone);
+                mHeadsUpManagerPhone, mKeyguardSecurityModel);
 
         ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
                 ArgumentCaptor.forClass(OnAttachStateChangeListener.class);
@@ -139,6 +142,15 @@
         sBStateListenerCaptor.getValue().onDozingChanged(true);
 
         verify(mLockIcon).updateIconVisibility(false);
+    }
 
+    @Test
+    public void testVisibility_noBouncer() {
+        // no security (ie: no lock screen OR swipe to unlock)
+        when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
+                KeyguardSecurityModel.SecurityMode.None);
+
+        mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon);
+        verify(mLockIcon).updateIconVisibility(false);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index d4a94a1..d452861 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -199,6 +199,8 @@
     @Mock
     private AuthController mAuthController;
     @Mock
+    private ScrimController mScrimController;
+    @Mock
     private MediaDataManager mMediaDataManager;
 
     private NotificationPanelViewController mNotificationPanelViewController;
@@ -279,6 +281,7 @@
                 mNotificationAreaController,
                 mAuthController,
                 new QSDetailDisplayer(),
+                mScrimController,
                 mMediaDataManager);
         mNotificationPanelViewController.initDependencies(
                 mStatusBar,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index eaf31ed..342b2f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -249,6 +249,20 @@
     }
 
     @Test
+    public void transitionToShadeLocked() {
+        mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
+        finishAnimationsImmediately();
+
+        assertScrimAlpha(TRANSPARENT /* front */,
+                OPAQUE /* back */,
+                TRANSPARENT /* bubble */);
+
+        assertScrimTint(false /* front */,
+                false /* behind */,
+                false /* bubble */);
+    }
+
+    @Test
     public void transitionToOff() {
         mScrimController.transitionTo(ScrimState.OFF);
         finishAnimationsImmediately();
@@ -464,7 +478,7 @@
         // Front scrim should be transparent
         // Back scrim should be visible without tint
         assertScrimAlpha(TRANSPARENT /* front */,
-                SEMI_TRANSPARENT /* back */,
+                OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
 
         assertScrimTint(false /* front */,
@@ -478,7 +492,7 @@
         finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
-        assertScrimAlpha(SEMI_TRANSPARENT /* front */,
+        assertScrimAlpha(OPAQUE /* front */,
                 TRANSPARENT /* back */,
                 TRANSPARENT /* bubble */);
         assertScrimTint(false /* front */,
@@ -519,11 +533,11 @@
         Assert.assertEquals(ScrimController.TRANSPARENT,
                 mScrimInFront.getViewAlpha(), 0.0f);
         // Back scrim should be visible
-        Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA,
+        Assert.assertEquals(ScrimController.BUSY_SCRIM_ALPHA,
                 mScrimBehind.getViewAlpha(), 0.0f);
         // Bubble scrim should be visible
-        Assert.assertEquals(ScrimController.BLUR_SCRIM_ALPHA,
-                mScrimBehind.getViewAlpha(), 0.0f);
+        Assert.assertEquals(ScrimController.BUBBLE_SCRIM_ALPHA,
+                mScrimForBubble.getViewAlpha(), 0.0f);
     }
 
     @Test
@@ -564,6 +578,15 @@
     }
 
     @Test
+    public void qsExpansion() {
+        reset(mScrimBehind);
+        mScrimController.setQsExpansion(1f);
+        finishAnimationsImmediately();
+
+        assertScrimAlpha(TRANSPARENT, OPAQUE, TRANSPARENT);
+    }
+
+    @Test
     public void panelExpansionAffectsAlpha() {
         mScrimController.setPanelExpansion(0f);
         mScrimController.setPanelExpansion(0.5f);
@@ -888,7 +911,7 @@
         HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList(
                 ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER,
                 ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED,
-                ScrimState.BUBBLE_EXPANDED));
+                ScrimState.BUBBLE_EXPANDED, ScrimState.SHADE_LOCKED));
 
         for (ScrimState state : ScrimState.values()) {
             if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) {
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 5416f75..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,9 +148,10 @@
 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;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -244,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;
@@ -404,7 +405,7 @@
                 mCommandQueue,
                 mStatusBarComponentBuilderProvider,
                 mPluginManager,
-                Optional.of(mSplitScreen),
+                Optional.of(mLegacySplitScreen),
                 mLightsOutNotifController,
                 mStatusBarNotificationActivityStarterBuilder,
                 mShadeController,
@@ -886,6 +887,7 @@
         verify(mDozeServiceHost).setDozeSuppressed(false);
     }
 
+    @Ignore // TODO (b/175240607) - Figure out if the device will actually dial 911.
     @Test
     public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() {
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -896,7 +898,6 @@
         verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true));
         Intent sentIntent = intentCaptor.getValue();
         assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
-
     }
 
     public static class TestableNotificationInterruptStateProviderImpl extends
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index 23fa6fd..2577dbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -16,7 +16,11 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.os.BatteryManager.EXTRA_PRESENT;
+
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Intent;
@@ -31,6 +35,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -98,4 +103,36 @@
         Assert.assertFalse(mBatteryController.isAodPowerSave());
     }
 
+    @Test
+    public void testBatteryPresentState_notPresent() {
+        // GIVEN a battery state callback listening for changes
+        BatteryStateChangeCallback cb = mock(BatteryStateChangeCallback.class);
+        mBatteryController.addCallback(cb);
+
+        // WHEN the state of the battery becomes unknown
+        Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        i.putExtra(EXTRA_PRESENT, false);
+        mBatteryController.onReceive(getContext(), i);
+
+        // THEN the callback is notified
+        verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true);
+    }
+
+    @Test
+    public void testBatteryPresentState_callbackAddedAfterStateChange() {
+        // GIVEN a battery state callback
+        BatteryController.BatteryStateChangeCallback cb =
+                mock(BatteryController.BatteryStateChangeCallback.class);
+
+        // GIVEN the state has changed before adding a new callback
+        Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        i.putExtra(EXTRA_PRESENT, false);
+        mBatteryController.onReceive(getContext(), i);
+
+        // WHEN a callback is added
+        mBatteryController.addCallback(cb);
+
+        // THEN it is informed about the battery state
+        verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true);
+    }
 }
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 138236a..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 com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -225,7 +226,7 @@
         setDefaultSubId(mSubId);
         setSubscriptions(mSubId);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
-        mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
+        mPhoneStateListener = mMobileSignalController.mMobileStatusTracker.getPhoneStateListener();
 
         ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg =
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
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/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index c826cbc..d33fac0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -107,7 +107,7 @@
                 eq(UserHandle.USER_ALL));
         verify(mDumpManager).registerDumpable(any(), any());
 
-        List<Integer> colorList = List.of(Color.RED, Color.BLUE, 0x0CCCCC, 0x000111);
+        List<Integer> colorList = List.of(Color.RED, Color.BLUE, 0x0CCCCC, 0x000CCC);
         when(mThemeOverlayApplier.getAvailableAccentColors()).thenReturn(colorList);
         when(mThemeOverlayApplier.getAvailableSystemColors()).thenReturn(colorList);
     }
@@ -136,11 +136,9 @@
 
         // Assert that we received the colors that we were expecting
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
-                .isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE
-                        + Integer.toHexString(Color.RED).toUpperCase());
+                .isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE + "FF0000");
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_ACCENT_COLOR))
-                .isEqualTo(MONET_ACCENT_COLOR_PACKAGE
-                        + Integer.toHexString(Color.BLUE).toUpperCase());
+                .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "0000FF");
 
         // Should not ask again if changed to same value
         mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
@@ -148,10 +146,36 @@
     }
 
     @Test
+    public void onWallpaperColorsChanged_whiteTheme() {
+        WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.WHITE),
+                Color.valueOf(Color.BLUE), null);
+        mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+        ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
+
+        verify(mThemeOverlayApplier).applyCurrentUserOverlays(themeOverlays.capture(), any());
+
+        // Assert that we received the colors that we were expecting
+        assertThat(themeOverlays.getValue().containsKey(OVERLAY_CATEGORY_SYSTEM_PALETTE)).isFalse();
+    }
+
+    @Test
+    public void onWallpaperColorsChanged_blackTheme() {
+        WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.BLACK),
+                Color.valueOf(Color.BLUE), null);
+        mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+        ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
+
+        verify(mThemeOverlayApplier).applyCurrentUserOverlays(themeOverlays.capture(), any());
+
+        // Assert that we received the colors that we were expecting
+        assertThat(themeOverlays.getValue().containsKey(OVERLAY_CATEGORY_SYSTEM_PALETTE)).isFalse();
+    }
+
+    @Test
     public void onWallpaperColorsChanged_addsLeadingZerosToColors() {
         // Should ask for a new theme when wallpaper colors change
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(0x0CCCCC),
-                Color.valueOf(0x000111), null);
+                Color.valueOf(0x000CCC), null);
         mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
         ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
 
@@ -161,7 +185,7 @@
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
                 .isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE + "0CCCCC");
         assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_ACCENT_COLOR))
-                .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "000111");
+                .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "000CCC");
     }
 
     @Test
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/packages/Tethering/OWNERS b/packages/Tethering/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/Tethering/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/VpnDialogs/OWNERS b/packages/VpnDialogs/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/VpnDialogs/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/WAPPushManager/OWNERS b/packages/WAPPushManager/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/packages/WAPPushManager/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/packages/WallpaperBackup/OWNERS b/packages/WallpaperBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/packages/WallpaperBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 52a82dd..5ee30fb7 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -51,7 +51,6 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 
 public class WallpaperBackupAgent extends BackupAgent {
     private static final String TAG = "WallpaperBackup";
@@ -323,8 +322,7 @@
     private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
         Rect cropHint = new Rect();
         try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, StandardCharsets.UTF_8.name());
+            XmlPullParser parser = Xml.resolvePullParser(stream);
 
             int type;
             do {
@@ -351,8 +349,7 @@
     private ComponentName parseWallpaperComponent(File wallpaperInfo, String sectionTag) {
         ComponentName name = null;
         try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, StandardCharsets.UTF_8.name());
+            final XmlPullParser parser = Xml.resolvePullParser(stream);
 
             int type;
             do {
diff --git a/packages/WallpaperCropper/OWNERS b/packages/WallpaperCropper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/packages/WallpaperCropper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/packages/WindowManager/OWNERS b/packages/WindowManager/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/packages/WindowManager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
index 06cb33b..cd53227 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
@@ -54,4 +54,6 @@
          show. -->
     <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
 
+    <!-- If true, attach the navigation bar to the app during app transition -->
+    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
 </resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
index d5991f3..88cb74d79 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
@@ -54,4 +54,6 @@
          show. -->
     <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
 
+    <!-- If true, attach the navigation bar to the app during app transition -->
+    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
 </resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
index ff507ee..70c41d0 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
@@ -54,4 +54,6 @@
          show. -->
     <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
 
+    <!-- If true, attach the navigation bar to the app during app transition -->
+    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
 </resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
index 378756a..de26394 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
@@ -54,4 +54,6 @@
          show. -->
     <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
 
+    <!-- If true, attach the navigation bar to the app during app transition -->
+    <bool name="config_attachNavBarToAppDuringTransition">true</bool>
 </resources>
diff --git a/packages/overlays/OWNERS b/packages/overlays/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/packages/overlays/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/packages/services/PacProcessor/OWNERS b/packages/services/PacProcessor/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/services/PacProcessor/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/packages/services/Proxy/OWNERS b/packages/services/Proxy/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/packages/services/Proxy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/proto/src/OWNERS b/proto/src/OWNERS
new file mode 100644
index 0000000..e7ddf86
--- /dev/null
+++ b/proto/src/OWNERS
@@ -0,0 +1,2 @@
+per-file gnss.proto = file:/services/core/java/com/android/server/location/OWNERS
+per-file wifi.proto = file:/wifi/OWNERS
diff --git a/samples/training/network-usage/OWNERS b/samples/training/network-usage/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/samples/training/network-usage/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/Android.bp b/services/Android.bp
index 1101e2a..3447b5c 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -27,6 +27,7 @@
         ":services.print-sources",
         ":services.profcollect-sources",
         ":services.restrictions-sources",
+        ":services.searchui-sources",
         ":services.startop.iorap-sources",
         ":services.systemcaptions-sources",
         ":services.usage-sources",
@@ -72,6 +73,7 @@
         "services.print",
         "services.profcollect",
         "services.restrictions",
+        "services.searchui",
         "services.startop",
         "services.systemcaptions",
         "services.usage",
diff --git a/services/OWNERS b/services/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/services/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index de8a518..a2c7e4f 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -19,16 +19,15 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.util.Slog;
-import android.view.MagnificationSpec;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.IAccessibilityInteractionConnection;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * If we are stripping and/or replacing the actions from a window, we need to intercept the
@@ -41,10 +40,14 @@
     private final IAccessibilityInteractionConnectionCallback mServiceCallback;
     private final IAccessibilityInteractionConnection mConnectionWithReplacementActions;
     private final int mInteractionId;
+    private final int mNodeWithReplacementActionsInteractionId;
     private final Object mLock = new Object();
 
     @GuardedBy("mLock")
-    List<AccessibilityNodeInfo> mNodesWithReplacementActions;
+    private boolean mRequestForNodeWithReplacementActionFailed;
+
+    @GuardedBy("mLock")
+    AccessibilityNodeInfo mNodeWithReplacementActions;
 
     @GuardedBy("mLock")
     List<AccessibilityNodeInfo> mNodesFromOriginalWindow;
@@ -52,18 +55,8 @@
     @GuardedBy("mLock")
     AccessibilityNodeInfo mNodeFromOriginalWindow;
 
-    // Keep track of whether or not we've been called back for a single node
     @GuardedBy("mLock")
-    boolean mSingleNodeCallbackHappened;
-
-    // Keep track of whether or not we've been called back for multiple node
-    @GuardedBy("mLock")
-    boolean mMultiNodeCallbackHappened;
-
-    // We shouldn't get any more callbacks after we've called back the original service, but
-    // keep track to make sure we catch such strange things
-    @GuardedBy("mLock")
-    boolean mDone;
+    List<AccessibilityNodeInfo> mPrefetchedNodesFromOriginalWindow;
 
     public ActionReplacingCallback(IAccessibilityInteractionConnectionCallback serviceCallback,
             IAccessibilityInteractionConnection connectionWithReplacementActions,
@@ -71,19 +64,20 @@
         mServiceCallback = serviceCallback;
         mConnectionWithReplacementActions = connectionWithReplacementActions;
         mInteractionId = interactionId;
+        mNodeWithReplacementActionsInteractionId = interactionId + 1;
 
         // Request the root node of the replacing window
         final long identityToken = Binder.clearCallingIdentity();
         try {
             mConnectionWithReplacementActions.findAccessibilityNodeInfoByAccessibilityId(
-                    AccessibilityNodeInfo.ROOT_NODE_ID, null, interactionId + 1, this, 0,
+                    AccessibilityNodeInfo.ROOT_NODE_ID, null,
+                    mNodeWithReplacementActionsInteractionId, this, 0,
                     interrogatingPid, interrogatingTid, null, null);
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
             }
-            // Pretend we already got a (null) list of replacement nodes
-            mMultiNodeCallbackHappened = true;
+            mRequestForNodeWithReplacementActionFailed = true;
         } finally {
             Binder.restoreCallingIdentity(identityToken);
         }
@@ -91,46 +85,73 @@
 
     @Override
     public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId) {
-        boolean readyForCallback;
-        synchronized(mLock) {
+        synchronized (mLock) {
             if (interactionId == mInteractionId) {
                 mNodeFromOriginalWindow = info;
+            } else if (interactionId == mNodeWithReplacementActionsInteractionId) {
+                mNodeWithReplacementActions = info;
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
                 return;
             }
-
-            mSingleNodeCallbackHappened = true;
-            readyForCallback = mMultiNodeCallbackHappened;
         }
-        if (readyForCallback) {
-            replaceInfoActionsAndCallService();
-        }
+        replaceInfoActionsAndCallServiceIfReady();
     }
 
     @Override
     public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
             int interactionId) {
-        boolean callbackForSingleNode;
-        boolean callbackForMultipleNodes;
-        synchronized(mLock) {
+        synchronized (mLock) {
             if (interactionId == mInteractionId) {
                 mNodesFromOriginalWindow = infos;
-            } else if (interactionId == mInteractionId + 1) {
-                mNodesWithReplacementActions = infos;
+            } else if (interactionId == mNodeWithReplacementActionsInteractionId) {
+                setNodeWithReplacementActionsFromList(infos);
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
                 return;
             }
-            callbackForSingleNode = mSingleNodeCallbackHappened;
-            callbackForMultipleNodes = mMultiNodeCallbackHappened;
-            mMultiNodeCallbackHappened = true;
         }
-        if (callbackForSingleNode) {
+        replaceInfoActionsAndCallServiceIfReady();
+    }
+
+    @Override
+    public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos,
+                                                       int interactionId)
+            throws RemoteException {
+        synchronized (mLock) {
+            if (interactionId == mInteractionId) {
+                mPrefetchedNodesFromOriginalWindow = infos;
+            }  else {
+                Slog.e(LOG_TAG, "Callback with unexpected interactionId");
+                return;
+            }
+        }
+        replaceInfoActionsAndCallServiceIfReady();
+    }
+
+    private void replaceInfoActionsAndCallServiceIfReady() {
+        boolean originalAndReplacementCallsHaveHappened = false;
+        synchronized (mLock) {
+            originalAndReplacementCallsHaveHappened = mNodeWithReplacementActions != null
+                    && (mNodeFromOriginalWindow != null
+                    || mNodesFromOriginalWindow != null
+                    || mPrefetchedNodesFromOriginalWindow != null);
+            originalAndReplacementCallsHaveHappened
+                    |= mRequestForNodeWithReplacementActionFailed;
+        }
+        if (originalAndReplacementCallsHaveHappened) {
             replaceInfoActionsAndCallService();
-        }
-        if (callbackForMultipleNodes) {
             replaceInfosActionsAndCallService();
+            replacePrefetchInfosActionsAndCallService();
+        }
+    }
+
+    private void setNodeWithReplacementActionsFromList(List<AccessibilityNodeInfo> infos) {
+        for (int i = 0; i < infos.size(); i++) {
+            AccessibilityNodeInfo info = infos.get(i);
+            if (info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID) {
+                mNodeWithReplacementActions = info;
+            }
         }
     }
 
@@ -144,18 +165,10 @@
     private void replaceInfoActionsAndCallService() {
         final AccessibilityNodeInfo nodeToReturn;
         synchronized (mLock) {
-            if (mDone) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "Extra callback");
-                }
-                return;
-            }
             if (mNodeFromOriginalWindow != null) {
                 replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
             }
-            recycleReplaceActionNodesLocked();
             nodeToReturn = mNodeFromOriginalWindow;
-            mDone = true;
         }
         try {
             mServiceCallback.setFindAccessibilityNodeInfoResult(nodeToReturn, mInteractionId);
@@ -169,21 +182,7 @@
     private void replaceInfosActionsAndCallService() {
         final List<AccessibilityNodeInfo> nodesToReturn;
         synchronized (mLock) {
-            if (mDone) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "Extra callback");
-                }
-                return;
-            }
-            if (mNodesFromOriginalWindow != null) {
-                for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
-                    replaceActionsOnInfoLocked(mNodesFromOriginalWindow.get(i));
-                }
-            }
-            recycleReplaceActionNodesLocked();
-            nodesToReturn = (mNodesFromOriginalWindow == null)
-                    ? null : new ArrayList<>(mNodesFromOriginalWindow);
-            mDone = true;
+            nodesToReturn = replaceActionsLocked(mNodesFromOriginalWindow);
         }
         try {
             mServiceCallback.setFindAccessibilityNodeInfosResult(nodesToReturn, mInteractionId);
@@ -194,6 +193,31 @@
         }
     }
 
+    private void replacePrefetchInfosActionsAndCallService() {
+        final List<AccessibilityNodeInfo> nodesToReturn;
+        synchronized (mLock) {
+            nodesToReturn = replaceActionsLocked(mPrefetchedNodesFromOriginalWindow);
+        }
+        try {
+            mServiceCallback.setPrefetchAccessibilityNodeInfoResult(nodesToReturn, mInteractionId);
+        } catch (RemoteException re) {
+            if (DEBUG) {
+                Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult");
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private List<AccessibilityNodeInfo> replaceActionsLocked(List<AccessibilityNodeInfo> infos) {
+        if (infos != null) {
+            for (int i = 0; i < infos.size(); i++) {
+                replaceActionsOnInfoLocked(infos.get(i));
+            }
+        }
+        return (infos == null)
+                ? null : new ArrayList<>(infos);
+    }
+
     @GuardedBy("mLock")
     private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
         info.removeAllActions();
@@ -205,40 +229,22 @@
         info.setDismissable(false);
         // We currently only replace actions for the root node
         if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
-                && mNodesWithReplacementActions != null) {
-            // This list should always contain a single node with the root ID
-            for (int i = 0; i < mNodesWithReplacementActions.size(); i++) {
-                AccessibilityNodeInfo nodeWithReplacementActions =
-                        mNodesWithReplacementActions.get(i);
-                if (nodeWithReplacementActions.getSourceNodeId()
-                        == AccessibilityNodeInfo.ROOT_NODE_ID) {
-                    List<AccessibilityAction> actions = nodeWithReplacementActions.getActionList();
-                    if (actions != null) {
-                        for (int j = 0; j < actions.size(); j++) {
-                            info.addAction(actions.get(j));
-                        }
-                        // The PIP needs to be able to take accessibility focus
-                        info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
-                        info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
-                    }
-                    info.setClickable(nodeWithReplacementActions.isClickable());
-                    info.setFocusable(nodeWithReplacementActions.isFocusable());
-                    info.setContextClickable(nodeWithReplacementActions.isContextClickable());
-                    info.setScrollable(nodeWithReplacementActions.isScrollable());
-                    info.setLongClickable(nodeWithReplacementActions.isLongClickable());
-                    info.setDismissable(nodeWithReplacementActions.isDismissable());
+                && mNodeWithReplacementActions != null) {
+            List<AccessibilityAction> actions = mNodeWithReplacementActions.getActionList();
+            if (actions != null) {
+                for (int j = 0; j < actions.size(); j++) {
+                    info.addAction(actions.get(j));
                 }
+                // The PIP needs to be able to take accessibility focus
+                info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
+                info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
             }
+            info.setClickable(mNodeWithReplacementActions.isClickable());
+            info.setFocusable(mNodeWithReplacementActions.isFocusable());
+            info.setContextClickable(mNodeWithReplacementActions.isContextClickable());
+            info.setScrollable(mNodeWithReplacementActions.isScrollable());
+            info.setLongClickable(mNodeWithReplacementActions.isLongClickable());
+            info.setDismissable(mNodeWithReplacementActions.isDismissable());
         }
     }
-
-    @GuardedBy("mLock")
-    private void recycleReplaceActionNodesLocked() {
-        if (mNodesWithReplacementActions == null) return;
-        for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
-            AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
-            nodeWithReplacementAction.recycle();
-        }
-        mNodesWithReplacementActions = null;
-    }
 }
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/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 189a390..c7f0efa 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -99,7 +99,7 @@
          * The current magnification spec. If an animation is running, this
          * reflects the end state.
          */
-        private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
+        private final MagnificationSpec mCurrentMagnificationSpec = new MagnificationSpec();
 
         private final Region mMagnificationRegion = Region.obtain();
         private final Rect mMagnificationBounds = new Rect();
@@ -1227,13 +1227,11 @@
          * The magnification spec that was sent to the window manager. This should
          * only be accessed with the lock held.
          */
-        private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
+        private final MagnificationSpec mSentMagnificationSpec = new MagnificationSpec();
 
-        private final MagnificationSpec mStartMagnificationSpec = MagnificationSpec.obtain();
+        private final MagnificationSpec mStartMagnificationSpec = new MagnificationSpec();
 
-        private final MagnificationSpec mEndMagnificationSpec = MagnificationSpec.obtain();
-
-        private final MagnificationSpec mTmpMagnificationSpec = MagnificationSpec.obtain();
+        private final MagnificationSpec mEndMagnificationSpec = new MagnificationSpec();
 
         /**
          * The animator should only be accessed and modified on the main (e.g. animation) thread.
@@ -1335,15 +1333,16 @@
             synchronized (mLock) {
                 if (mEnabled) {
                     float fract = animation.getAnimatedFraction();
-                    mTmpMagnificationSpec.scale = mStartMagnificationSpec.scale
+                    MagnificationSpec magnificationSpec = new MagnificationSpec();
+                    magnificationSpec.scale = mStartMagnificationSpec.scale
                             + (mEndMagnificationSpec.scale - mStartMagnificationSpec.scale) * fract;
-                    mTmpMagnificationSpec.offsetX = mStartMagnificationSpec.offsetX
+                    magnificationSpec.offsetX = mStartMagnificationSpec.offsetX
                             + (mEndMagnificationSpec.offsetX - mStartMagnificationSpec.offsetX)
                             * fract;
-                    mTmpMagnificationSpec.offsetY = mStartMagnificationSpec.offsetY
+                    magnificationSpec.offsetY = mStartMagnificationSpec.offsetY
                             + (mEndMagnificationSpec.offsetY - mStartMagnificationSpec.offsetY)
                             * fract;
-                    setMagnificationSpecLocked(mTmpMagnificationSpec);
+                    setMagnificationSpecLocked(magnificationSpec);
                 }
             }
         }
diff --git a/services/api/OWNERS b/services/api/OWNERS
new file mode 100644
index 0000000..a609390
--- /dev/null
+++ b/services/api/OWNERS
@@ -0,0 +1,4 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
+
+# API changes are managed via Prolog rules, not OWNERS
+*
diff --git a/services/appprediction/OWNERS b/services/appprediction/OWNERS
new file mode 100644
index 0000000..3a5d23d
--- /dev/null
+++ b/services/appprediction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/appprediction/OWNERS
diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS
new file mode 100644
index 0000000..c52751d
--- /dev/null
+++ b/services/autofill/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/autofill/OWNERS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 33d13de..bc59602 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -29,8 +29,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -86,6 +84,7 @@
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.infra.AbstractPerUserSystemService;
 import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1638,19 +1637,16 @@
                 }
             }
 
-            final IActivityTaskManager atm = ActivityTaskManager.getService();
+            final ActivityTaskManagerInternal atmInternal = LocalServices.getService(
+                    ActivityTaskManagerInternal.class);
 
             // Only remove sessions which's activities are not known to the activity manager anymore
             for (int i = 0; i < numSessionsToRemove; i++) {
-                try {
-                    // The activity manager cannot resolve activities that have been removed
-                    if (atm.getActivityClassForToken(sessionsToRemove.valueAt(i)) != null) {
-                        sessionsToRemove.removeAt(i);
-                        i--;
-                        numSessionsToRemove--;
-                    }
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Cannot figure out if activity is finished", e);
+                // The activity task manager cannot resolve activities that have been removed.
+                if (atmInternal.getActivityName(sessionsToRemove.valueAt(i)) != null) {
+                    sessionsToRemove.removeAt(i);
+                    i--;
+                    numSessionsToRemove--;
                 }
             }
 
diff --git a/services/autofill/java/com/android/server/autofill/TEST_MAPPING b/services/autofill/java/com/android/server/autofill/TEST_MAPPING
index cf058ad..d8a6917 100644
--- a/services/autofill/java/com/android/server/autofill/TEST_MAPPING
+++ b/services/autofill/java/com/android/server/autofill/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     {
       "name": "CtsAutoFillServiceTestCases",
       "options": [
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ac6ed44..6c30999 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -512,7 +512,7 @@
         int callingUid = Binder.getCallingUid();
         if (CompatChanges.isChangeEnabled(
                 BackupManager.IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE, callingUid)) {
-            mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                     "isBackupServiceActive");
         }
         synchronized (mStateLock) {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 0a80b02..f3d0a2e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -18,6 +18,7 @@
 package com.android.server.companion;
 
 import static com.android.internal.util.CollectionUtils.emptyIfNull;
+import static com.android.internal.util.CollectionUtils.find;
 import static com.android.internal.util.CollectionUtils.forEach;
 import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
 import static com.android.internal.util.Preconditions.checkArgument;
@@ -40,6 +41,7 @@
 import android.companion.Association;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
+import android.companion.DeviceNotAssociatedException;
 import android.companion.ICompanionDeviceDiscoveryService;
 import android.companion.ICompanionDeviceManager;
 import android.companion.IFindDeviceCallback;
@@ -130,9 +132,6 @@
             CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
             ".DeviceDiscoveryService");
 
-    // 10 min
-    public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000;
-
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "CompanionDeviceManagerService";
 
@@ -486,6 +485,43 @@
                     a -> Objects.equals(a.getDeviceMacAddress(), macAddress));
         }
 
+        @Override
+        public void registerDevicePresenceListenerService(
+                String packageName, String deviceAddress)
+                throws RemoteException {
+            checkCanRegisterObserverService(packageName, deviceAddress);
+
+            //TODO(eugenesusla) implement
+        }
+
+        @Override
+        public void unregisterDevicePresenceListenerService(
+                String packageName, String deviceAddress)
+                throws RemoteException {
+            checkCanRegisterObserverService(packageName, deviceAddress);
+
+            //TODO(eugenesusla) implement
+        }
+
+        private void checkCanRegisterObserverService(String packageName, String deviceAddress)
+                throws RemoteException {
+            getContext().enforceCallingOrSelfPermission(
+                    android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE,
+                    "[un]registerDevicePresenceListenerService");
+            checkCallerIsSystemOr(packageName);
+
+            int userId = getCallingUserId();
+            Set<Association> deviceAssociations = CollectionUtils.filter(
+                    getAllAssociations(userId, packageName),
+                    association -> deviceAddress.equals(association.getDeviceMacAddress()));
+
+            if (deviceAssociations.isEmpty()) {
+                throw new RemoteException(new DeviceNotAssociatedException("App " + packageName
+                        + " is not associated with device " + deviceAddress
+                        + " for user " + userId));
+            }
+        }
+
         private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
             checkCallerIsSystemOr(callingPackage);
             int userId = getCallingUserId();
@@ -555,12 +591,45 @@
 
     void removeAssociation(int userId, String pkg, String deviceMacAddress) {
         updateAssociations(associations -> CollectionUtils.filter(associations, association -> {
-            return association.getUserId() != userId
+            boolean notMatch = association.getUserId() != userId
                     || !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress)
                     || !Objects.equals(association.getPackageName(), pkg);
+            if (!notMatch) {
+                onAssociationPreRemove(association);
+            }
+            return notMatch;
         }));
     }
 
+    void onAssociationPreRemove(Association association) {
+        String deviceProfile = association.getDeviceProfile();
+        if (deviceProfile != null) {
+            Association otherAssociationWithDeviceProfile = find(
+                    getAllAssociations(association.getUserId()),
+                    a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile()));
+            if (otherAssociationWithDeviceProfile != null) {
+                Log.i(LOG_TAG, "Not revoking " + deviceProfile
+                        + " for " + association
+                        + " - profile still present in " + otherAssociationWithDeviceProfile);
+            } else {
+                mRoleManager.removeRoleHolderAsUser(
+                        association.getDeviceProfile(),
+                        association.getPackageName(),
+                        RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+                        UserHandle.of(association.getUserId()),
+                        getContext().getMainExecutor(),
+                        success -> {
+                            if (!success) {
+                                Log.e(LOG_TAG, "Failed to revoke device profile role "
+                                        + association.getDeviceProfile()
+                                        + " to " + association.getPackageName()
+                                        + " for user " + association.getUserId());
+                            }
+                        });
+            }
+        }
+    }
+
     private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
         PackageInfo packageInfo = getPackageInfo(
                 association.getPackageName(),
@@ -598,6 +667,10 @@
         }
 
         exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid);
+
+        if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddress())) {
+            grantDeviceProfile(association);
+        }
     }
 
     private void exemptFromAutoRevoke(String packageName, int uid) {
@@ -779,72 +852,39 @@
     void onDeviceConnected(String address) {
         mCurrentlyConnectedDevices.add(address);
 
-        Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address));
-
         for (UserInfo user : getAllUsers()) {
             for (Association association : getAllAssociations(user.id)) {
                 if (Objects.equals(address, association.getDeviceMacAddress())) {
                     if (association.getDeviceProfile() != null) {
                         Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile()
                                 + " to " + association.getPackageName()
-                                + " due to device connected: " + address);
-                        mRoleManager.addRoleHolderAsUser(
-                                association.getDeviceProfile(),
-                                association.getPackageName(),
-                                RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
-                                UserHandle.of(association.getUserId()),
-                                getContext().getMainExecutor(),
-                                success -> {
-                                    if (!success) {
-                                        Log.e(LOG_TAG, "Failed to grant device profile role "
-                                                + association.getDeviceProfile()
-                                                + " to " + association.getPackageName()
-                                                + " for user " + association.getUserId());
-                                    }
-                                });
+                                + " due to device connected: " + association.getDeviceMacAddress());
+                        grantDeviceProfile(association);
                     }
                 }
             }
         }
     }
 
-    void onDeviceDisconnected(String address) {
-        mCurrentlyConnectedDevices.remove(address);
-
-        Handler.getMain().postDelayed(() -> {
-            if (!mCurrentlyConnectedDevices.contains(address)) {
-                for (UserInfo user : getAllUsers()) {
-                    for (Association association : getAllAssociations(user.id)) {
-                        if (association.getDeviceProfile() != null
-                                && Objects.equals(address, association.getDeviceMacAddress())
-                                && !association.isKeepProfilePrivilegesWhenDeviceAway()) {
-                            Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile()
-                                    + " to " + association.getPackageName()
-                                    + " due to device disconnected: " + address);
-                            mRoleManager.removeRoleHolderAsUser(
-                                    association.getDeviceProfile(),
-                                    association.getPackageName(),
-                                    RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
-                                    UserHandle.of(association.getUserId()),
-                                    getContext().getMainExecutor(),
-                                    success -> {
-                                        if (!success) {
-                                            Log.e(LOG_TAG, "Failed to revoke device profile role "
-                                                    + association.getDeviceProfile()
-                                                    + " to " + association.getPackageName()
-                                                    + " for user " + association.getUserId());
-                                        }
-                                    });
-                        }
+    private void grantDeviceProfile(Association association) {
+        mRoleManager.addRoleHolderAsUser(
+                association.getDeviceProfile(),
+                association.getPackageName(),
+                RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+                UserHandle.of(association.getUserId()),
+                getContext().getMainExecutor(),
+                success -> {
+                    if (!success) {
+                        Log.e(LOG_TAG, "Failed to grant device profile role "
+                                + association.getDeviceProfile()
+                                + " to " + association.getPackageName()
+                                + " for user " + association.getUserId());
                     }
-                }
-            }
-        }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS);
+                });
     }
 
-    @NonNull
-    private String getDisconnectJobHandlerId(String address) {
-        return "CDM_onDisconnected_" + address;
+    void onDeviceDisconnected(String address) {
+        mCurrentlyConnectedDevices.remove(address);
     }
 
     private class ShellCmd extends ShellCommand {
@@ -860,34 +900,49 @@
 
         @Override
         public int onCommand(String cmd) {
-            switch (cmd) {
-                case "list": {
-                    forEach(
-                            getAllAssociations(getNextArgInt()),
-                            a -> getOutPrintWriter()
-                                    .println(a.getPackageName() + " " + a.getDeviceMacAddress()));
-                } break;
+            try {
+                switch (cmd) {
+                    case "list": {
+                        forEach(
+                                getAllAssociations(getNextArgInt()),
+                                a -> getOutPrintWriter()
+                                        .println(a.getPackageName() + " "
+                                                + a.getDeviceMacAddress()));
+                    }
+                    break;
 
-                case "associate": {
-                    addAssociation(new Association(getNextArgInt(), getNextArgRequired(),
-                            getNextArgRequired(), null, false));
-                } break;
+                    case "associate": {
+                        String pkg = getNextArgRequired();
+                        String address = getNextArgRequired();
+                        addAssociation(new Association(getNextArgInt(), address, pkg, null, false));
+                    }
+                    break;
 
-                case "disassociate": {
-                    removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired());
-                } break;
+                    case "disassociate": {
+                        removeAssociation(getNextArgInt(), getNextArgRequired(),
+                                getNextArgRequired());
+                    }
+                    break;
 
-                case "simulate_connect": {
-                    onDeviceConnected(getNextArgRequired());
-                } break;
+                    case "simulate_connect": {
+                        onDeviceConnected(getNextArgRequired());
+                    }
+                    break;
 
-                case "simulate_disconnect": {
-                    onDeviceDisconnected(getNextArgRequired());
-                } break;
+                    case "simulate_disconnect": {
+                        onDeviceDisconnected(getNextArgRequired());
+                    }
+                    break;
 
-                default: return handleDefaultCommands(cmd);
+                    default:
+                        return handleDefaultCommands(cmd);
+                }
+                return 0;
+            } catch (Throwable t) {
+                Log.e(LOG_TAG, "Error running a command: $ " + cmd, t);
+                getErrPrintWriter().println(Log.getStackTraceString(t));
+                return 1;
             }
-            return 0;
         }
 
         private int getNextArgInt() {
diff --git a/services/contentcapture/OWNERS b/services/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/services/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/services/contentsuggestions/OWNERS b/services/contentsuggestions/OWNERS
new file mode 100644
index 0000000..449db3a
--- /dev/null
+++ b/services/contentsuggestions/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentsuggestions/OWNERS
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 86ea1e4..00c91fe 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -21,7 +21,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.contentsuggestions.ClassificationsRequest;
 import android.app.contentsuggestions.ContentSuggestionsManager;
 import android.app.contentsuggestions.IClassificationsCallback;
@@ -40,6 +39,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
+import android.window.TaskSnapshot;
 
 import com.android.internal.os.IResultReceiver;
 import com.android.server.LocalServices;
@@ -162,7 +162,7 @@
             // Skip taking TaskSnapshot when bitmap is provided.
             if (!imageContextRequestExtras.containsKey(ContentSuggestionsManager.EXTRA_BITMAP)) {
                 // Can block, so call before acquiring the lock.
-                ActivityManager.TaskSnapshot snapshot =
+                TaskSnapshot snapshot =
                         mActivityTaskManagerInternal.getTaskSnapshotBlocking(taskId, false);
                 if (snapshot != null) {
                     snapshotBuffer = snapshot.getHardwareBuffer();
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 17e3456..f848197 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -110,6 +110,7 @@
     ],
 
     required: [
+        "cec_config.xml",
         "gps_debug.conf",
         "protolog.conf.json.gz",
     ],
@@ -172,6 +173,11 @@
 }
 
 prebuilt_etc {
+    name: "cec_config.xml",
+    src: "java/com/android/server/hdmi/cec_config.xml",
+}
+
+prebuilt_etc {
     name: "gps_debug.conf",
     src: "java/com/android/server/location/gnss/gps_debug.conf",
 }
@@ -213,7 +219,6 @@
         "java/com/android/server/connectivity/KeepaliveTracker.java",
         "java/com/android/server/connectivity/LingerMonitor.java",
         "java/com/android/server/connectivity/MockableSystemProperties.java",
-        "java/com/android/server/connectivity/MultipathPolicyTracker.java",
         "java/com/android/server/connectivity/Nat464Xlat.java",
         "java/com/android/server/connectivity/NetdEventListenerService.java",
         "java/com/android/server/connectivity/NetworkAgentInfo.java",
diff --git a/services/core/OWNERS b/services/core/OWNERS
new file mode 100644
index 0000000..88d0b61
--- /dev/null
+++ b/services/core/OWNERS
@@ -0,0 +1 @@
+per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
index 4d9680c..aa56da5 100644
--- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
+++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
@@ -119,7 +119,9 @@
             }
             return;
         }
-        mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
+        if (mAirplaneHelper != null) {
+            mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
+        }
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 0a68428..dc24ffd 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1275,7 +1275,7 @@
     @Override
     public boolean bindBluetoothProfileService(int bluetoothProfile,
             IBluetoothProfileServiceConnection proxy) {
-        if (!mEnable) {
+        if (mState != BluetoothAdapter.STATE_ON) {
             if (DBG) {
                 Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
                         + ", while Bluetooth was disabled");
@@ -1441,7 +1441,7 @@
                 mBluetoothLock.readLock().unlock();
             }
 
-            if (!mEnable || state != BluetoothAdapter.STATE_ON) {
+            if (state != BluetoothAdapter.STATE_ON) {
                 if (DBG) {
                     Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
                 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0d0f0dd..2e1fbb7 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;
@@ -129,6 +128,7 @@
 import android.net.SocketKeepalive;
 import android.net.TetheringManager;
 import android.net.UidRange;
+import android.net.UidRangeParcel;
 import android.net.Uri;
 import android.net.VpnManager;
 import android.net.VpnService;
@@ -144,6 +144,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -184,7 +185,6 @@
 import com.android.internal.net.VpnProfile;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.LocationPermissionChecker;
 import com.android.internal.util.MessageUtils;
@@ -877,6 +877,10 @@
      */
     @VisibleForTesting
     public static class Dependencies {
+        public int getCallingUid() {
+            return Binder.getCallingUid();
+        }
+
         /**
          * Get system properties to use in ConnectivityService.
          */
@@ -1287,7 +1291,7 @@
         if (network == null) {
             return null;
         }
-        return getNetworkAgentInfoForNetId(network.netId);
+        return getNetworkAgentInfoForNetId(network.getNetId());
     }
 
     private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
@@ -1377,8 +1381,11 @@
             return;
         }
         final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+        final NetworkRequest satisfiedRequest = nri.getSatisfiedRequest();
+        final int requestId =  satisfiedRequest != null
+                ? satisfiedRequest.requestId : nri.mRequests.get(0).requestId;
         mNetworkInfoBlockingLogs.log(String.format(
-                "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.netId));
+                "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
     }
 
     /**
@@ -1409,7 +1416,7 @@
     @Override
     public NetworkInfo getActiveNetworkInfo() {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         final NetworkState state = getUnfilteredActiveNetworkState(uid);
         filterNetworkStateForUid(state, uid, false);
         maybeLogBlockedNetworkInfo(state.networkInfo, uid);
@@ -1419,7 +1426,7 @@
     @Override
     public Network getActiveNetwork() {
         enforceAccessPermission();
-        return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
+        return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false);
     }
 
     @Override
@@ -1459,7 +1466,7 @@
     // Public because it's used by mLockdownTracker.
     public NetworkInfo getActiveNetworkInfoUnfiltered() {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         NetworkState state = getUnfilteredActiveNetworkState(uid);
         return state.networkInfo;
     }
@@ -1475,7 +1482,7 @@
     @Override
     public NetworkInfo getNetworkInfo(int networkType) {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         if (getVpnUnderlyingNetworks(uid) != null) {
             // A VPN is active, so we may need to return one of its underlying networks. This
             // information is not available in LegacyTypeTracker, so we have to get it from
@@ -1520,7 +1527,7 @@
     @Override
     public Network getNetworkForType(int networkType) {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         NetworkState state = getFilteredNetworkState(networkType, uid);
         if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
             return state.network;
@@ -1567,7 +1574,7 @@
             result.put(
                     nai.network,
                     maybeSanitizeLocationInfoForCaller(
-                            nc, Binder.getCallingUid(), callingPackageName));
+                            nc, mDeps.getCallingUid(), callingPackageName));
         }
 
         synchronized (mVpns) {
@@ -1582,7 +1589,7 @@
                                 result.put(
                                         network,
                                         maybeSanitizeLocationInfoForCaller(
-                                                nc, Binder.getCallingUid(), callingPackageName));
+                                                nc, mDeps.getCallingUid(), callingPackageName));
                             }
                         }
                     }
@@ -1612,7 +1619,7 @@
     @Override
     public LinkProperties getActiveLinkProperties() {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         NetworkState state = getUnfilteredActiveNetworkState(uid);
         if (state.linkProperties == null) return null;
         return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
@@ -1626,7 +1633,7 @@
         final LinkProperties lp = getLinkProperties(nai);
         if (lp == null) return null;
         return linkPropertiesRestrictedForCallerPermissions(
-                lp, Binder.getCallingPid(), Binder.getCallingUid());
+                lp, Binder.getCallingPid(), mDeps.getCallingUid());
     }
 
     // TODO - this should be ALL networks
@@ -1636,7 +1643,7 @@
         final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
         if (lp == null) return null;
         return linkPropertiesRestrictedForCallerPermissions(
-                lp, Binder.getCallingPid(), Binder.getCallingUid());
+                lp, Binder.getCallingPid(), mDeps.getCallingUid());
     }
 
     @Nullable
@@ -1658,17 +1665,17 @@
         synchronized (nai) {
             if (nai.networkCapabilities == null) return null;
             return networkCapabilitiesRestrictedForCallerPermissions(
-                    nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
+                    nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid());
         }
     }
 
     @Override
     public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
-        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
+        mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
         enforceAccessPermission();
         return maybeSanitizeLocationInfoForCaller(
                 getNetworkCapabilitiesInternal(network),
-                Binder.getCallingUid(), callingPackageName);
+                mDeps.getCallingUid(), callingPackageName);
     }
 
     @VisibleForTesting
@@ -1706,16 +1713,17 @@
             return newNc;
         }
 
-        Binder.withCleanCallingIdentity(
-                () -> {
-                    if (!mLocationPermissionChecker.checkLocationPermission(
-                            callerPkgName, null /* featureId */, callerUid, null /* message */)) {
-                        // Caller does not have the requisite location permissions. Reset the
-                        // owner's UID in the NetworkCapabilities.
-                        newNc.setOwnerUid(INVALID_UID);
-                    }
-                }
-        );
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (!mLocationPermissionChecker.checkLocationPermission(
+                    callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+                // Caller does not have the requisite location permissions. Reset the
+                // owner's UID in the NetworkCapabilities.
+                newNc.setOwnerUid(INVALID_UID);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         return newNc;
     }
@@ -1756,7 +1764,7 @@
     }
 
     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
-        if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
+        if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) {
             nc.addCapability(NET_CAPABILITY_FOREGROUND);
         }
     }
@@ -1781,14 +1789,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();
 
@@ -1817,7 +1817,7 @@
         // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
         // for devices launched with Q and above. However, existing devices upgrading to Q and
         // above must continued to be supported for few more releases.
-        if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
+        if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt(
                 "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
             log("This method exists only for app backwards compatibility"
                     + " and must not be called by system services.");
@@ -1883,14 +1883,14 @@
             return false;
         }
 
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         final long token = Binder.clearCallingIdentity();
         try {
             LinkProperties lp;
             int netId;
             synchronized (nai) {
                 lp = nai.linkProperties;
-                netId = nai.network.netId;
+                netId = nai.network.getNetId();
             }
             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
             if (DBG) log("requestRouteToHostAddress ok=" + ok);
@@ -2303,7 +2303,7 @@
      */
     @Override
     public void systemReady() {
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+        if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
             throw new SecurityException("Calling Uid is not system uid.");
         }
         systemReadyInternal();
@@ -2341,6 +2341,31 @@
     }
 
     /**
+     * Start listening for default data network activity state changes.
+     */
+    @Override
+    public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Stop listening for default data network activity state changes.
+     */
+    @Override
+    public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Check whether the default network radio is currently active.
+     */
+    @Override
+    public boolean isDefaultNetworkActive() {
+        // TODO: Replace isNetworkActive() in NMS.
+        return false;
+    }
+
+    /**
      * Setup data activity tracking for the given network.
      *
      * Every {@code setupDataActivityTracking} should be paired with a
@@ -2525,9 +2550,21 @@
         PriorityDump.dump(mPriorityDumper, fd, writer, args);
     }
 
+    private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+        if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump " + tag + " from from pid="
+                    + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid()
+                    + " due to missing android.permission.DUMP permission");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
     private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+        if (!checkDumpPermission(mContext, TAG, pw)) return;
         if (asProto) return;
 
         if (ArrayUtils.contains(args, DIAG_ARG)) {
@@ -2553,7 +2590,7 @@
         if (defaultNai == null) {
             pw.println("none");
         } else {
-            pw.println(defaultNai.network.netId);
+            pw.println(defaultNai.network.getNetId());
         }
         pw.println();
 
@@ -2690,7 +2727,7 @@
     private NetworkAgentInfo[] networksSortedById() {
         NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
         networks = mNetworkAgentInfos.values().toArray(networks);
-        Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId));
+        Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId()));
         return networks;
     }
 
@@ -2698,7 +2735,7 @@
      * Return an array of all current NetworkRequest sorted by request id.
      */
     @VisibleForTesting
-    protected NetworkRequestInfo[] requestsSortedById() {
+    NetworkRequestInfo[] requestsSortedById() {
         NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
         requests = mNetworkRequests.values().toArray(requests);
         // Sort the array based off the NRI containing the min requestId in its requests.
@@ -2811,6 +2848,7 @@
                     break;
                 }
                 case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
+                    // TODO: prevent loops, e.g., if a network declares itself as underlying.
                     if (!nai.supportsUnderlyingNetworks()) {
                         Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
                         break;
@@ -2831,7 +2869,7 @@
                             log(nai.toShortString() + " changed underlying networks to "
                                     + Arrays.toString(nai.declaredUnderlyingNetworks));
                         }
-                        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+                        updateCapabilitiesForNetwork(nai);
                         notifyIfacesChangedForNetworkStats();
                     }
                 }
@@ -2855,8 +2893,7 @@
                     if (probePrivateDnsCompleted) {
                         if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
                             nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
-                            final int oldScore = nai.getCurrentScore();
-                            updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                            updateCapabilitiesForNetwork(nai);
                         }
                         // Only show the notification when the private DNS is broken and the
                         // PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
@@ -2871,8 +2908,7 @@
                         // done yet. In either case, the networkCapabilities should be updated to
                         // reflect the new status.
                         nai.networkCapabilities.setPrivateDnsBroken(false);
-                        final int oldScore = nai.getCurrentScore();
-                        updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                        updateCapabilitiesForNetwork(nai);
                         nai.networkAgentConfig.hasShownBroken = false;
                     }
                     break;
@@ -2893,7 +2929,6 @@
                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
                     // If captive portal status has changed, update capabilities or disconnect.
                     if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
-                        final int oldScore = nai.getCurrentScore();
                         nai.lastCaptivePortalDetected = visible;
                         nai.everCaptivePortalDetected |= visible;
                         if (nai.lastCaptivePortalDetected &&
@@ -2904,7 +2939,7 @@
                             teardownUnneededNetwork(nai);
                             break;
                         }
-                        updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                        updateCapabilitiesForNetwork(nai);
                     }
                     if (!visible) {
                         // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
@@ -2974,13 +3009,13 @@
                     handleFreshlyValidatedNetwork(nai);
                     // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
                     // LOST_INTERNET notifications if network becomes valid.
-                    mNotifier.clearNotification(nai.network.netId,
+                    mNotifier.clearNotification(nai.network.getNetId(),
                             NotificationType.NO_INTERNET);
-                    mNotifier.clearNotification(nai.network.netId,
+                    mNotifier.clearNotification(nai.network.getNetId(),
                             NotificationType.LOST_INTERNET);
-                    mNotifier.clearNotification(nai.network.netId,
+                    mNotifier.clearNotification(nai.network.getNetId(),
                             NotificationType.PARTIAL_CONNECTIVITY);
-                    mNotifier.clearNotification(nai.network.netId,
+                    mNotifier.clearNotification(nai.network.getNetId(),
                             NotificationType.PRIVATE_DNS_BROKEN);
                     // If network becomes valid, the hasShownBroken should be reset for
                     // that network so that the notification will be fired when the private
@@ -2988,7 +3023,7 @@
                     nai.networkAgentConfig.hasShownBroken = false;
                 }
             } else if (partialConnectivityChanged) {
-                updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+                updateCapabilitiesForNetwork(nai);
             }
             updateInetCondition(nai);
             // Let the NetworkAgent know the state of its network
@@ -3051,7 +3086,7 @@
         private final AutodestructReference<NetworkAgentInfo> mNai;
 
         private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
-            mNetId = nai.network.netId;
+            mNetId = nai.network.getNetId();
             mNai = new AutodestructReference<>(nai);
         }
 
@@ -3201,7 +3236,7 @@
         // in order to restart a validation pass from within netd.
         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
         if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) {
-            updateDnses(nai.linkProperties, null, nai.network.netId);
+            updateDnses(nai.linkProperties, null, nai.network.getNetId());
         }
     }
 
@@ -3234,7 +3269,7 @@
 
     private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
         mDnsManager.updatePrivateDns(nai.network, newCfg);
-        updateDnses(nai.linkProperties, null, nai.network.netId);
+        updateDnses(nai.linkProperties, null, nai.network.getNetId());
     }
 
     private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
@@ -3330,9 +3365,9 @@
                 if (nai != null) {
                     final boolean wasDefault = isDefaultNetwork(nai);
                     synchronized (mNetworkForNetId) {
-                        mNetworkForNetId.remove(nai.network.netId);
+                        mNetworkForNetId.remove(nai.network.getNetId());
                     }
-                    mNetIdManager.releaseNetId(nai.network.netId);
+                    mNetIdManager.releaseNetId(nai.network.getNetId());
                     // Just in case.
                     mLegacyTypeTracker.remove(nai, wasDefault);
                 }
@@ -3362,7 +3397,7 @@
             log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests());
         }
         // Clear all notifications of this network.
-        mNotifier.clearNotification(nai.network.netId);
+        mNotifier.clearNotification(nai.network.getNetId());
         // A network agent has disconnected.
         // TODO - if we move the logic to the network agent (have them disconnect
         // because they lost all their requests or because their score isn't good)
@@ -3399,19 +3434,21 @@
         synchronized (mNetworkForNetId) {
             // Remove the NetworkAgent, but don't mark the netId as
             // available until we've told netd to delete it below.
-            mNetworkForNetId.remove(nai.network.netId);
+            mNetworkForNetId.remove(nai.network.getNetId());
         }
         // Remove all previously satisfied requests.
         for (int i = 0; i < nai.numNetworkRequests(); i++) {
             NetworkRequest request = nai.requestAt(i);
             final NetworkRequestInfo nri = mNetworkRequests.get(request);
             final NetworkAgentInfo currentNetwork = nri.mSatisfier;
-            if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
+            if (currentNetwork != null
+                    && currentNetwork.network.getNetId() == nai.network.getNetId()) {
                 nri.mSatisfier = null;
                 sendUpdatedScoreToFactories(request, null);
             }
         }
         nai.clearLingerState();
+        propagateUnderlyingNetworkCapabilities(nai.network);
         if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
             mDefaultNetworkNai = null;
             updateDataActivityTracking(null /* newNetwork */, nai);
@@ -3419,9 +3456,6 @@
             ensureNetworkTransitionWakelock(nai.toShortString());
         }
         mLegacyTypeTracker.remove(nai, wasDefault);
-        if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
-            propagateUnderlyingNetworkCapabilities();
-        }
         rematchAllNetworksAndRequests();
         mLingerMonitor.noteDisconnect(nai);
         if (nai.created) {
@@ -3436,26 +3470,26 @@
             destroyNativeNetwork(nai);
             mDnsManager.removeNetwork(nai.network);
         }
-        mNetIdManager.releaseNetId(nai.network.netId);
+        mNetIdManager.releaseNetId(nai.network.getNetId());
     }
 
     private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
         try {
             // This should never fail.  Specifying an already in use NetID will cause failure.
             if (networkAgent.isVPN()) {
-                mNetd.networkCreateVpn(networkAgent.network.netId,
+                mNetd.networkCreateVpn(networkAgent.network.getNetId(),
                         (networkAgent.networkAgentConfig == null
                                 || !networkAgent.networkAgentConfig.allowBypass));
             } else {
-                mNetd.networkCreatePhysical(networkAgent.network.netId,
+                mNetd.networkCreatePhysical(networkAgent.network.getNetId(),
                         getNetworkPermission(networkAgent.networkCapabilities));
             }
-            mDnsResolver.createNetworkCache(networkAgent.network.netId);
-            mDnsManager.updateTransportsForNetwork(networkAgent.network.netId,
+            mDnsResolver.createNetworkCache(networkAgent.network.getNetId());
+            mDnsManager.updateTransportsForNetwork(networkAgent.network.getNetId(),
                     networkAgent.networkCapabilities.getTransportTypes());
             return true;
         } catch (RemoteException | ServiceSpecificException e) {
-            loge("Error creating network " + networkAgent.network.netId + ": "
+            loge("Error creating network " + networkAgent.network.getNetId() + ": "
                     + e.getMessage());
             return false;
         }
@@ -3463,8 +3497,8 @@
 
     private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
         try {
-            mNetd.networkDestroy(networkAgent.network.netId);
-            mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+            mNetd.networkDestroy(networkAgent.network.getNetId());
+            mDnsResolver.destroyNetworkCache(networkAgent.network.getNetId());
         } catch (RemoteException | ServiceSpecificException e) {
             loge("Exception destroying network: " + e);
         }
@@ -3551,30 +3585,58 @@
             return false;
         }
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
+            if (reason == UnneededFor.LINGER
+                    && !nri.isMultilayerRequest()
+                    && nri.mRequests.get(0).isBackgroundRequest()) {
                 // Background requests don't affect lingering.
                 continue;
             }
 
-            // If this Network is already the highest scoring Network for a request, or if
-            // there is hope for it to become one if it validated, then it is needed.
-            if (nri.request.isRequest() && nai.satisfies(nri.request) &&
-                    (nai.isSatisfyingRequest(nri.request.requestId) ||
-                    // Note that this catches two important cases:
-                    // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
-                    //    is currently satisfying the request.  This is desirable when
-                    //    cellular ends up validating but WiFi does not.
-                    // 2. Unvalidated WiFi will not be reaped when validated cellular
-                    //    is currently satisfying the request.  This is desirable when
-                    //    WiFi ends up validating and out scoring cellular.
-                    nri.mSatisfier.getCurrentScore()
-                            < nai.getCurrentScoreAsValidated())) {
+            if (isNetworkPotentialSatisfier(nai, nri)) {
                 return false;
             }
         }
         return true;
     }
 
+    private boolean isNetworkPotentialSatisfier(
+            @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
+        // listen requests won't keep up a network satisfying it. If this is not a multilayer
+        // request, we can return immediately. For multilayer requests, we have to check to see if
+        // any of the multilayer requests may have a potential satisfier.
+        if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+            return false;
+        }
+        for (final NetworkRequest req : nri.mRequests) {
+            // As non-multilayer listen requests have already returned, the below would only happen
+            // for a multilayer request therefore continue to the next request if available.
+            if (req.isListen()) {
+                continue;
+            }
+            // If this Network is already the highest scoring Network for a request, or if
+            // there is hope for it to become one if it validated, then it is needed.
+            if (candidate.satisfies(req)) {
+                // As soon as a network is found that satisfies a request, return. Specifically for
+                // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
+                // is important so as to not evaluate lower priority requests further in
+                // nri.mRequests.
+                final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
+                        // Note that this catches two important cases:
+                        // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+                        //    is currently satisfying the request.  This is desirable when
+                        //    cellular ends up validating but WiFi does not.
+                        // 2. Unvalidated WiFi will not be reaped when validated cellular
+                        //    is currently satisfying the request.  This is desirable when
+                        //    WiFi ends up validating and out scoring cellular.
+                        || nri.mSatisfier.getCurrentScore()
+                        < candidate.getCurrentScoreAsValidated();
+                return isNetworkNeeded;
+            }
+        }
+
+        return false;
+    }
+
     private NetworkRequestInfo getNriForAppRequest(
             NetworkRequest request, int callingUid, String requestedOperation) {
         final NetworkRequestInfo nri = mNetworkRequests.get(request);
@@ -3656,7 +3718,7 @@
                 nri.mSatisfier = null;
                 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
                     // Went from foreground to background.
-                    updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+                    updateCapabilitiesForNetwork(nai);
                 }
             }
 
@@ -3871,8 +3933,12 @@
                 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
         appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
 
-        Binder.withCleanCallingIdentity(() ->
-                mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private class CaptivePortalImpl extends ICaptivePortal.Stub {
@@ -3900,7 +3966,7 @@
 
             if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
                 checkNetworkStackPermission();
-                nm.forceReevaluation(Binder.getCallingUid());
+                nm.forceReevaluation(mDeps.getCallingUid());
             }
         }
 
@@ -4026,7 +4092,7 @@
 
         Intent intent = new Intent(action);
         if (type != NotificationType.PRIVATE_DNS_BROKEN) {
-            intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
+            intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.getNetId()), null));
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             // Some OEMs have their own Settings package. Thus, need to get the current using
             // Settings package name instead of just use default name "com.android.settings".
@@ -4041,7 +4107,8 @@
                 intent,
                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
 
-        mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority);
+        mNotifier.showNotification(
+                nai.network.getNetId(), type, nai, null, pendingIntent, highPriority);
     }
 
     private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) {
@@ -4366,7 +4433,7 @@
     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
         enforceAccessPermission();
         enforceInternetPermission();
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         final int connectivityInfo = encodeBool(hasConnectivity);
 
         // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This
@@ -4407,7 +4474,7 @@
             return;
         }
         if (DBG) {
-            int netid = nai.network.netId;
+            int netid = nai.network.getNetId();
             log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
         }
         // Validating a network that has not yet connected could result in a call to
@@ -4436,13 +4503,13 @@
         if (globalProxy != null) return globalProxy;
         if (network == null) {
             // Get the network associated with the calling UID.
-            final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(),
+            final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(),
                     true);
             if (activeNetwork == null) {
                 return null;
             }
             return getLinkPropertiesProxyInfo(activeNetwork);
-        } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) {
+        } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network.getNetId())) {
             // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
             // caller may not have.
             return getLinkPropertiesProxyInfo(network);
@@ -4611,7 +4678,7 @@
      */
     @Override
     public ParcelFileDescriptor establishVpn(VpnConfig config) {
-        int user = UserHandle.getUserId(Binder.getCallingUid());
+        int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             throwIfLockdownEnabled();
             return mVpns.get(user).establish(config);
@@ -4632,7 +4699,7 @@
      */
     @Override
     public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) {
-        final int user = UserHandle.getUserId(Binder.getCallingUid());
+        final int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore);
         }
@@ -4650,7 +4717,7 @@
      */
     @Override
     public void deleteVpnProfile(@NonNull String packageName) {
-        final int user = UserHandle.getUserId(Binder.getCallingUid());
+        final int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             mVpns.get(user).deleteVpnProfile(packageName, mKeyStore);
         }
@@ -4667,7 +4734,7 @@
      */
     @Override
     public void startVpnProfile(@NonNull String packageName) {
-        final int user = UserHandle.getUserId(Binder.getCallingUid());
+        final int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             throwIfLockdownEnabled();
             mVpns.get(user).startVpnProfile(packageName, mKeyStore);
@@ -4684,7 +4751,7 @@
      */
     @Override
     public void stopVpnProfile(@NonNull String packageName) {
-        final int user = UserHandle.getUserId(Binder.getCallingUid());
+        final int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             mVpns.get(user).stopVpnProfile(packageName);
         }
@@ -4696,7 +4763,7 @@
      */
     @Override
     public void startLegacyVpn(VpnProfile profile) {
-        int user = UserHandle.getUserId(Binder.getCallingUid());
+        int user = UserHandle.getUserId(mDeps.getCallingUid());
         final LinkProperties egress = getActiveLinkProperties();
         if (egress == null) {
             throw new IllegalStateException("Missing active network connection");
@@ -4809,25 +4876,43 @@
         }
     }
 
+    private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) {
+        final Network defaultNetwork = getNetwork(getDefaultNetwork());
+        if (underlyingNetworks == null && defaultNetwork != null) {
+            // null underlying networks means to track the default.
+            underlyingNetworks = new Network[] { defaultNetwork };
+        }
+        return underlyingNetworks;
+    }
+
+    // Returns true iff |network| is an underlying network of |nai|.
+    private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) {
+        // TODO: support more than one level of underlying networks, either via a fixed-depth search
+        // (e.g., 2 levels of underlying networks), or via loop detection, or....
+        if (!nai.supportsUnderlyingNetworks()) return false;
+        final Network[] underlying = underlyingNetworksOrDefault(nai.declaredUnderlyingNetworks);
+        return ArrayUtils.contains(underlying, network);
+    }
+
     /**
-     * Ask all networks with underlying networks to recompute and update their capabilities.
+     * Recompute the capabilities for any networks that had a specific network as underlying.
      *
      * When underlying networks change, such networks may have to update capabilities to reflect
      * things like the metered bit, their transports, and so on. The capabilities are calculated
      * immediately. This method runs on the ConnectivityService thread.
      */
-    private void propagateUnderlyingNetworkCapabilities() {
+    private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) {
         ensureRunningOnConnectivityServiceThread();
         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
-            if (nai.supportsUnderlyingNetworks()) {
-                updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+            if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) {
+                updateCapabilitiesForNetwork(nai);
             }
         }
     }
 
     @Override
     public boolean updateLockdownVpn() {
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+        if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
             logw("Lockdown VPN only available to AID_SYSTEM");
             return false;
         }
@@ -4849,7 +4934,7 @@
                     setLockdownTracker(null);
                     return true;
                 }
-                int user = UserHandle.getUserId(Binder.getCallingUid());
+                int user = UserHandle.getUserId(mDeps.getCallingUid());
                 Vpn vpn = mVpns.get(user);
                 if (vpn == null) {
                     logw("VPN for user " + user + " not ready yet. Skipping lockdown");
@@ -5142,7 +5227,7 @@
                 loge("Starting user already has a VPN");
                 return;
             }
-            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
+            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
             mVpns.put(userId, userVpn);
             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
                 updateLockdownVpn();
@@ -5414,7 +5499,7 @@
             messenger = null;
             mBinder = null;
             mPid = getCallingPid();
-            mUid = getCallingUid();
+            mUid = mDeps.getCallingUid();
             enforceRequestCountLimit();
         }
 
@@ -5426,7 +5511,7 @@
             ensureAllNetworkRequestsHaveType(mRequests);
             mBinder = binder;
             mPid = getCallingPid();
-            mUid = getCallingUid();
+            mUid = mDeps.getCallingUid();
             mPendingIntent = null;
             enforceRequestCountLimit();
 
@@ -5441,6 +5526,10 @@
             this(r, null);
         }
 
+        boolean isMultilayerRequest() {
+            return mRequests.size() > 1;
+        }
+
         private List<NetworkRequest> initializeRequests(NetworkRequest r) {
             final ArrayList<NetworkRequest> tempRequests = new ArrayList<>();
             tempRequests.add(new NetworkRequest(r));
@@ -5482,7 +5571,7 @@
         public void binderDied() {
             log("ConnectivityService NetworkRequestInfo binderDied(" +
                     mRequests + ", " + mBinder + ")");
-            releaseNetworkRequest(mRequests);
+            releaseNetworkRequests(mRequests);
         }
 
         @Override
@@ -5515,13 +5604,15 @@
         mAppOpsManager.checkPackage(callerUid, callerPackageName);
     }
 
-    private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
+    private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
         final SortedSet<Integer> thresholds = new TreeSet<>();
         synchronized (nai) {
-            for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-                if (nri.request.networkCapabilities.hasSignalStrength() &&
-                        nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
-                    thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+            for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+                for (final NetworkRequest req : nri.mRequests) {
+                    if (req.networkCapabilities.hasSignalStrength()
+                            && nai.satisfiesImmutableCapabilitiesOf(req)) {
+                        thresholds.add(req.networkCapabilities.getSignalStrength());
+                    }
                 }
             }
         }
@@ -5569,11 +5660,12 @@
     }
 
     private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) {
-        final PackageManager pm = mContext.getPackageManager();
-        final int userId = UserHandle.getCallingUserId();
+        final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid());
+        final PackageManager pm =
+                mContext.createContextAsUser(user, 0 /* flags */).getPackageManager();
         try {
-            final int callingVersion = pm.getApplicationInfoAsUser(
-                    callingPackageName, 0 /* flags */, userId).targetSdkVersion;
+            final int callingVersion = pm.getApplicationInfo(
+                    callingPackageName, 0 /* flags */).targetSdkVersion;
             if (callingVersion < version) return false;
         } catch (PackageManager.NameNotFoundException e) { }
         return true;
@@ -5588,7 +5680,7 @@
                 throw new SecurityException("Insufficient permissions to specify legacy type");
             }
         }
-        final int callingUid = Binder.getCallingUid();
+        final int callingUid = mDeps.getCallingUid();
         final NetworkRequest.Type type = (networkCapabilities == null)
                 ? NetworkRequest.Type.TRACK_DEFAULT
                 : NetworkRequest.Type.REQUEST;
@@ -5653,12 +5745,12 @@
             return false;
         }
         synchronized (mNetworkForNetId) {
-            nai = mNetworkForNetId.get(network.netId);
+            nai = mNetworkForNetId.get(network.getNetId());
         }
         if (nai != null) {
             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
             synchronized (mBandwidthRequests) {
-                final int uid = Binder.getCallingUid();
+                final int uid = mDeps.getCallingUid();
                 Integer uidReqs = mBandwidthRequests.get(uid);
                 if (uidReqs == null) {
                     uidReqs = 0;
@@ -5675,7 +5767,7 @@
     }
 
     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         if (isSystem(uid)) {
             // Exemption for system uid.
             return;
@@ -5695,7 +5787,7 @@
             PendingIntent operation, @NonNull String callingPackageName,
             @Nullable String callingAttributionTag) {
         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
-        final int callingUid = Binder.getCallingUid();
+        final int callingUid = mDeps.getCallingUid();
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
                 callingAttributionTag);
@@ -5754,7 +5846,7 @@
     @Override
     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
             Messenger messenger, IBinder binder, @NonNull String callingPackageName) {
-        final int callingUid = Binder.getCallingUid();
+        final int callingUid = mDeps.getCallingUid();
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
@@ -5784,7 +5876,7 @@
     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
             PendingIntent operation, @NonNull String callingPackageName) {
         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
-        final int callingUid = Binder.getCallingUid();
+        final int callingUid = mDeps.getCallingUid();
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
@@ -5807,7 +5899,7 @@
         return mNextNetworkProviderId.getAndIncrement();
     }
 
-    private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+    private void releaseNetworkRequests(List<NetworkRequest> networkRequests) {
         for (int i = 0; i < networkRequests.size(); i++) {
             releaseNetworkRequest(networkRequests.get(i));
         }
@@ -5885,7 +5977,7 @@
         } else {
             enforceNetworkFactoryPermission();
         }
-        mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
+        mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true));
     }
 
     // NOTE: Accessed on multiple threads, must be synchronized on itself.
@@ -5979,7 +6071,7 @@
             enforceNetworkFactoryPermission();
         }
 
-        final int uid = Binder.getCallingUid();
+        final int uid = mDeps.getCallingUid();
         final long token = Binder.clearCallingIdentity();
         try {
             return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
@@ -6033,7 +6125,7 @@
         if (VDBG) log("Got NetworkAgent Messenger");
         mNetworkAgentInfos.put(nai.messenger, nai);
         synchronized (mNetworkForNetId) {
-            mNetworkForNetId.put(nai.network.netId, nai);
+            mNetworkForNetId.put(nai.network.getNetId(), nai);
         }
 
         try {
@@ -6061,7 +6153,7 @@
 
     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
             @NonNull LinkProperties oldLp) {
-        int netId = networkAgent.network.netId;
+        int netId = networkAgent.network.getNetId();
 
         // The NetworkAgent does not know whether clatd is running on its network or not, or whether
         // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure
@@ -6342,7 +6434,7 @@
         final int newPermission = getNetworkPermission(newNc);
         if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
             try {
-                mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission);
+                mNetd.networkSetPermissionForNetwork(nai.network.getNetId(), newPermission);
             } catch (RemoteException | ServiceSpecificException e) {
                 loge("Exception in networkSetPermissionForNetwork: " + e);
             }
@@ -6357,22 +6449,28 @@
      * This method should never alter the agent's NetworkCapabilities, only store data in |nai|.
      */
     private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
-        nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
+        // Note: resetting the owner UID before storing the agent capabilities in NAI means that if
+        // the agent attempts to change the owner UID, then nai.declaredCapabilities will not
+        // actually be the same as the capabilities sent by the agent. Still, it is safer to reset
+        // the owner UID here and behave as if the agent had never tried to change it.
+        if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) {
+            Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from "
+                    + nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
+            nc.setOwnerUid(nai.networkCapabilities.getOwnerUid());
+        }
+        nai.declaredCapabilities = new NetworkCapabilities(nc);
     }
 
-    /** Modifies |caps| based on the capabilities of the specified underlying networks. */
+    /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */
     @VisibleForTesting
     void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
-            @NonNull NetworkCapabilities caps,  boolean declaredMetered) {
-        final Network defaultNetwork = getNetwork(getDefaultNetwork());
-        if (underlyingNetworks == null && defaultNetwork != null) {
-            // null underlying networks means to track the default.
-            underlyingNetworks = new Network[] { defaultNetwork };
-        }
-        int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+            @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) {
+        underlyingNetworks = underlyingNetworksOrDefault(underlyingNetworks);
+        int[] transportTypes = agentCaps.getTransportTypes();
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
+        // metered if any underlying is metered, or originally declared metered by the agent.
+        boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
         boolean roaming = false; // roaming if any underlying is roaming
         boolean congested = false; // congested if any underlying is congested
         boolean suspended = true; // suspended if all underlying are suspended
@@ -6418,13 +6516,13 @@
             suspended = false;
         }
 
-        caps.setTransportTypes(transportTypes);
-        caps.setLinkDownstreamBandwidthKbps(downKbps);
-        caps.setLinkUpstreamBandwidthKbps(upKbps);
-        caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
-        caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
-        caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
-        caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
+        newNc.setTransportTypes(transportTypes);
+        newNc.setLinkDownstreamBandwidthKbps(downKbps);
+        newNc.setLinkUpstreamBandwidthKbps(upKbps);
+        newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+        newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+        newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+        newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
     }
 
     /**
@@ -6481,7 +6579,8 @@
         }
 
         if (nai.supportsUnderlyingNetworks()) {
-            applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
+            applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities,
+                    newNc);
         }
 
         return newNc;
@@ -6560,17 +6659,20 @@
             }
         }
 
-        if (!newNc.hasTransport(TRANSPORT_VPN)) {
-            // Tell VPNs about updated capabilities, since they may need to
-            // bubble those changes through.
-            propagateUnderlyingNetworkCapabilities();
-        }
+        // This network might have been underlying another network. Propagate its capabilities.
+        propagateUnderlyingNetworkCapabilities(nai.network);
 
         if (!newNc.equalsTransportTypes(prevNc)) {
-            mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes());
+            mDnsManager.updateTransportsForNetwork(
+                    nai.network.getNetId(), newNc.getTransportTypes());
         }
     }
 
+    /** Convenience method to update the capabilities for a given network. */
+    private void updateCapabilitiesForNetwork(NetworkAgentInfo nai) {
+        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+    }
+
     /**
      * Returns whether VPN isolation (ingress interface filtering) should be applied on the given
      * network.
@@ -6600,6 +6702,16 @@
                 && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
     }
 
+    private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
+        final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
+        int index = 0;
+        for (UidRange range : ranges) {
+            stableRanges[index] = new UidRangeParcel(range.start, range.stop);
+            index++;
+        }
+        return stableRanges;
+    }
+
     private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
             NetworkCapabilities newNc) {
         Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
@@ -6619,14 +6731,11 @@
             // removing old range works because, unlike the filtering rules below, it's possible to
             // add duplicate UID routing rules.
             if (!newRanges.isEmpty()) {
-                final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
-                newRanges.toArray(addedRangesArray);
-                mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
+                mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges));
             }
             if (!prevRanges.isEmpty()) {
-                final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
-                prevRanges.toArray(removedRangesArray);
-                mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
+                mNetd.networkRemoveUidRanges(
+                        nai.network.netId, toUidRangeStableParcels(prevRanges));
             }
             final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
             final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
@@ -6657,7 +6766,7 @@
     public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
         ensureRunningOnConnectivityServiceThread();
 
-        if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
+        if (getNetworkAgentInfoForNetId(nai.network.getNetId()) != nai) {
             // Ignore updates for disconnected networks
             return;
         }
@@ -6856,8 +6965,7 @@
             teardownUnneededNetwork(oldNetwork);
         } else {
             // Put the network in the background.
-            updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
-                    oldNetwork.networkCapabilities);
+            updateCapabilitiesForNetwork(oldNetwork);
         }
     }
 
@@ -6868,7 +6976,7 @@
 
         try {
             if (null != newNetwork) {
-                mNetd.networkSetDefault(newNetwork.network.netId);
+                mNetd.networkSetDefault(newNetwork.network.getNetId());
             } else {
                 mNetd.networkClearDefault();
             }
@@ -6882,8 +6990,10 @@
         updateTcpBufferSizes(null != newNetwork
                 ? newNetwork.linkProperties.getTcpBufferSizes() : null);
         notifyIfacesChangedForNetworkStats();
-        // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
-        propagateUnderlyingNetworkCapabilities();
+        // Fix up the NetworkCapabilities of any networks that have this network as underlying.
+        if (newNetwork != null) {
+            propagateUnderlyingNetworkCapabilities(newNetwork.network);
+        }
     }
 
     private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
@@ -6931,8 +7041,8 @@
 
             public String toString() {
                 return mRequest.mRequests.get(0).requestId + " : "
-                        + (null != mOldNetwork ? mOldNetwork.network.netId : "null")
-                        + " → " + (null != mNewNetwork ? mNewNetwork.network.netId : "null");
+                        + (null != mOldNetwork ? mOldNetwork.network.getNetId() : "null")
+                        + " → " + (null != mNewNetwork ? mNewNetwork.network.getNetId() : "null");
             }
         }
 
@@ -7339,13 +7449,11 @@
             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
 
             if (!createNativeNetwork(networkAgent)) return;
-            if (networkAgent.isVPN()) {
-                // Initialize the VPN capabilities to their starting values according to the
-                // underlying networks. This will avoid a spurious callback to
-                // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
-                // the VPN would switch from its default, blank capabilities to those
-                // that reflect the capabilities of its underlying networks.
-                propagateUnderlyingNetworkCapabilities();
+            if (networkAgent.supportsUnderlyingNetworks()) {
+                // Initialize the network's capabilities to their starting values according to the
+                // underlying networks. This ensures that the capabilities are correct before
+                // anything happens to the network.
+                updateCapabilitiesForNetwork(networkAgent);
             }
             networkAgent.created = true;
         }
@@ -7387,10 +7495,6 @@
             // doing.
             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
 
-            if (networkAgent.supportsUnderlyingNetworks()) {
-                propagateUnderlyingNetworkCapabilities();
-            }
-
             // Consider network even though it is not yet validated.
             rematchAllNetworksAndRequests();
 
@@ -7621,7 +7725,7 @@
 
     @Override
     public boolean addVpnAddress(String address, int prefixLength) {
-        int user = UserHandle.getUserId(Binder.getCallingUid());
+        int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             throwIfLockdownEnabled();
             return mVpns.get(user).addAddress(address, prefixLength);
@@ -7630,7 +7734,7 @@
 
     @Override
     public boolean removeVpnAddress(String address, int prefixLength) {
-        int user = UserHandle.getUserId(Binder.getCallingUid());
+        int user = UserHandle.getUserId(mDeps.getCallingUid());
         synchronized (mVpns) {
             throwIfLockdownEnabled();
             return mVpns.get(user).removeAddress(address, prefixLength);
@@ -7639,7 +7743,7 @@
 
     @Override
     public boolean setUnderlyingNetworksForVpn(Network[] networks) {
-        int user = UserHandle.getUserId(Binder.getCallingUid());
+        int user = UserHandle.getUserId(mDeps.getCallingUid());
         final boolean success;
         synchronized (mVpns) {
             throwIfLockdownEnabled();
@@ -7727,10 +7831,13 @@
 
         final int userId = UserHandle.getCallingUserId();
 
-        Binder.withCleanCallingIdentity(() -> {
+        final long token = Binder.clearCallingIdentity();
+        try {
             final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
             ipMemoryStore.factoryReset();
-        });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         // Turn airplane mode off
         setAirplaneMode(false);
@@ -7796,7 +7903,7 @@
 
     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
         int[] transports = nai.networkCapabilities.getTransportTypes();
-        mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
+        mMetricsLog.log(nai.network.getNetId(), transports, new NetworkEvent(evtype));
     }
 
     private static boolean toBool(int encodedBoolean) {
@@ -7866,7 +7973,7 @@
 
     @GuardedBy("mVpns")
     private Vpn getVpnIfOwner() {
-        return getVpnIfOwner(Binder.getCallingUid());
+        return getVpnIfOwner(mDeps.getCallingUid());
     }
 
     @GuardedBy("mVpns")
@@ -8344,7 +8451,7 @@
             throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
                     + " Please use NetworkCapabilities instead.");
         }
-        final int callingUid = Binder.getCallingUid();
+        final int callingUid = mDeps.getCallingUid();
         mAppOpsManager.checkPackage(callingUid, callingPackageName);
 
         // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
@@ -8379,7 +8486,7 @@
                 mConnectivityDiagnosticsHandler.obtainMessage(
                         ConnectivityDiagnosticsHandler
                                 .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
-                        Binder.getCallingUid(),
+                        mDeps.getCallingUid(),
                         0,
                         callback));
     }
@@ -8395,7 +8502,7 @@
         }
 
         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
-        if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
+        if (nai == null || nai.creatorUid != mDeps.getCallingUid()) {
             throw new SecurityException("Data Stall simulation is only possible for network "
                 + "creators");
         }
@@ -8418,6 +8525,6 @@
                     KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
         }
 
-        notifyDataStallSuspected(p, network.netId);
+        notifyDataStallSuspected(p, network.getNetId());
     }
 }
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/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 8ed23f9..c34285e 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -257,7 +257,7 @@
 
     @VisibleForTesting
     void updateEmergencyGestureEnabled() {
-        boolean enabled = isEmergencyGestureEnabled(mContext, mUserId);
+        boolean enabled = isEmergencyGestureSettingEnabled(mContext, mUserId);
         synchronized (this) {
             mEmergencyGestureEnabled = enabled;
         }
@@ -390,38 +390,50 @@
     /**
      * Whether to enable emergency gesture.
      */
-    public static boolean isEmergencyGestureEnabled(Context context, int userId) {
-        return Settings.Secure.getIntForUser(context.getContentResolver(),
+    @VisibleForTesting
+    static boolean isEmergencyGestureSettingEnabled(Context context, int userId) {
+        return isEmergencyGestureEnabled(context.getResources())
+                && Settings.Secure.getIntForUser(context.getContentResolver(),
                 Settings.Secure.EMERGENCY_GESTURE_ENABLED, 0, userId) != 0;
     }
 
     /**
      * Whether to enable the camera launch gesture.
      */
-    public static boolean isCameraLaunchEnabled(Resources resources) {
+    private static boolean isCameraLaunchEnabled(Resources resources) {
         boolean configSet = resources.getInteger(
                 com.android.internal.R.integer.config_cameraLaunchGestureSensorType) != -1;
         return configSet &&
                 !SystemProperties.getBoolean("gesture.disable_camera_launch", false);
     }
 
-    public static boolean isCameraDoubleTapPowerEnabled(Resources resources) {
+    @VisibleForTesting
+    static boolean isCameraDoubleTapPowerEnabled(Resources resources) {
         return resources.getBoolean(
                 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
     }
 
-    public static boolean isCameraLiftTriggerEnabled(Resources resources) {
+    private static boolean isCameraLiftTriggerEnabled(Resources resources) {
         boolean configSet = resources.getInteger(
                 com.android.internal.R.integer.config_cameraLiftTriggerSensorType) != -1;
         return configSet;
     }
 
     /**
+     * Whether or not the emergency gesture feature is enabled by platform
+     */
+    private static boolean isEmergencyGestureEnabled(Resources resources) {
+        return resources.getBoolean(com.android.internal.R.bool.config_emergencyGestureEnabled);
+    }
+
+    /**
      * Whether GestureLauncherService should be enabled according to system properties.
      */
     public static boolean isGestureLauncherEnabled(Resources resources) {
-        return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) ||
-                isCameraLiftTriggerEnabled(resources);
+        return isCameraLaunchEnabled(resources)
+                || isCameraDoubleTapPowerEnabled(resources)
+                || isCameraLiftTriggerEnabled(resources)
+                || isEmergencyGestureEnabled(resources);
     }
 
     /**
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index dbf179a..ea1ac0c 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -839,6 +839,17 @@
         }
     };
 
+    // Make <this> a copy of <orig>.  The presumption is that <this> is empty.
+    protected void doCopy(IntentResolver orig) {
+        mFilters.addAll(orig.mFilters);
+        mTypeToFilter.putAll(orig.mTypeToFilter);
+        mBaseTypeToFilter.putAll(orig.mBaseTypeToFilter);
+        mWildTypeToFilter.putAll(orig.mWildTypeToFilter);
+        mSchemeToFilter.putAll(orig.mSchemeToFilter);
+        mActionToFilter.putAll(orig.mActionToFilter);
+        mTypedActionToFilter.putAll(orig.mTypedActionToFilter);
+    }
+
     /**
      * All filters that have been registered.
      */
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index b2f0c83..f648c3e 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.net.IIpSecService;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
@@ -41,7 +42,6 @@
 import android.net.IpSecUdpEncapResponse;
 import android.net.LinkAddress;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.TrafficStats;
 import android.net.util.NetdService;
 import android.os.Binder;
@@ -1083,7 +1083,7 @@
             throw new IllegalArgumentException("Unspecified address");
         }
 
-        InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress);
+        InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress);
 
         if (checkAddr.isAnyLocalAddress()) {
             throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
@@ -1467,7 +1467,7 @@
 
     private int getFamily(String inetAddress) {
         int family = AF_UNSPEC;
-        InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress);
+        InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress);
         if (checkAddress instanceof Inet4Address) {
             family = AF_INET;
         } else if (checkAddress instanceof Inet6Address) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 821a967..636da6f 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -58,10 +58,8 @@
 import android.net.NetworkPolicyManager;
 import android.net.NetworkStack;
 import android.net.NetworkStats;
-import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.TetherStatsParcel;
-import android.net.UidRange;
 import android.net.UidRangeParcel;
 import android.net.shared.NetdUtils;
 import android.net.shared.RouteUtils;
@@ -92,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;
 
@@ -421,8 +418,6 @@
                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
                 } catch (RemoteException e) {
                 }
-                FrameworkStatsLog.write_non_chained(
-                        FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
             }
         }
 
@@ -433,8 +428,6 @@
                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
                 } catch (RemoteException e) {
                 }
-                FrameworkStatsLog.write_non_chained(
-                        FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
             }
         }
 
@@ -803,7 +796,7 @@
         InterfaceConfiguration cfg = new InterfaceConfiguration();
         cfg.setHardwareAddress(p.hwAddr);
 
-        final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
+        final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr);
         cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
         for (String flag : p.flags) {
             cfg.setFlag(flag);
@@ -1394,38 +1387,6 @@
         }
     }
 
-    private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
-        UidRangeParcel range = new UidRangeParcel();
-        range.start = start;
-        range.stop = stop;
-        return range;
-    }
-
-    private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
-        UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
-        for (int i = 0; i < ranges.length; i++) {
-            stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
-        }
-        return stableRanges;
-    }
-
-    @Override
-    public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
-            throws ServiceSpecificException {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
-        } catch (ServiceSpecificException e) {
-            Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
-                    + ": netd command failed", e);
-            throw e;
-        } catch (RemoteException e) {
-            Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
-                    + ": netd command failed", e);
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-
     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
         final int policyValue;
         switch (policy) {
@@ -1554,27 +1515,6 @@
     }
 
     @Override
-    public void addVpnUidRanges(int netId, UidRange[] ranges) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        try {
-            mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void removeVpnUidRanges(int netId, UidRange[] ranges) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
         try {
@@ -1617,7 +1557,7 @@
             ranges = new UidRangeParcel[] {
                 // TODO: is there a better way of finding all existing users? If so, we could
                 // specify their ranges here.
-                makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
+                new UidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
             };
             // ... except for the UIDs that have allow rules.
             synchronized (mRulesLock) {
@@ -1648,7 +1588,7 @@
                 for (int i = 0; i < ranges.length; i++) {
                     if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
                         int uid = rules.keyAt(i);
-                        ranges[numUids] = makeUidRangeParcel(uid, uid);
+                        ranges[numUids] = new UidRangeParcel(uid, uid);
                         numUids++;
                     }
                 }
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 8706cdf..a10764b 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -9,3 +9,24 @@
 
 # Userspace reboot
 per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com
+
+# Sensor Privacy
+per-file SensorPrivacyService.java = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
+
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
+per-file *AppOp* = file:/core/java/android/permission/OWNERS
+per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+per-file *Storage* = file:/core/java/android/os/storage/OWNERS
+per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS
+per-file ConnectivityService.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
+per-file IpSecService.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file MmsServiceBroker.java = file:/telephony/OWNERS
+per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
+per-file PackageWatchdog.java = file:/services/core/java/com/android/server/rollback/OWNERS
+per-file TelephonyRegistry.java = file:/telephony/OWNERS
+per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS
+per-file VcnManagementService.java = file:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 51e2b12..01021345 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -16,39 +16,68 @@
 
 package com.android.server;
 
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
 import android.hardware.ISensorPrivacyListener;
 import android.hardware.ISensorPrivacyManager;
+import android.hardware.SensorPrivacyManager;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.service.SensorPrivacyIndividualEnabledSensorProto;
+import android.service.SensorPrivacyServiceDumpProto;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
+import android.util.SparseBooleanArray;
 import android.util.TypedXmlPullParser;
 import android.util.TypedXmlSerializer;
 import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.io.PrintWriter;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 
 /** @hide */
 public final class SensorPrivacyService extends SystemService {
@@ -57,7 +86,15 @@
 
     private static final String SENSOR_PRIVACY_XML_FILE = "sensor_privacy.xml";
     private static final String XML_TAG_SENSOR_PRIVACY = "sensor-privacy";
+    private static final String XML_TAG_INDIVIDUAL_SENSOR_PRIVACY = "individual-sensor-privacy";
     private static final String XML_ATTRIBUTE_ENABLED = "enabled";
+    private static final String XML_ATTRIBUTE_SENSOR = "sensor";
+
+    private static final String SENSOR_PRIVACY_CHANNEL_ID = Context.SENSOR_PRIVACY_SERVICE;
+    private static final String ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY =
+            SensorPrivacyService.class.getName() + ".action.disable_sensor_privacy";
+    private static final String EXTRA_SENSOR = SensorPrivacyService.class.getName()
+            + ".extra.sensor";
 
     private final SensorPrivacyServiceImpl mSensorPrivacyServiceImpl;
 
@@ -71,7 +108,8 @@
         publishBinderService(Context.SENSOR_PRIVACY_SERVICE, mSensorPrivacyServiceImpl);
     }
 
-    class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub {
+    class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements
+            AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener {
 
         private final SensorPrivacyHandler mHandler;
         private final Context mContext;
@@ -80,6 +118,7 @@
         private final AtomicFile mAtomicFile;
         @GuardedBy("mLock")
         private boolean mEnabled;
+        private SparseBooleanArray mIndividualEnabled = new SparseBooleanArray();
 
         SensorPrivacyServiceImpl(Context context) {
             mContext = context;
@@ -88,8 +127,100 @@
                     SENSOR_PRIVACY_XML_FILE);
             mAtomicFile = new AtomicFile(sensorPrivacyFile);
             synchronized (mLock) {
-                mEnabled = readPersistedSensorPrivacyEnabledLocked();
+                readPersistedSensorPrivacyStateLocked();
             }
+
+            int[] micAndCameraOps = new int[]{OP_RECORD_AUDIO, OP_CAMERA};
+            AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+            appOpsManager.startWatchingNoted(micAndCameraOps, this);
+            appOpsManager.startWatchingStarted(micAndCameraOps, this);
+
+            mContext.registerReceiver(new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    setIndividualSensorPrivacy(intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false);
+                }
+            }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY));
+        }
+
+        @Override
+        public void onOpStarted(int code, int uid, String packageName,
+                @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+            onOpNoted(code, uid, packageName, flags, result);
+        }
+
+        @Override
+        public void onOpNoted(int code, int uid, String packageName,
+                @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+            if (result != MODE_ALLOWED || (flags & AppOpsManager.OP_FLAGS_ALL_TRUSTED) == 0) {
+                return;
+            }
+
+            int sensor;
+            if (code == OP_RECORD_AUDIO) {
+                sensor = MICROPHONE;
+            } else {
+                sensor = CAMERA;
+            }
+
+            onSensorUseStarted(uid, packageName, sensor);
+        }
+
+        /**
+         * Called when a sensor protected by individual sensor privacy is attempting to get used.
+         *
+         * @param uid The uid of the app using the sensor
+         * @param packageName The package name of the app using the sensor
+         * @param sensor The sensor that is attempting to be used
+         */
+        private void onSensorUseStarted(int uid, String packageName, int sensor) {
+            if (!isIndividualSensorPrivacyEnabled(sensor)) {
+                return;
+            }
+
+            // TODO moltmann: Use dialog instead of notification if we can determine the activity
+            //                which triggered this usage
+
+            // TODO evanseverson: - Implement final UX for notification
+            //                    - Finalize strings and icons and add as resources
+
+            int icon;
+            CharSequence notificationMessage;
+            if (sensor == MICROPHONE) {
+                icon = com.android.internal.R.drawable.ic_mic;
+                notificationMessage = "Microphone is muted because of sensor privacy";
+            } else {
+                icon = com.android.internal.R.drawable.ic_camera;
+                notificationMessage = "Camera is blocked because of sensor privacy";
+            }
+
+            NotificationManager notificationManager =
+                    mContext.getSystemService(NotificationManager.class);
+            NotificationChannel channel = new NotificationChannel(
+                    SENSOR_PRIVACY_CHANNEL_ID, "Sensor privacy",
+                    NotificationManager.IMPORTANCE_HIGH);
+            channel.setSound(null, null);
+            channel.setBypassDnd(true);
+            channel.enableVibration(false);
+            channel.setBlockable(false);
+
+            notificationManager.createNotificationChannel(channel);
+
+            notificationManager.notify(sensor,
+                    new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID)
+                            .setContentTitle(notificationMessage)
+                            .setSmallIcon(icon)
+                            .addAction(new Notification.Action.Builder(
+                                    Icon.createWithResource(mContext, icon),
+                                    "Disable sensor privacy",
+                                    PendingIntent.getBroadcast(mContext, sensor,
+                                            new Intent(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY)
+                                                    .setPackage(mContext.getPackageName())
+                                                    .putExtra(EXTRA_SENSOR, sensor),
+                                            PendingIntent.FLAG_IMMUTABLE
+                                                    | PendingIntent.FLAG_UPDATE_CURRENT))
+                                    .build())
+                            .build());
         }
 
         /**
@@ -101,24 +232,28 @@
             enforceSensorPrivacyPermission();
             synchronized (mLock) {
                 mEnabled = enable;
-                FileOutputStream outputStream = null;
-                try {
-                    outputStream = mAtomicFile.startWrite();
-                    TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream);
-                    serializer.startDocument(null, true);
-                    serializer.startTag(null, XML_TAG_SENSOR_PRIVACY);
-                    serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enable);
-                    serializer.endTag(null, XML_TAG_SENSOR_PRIVACY);
-                    serializer.endDocument();
-                    mAtomicFile.finishWrite(outputStream);
-                } catch (IOException e) {
-                    Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e);
-                    mAtomicFile.failWrite(outputStream);
-                }
+                persistSensorPrivacyStateLocked();
             }
             mHandler.onSensorPrivacyChanged(enable);
         }
 
+        public void setIndividualSensorPrivacy(int sensor, boolean enable) {
+            enforceSensorPrivacyPermission();
+            synchronized (mLock) {
+                mIndividualEnabled.put(sensor, enable);
+
+                if (!enable) {
+                    // Remove any notifications prompting the user to disable sensory privacy
+                    NotificationManager notificationManager =
+                            mContext.getSystemService(NotificationManager.class);
+
+                    notificationManager.cancel(sensor);
+                }
+
+                persistSensorPrivacyState();
+            }
+        }
+
         /**
          * Enforces the caller contains the necessary permission to change the state of sensor
          * privacy.
@@ -143,30 +278,48 @@
             }
         }
 
+        @Override
+        public boolean isIndividualSensorPrivacyEnabled(int sensor) {
+            synchronized (mLock) {
+                return mIndividualEnabled.get(sensor, false);
+            }
+        }
+
         /**
          * Returns the state of sensor privacy from persistent storage.
          */
-        private boolean readPersistedSensorPrivacyEnabledLocked() {
+        private void readPersistedSensorPrivacyStateLocked() {
             // if the file does not exist then sensor privacy has not yet been enabled on
             // the device.
             if (!mAtomicFile.exists()) {
-                return false;
+                return;
             }
-            boolean enabled;
             try (FileInputStream inputStream = mAtomicFile.openRead()) {
                 TypedXmlPullParser parser = Xml.resolvePullParser(inputStream);
                 XmlUtils.beginDocument(parser, XML_TAG_SENSOR_PRIVACY);
                 parser.next();
-                String tagName = parser.getName();
-                enabled = parser.getAttributeBoolean(null, XML_ATTRIBUTE_ENABLED, false);
+                mEnabled = parser.getAttributeBoolean(null, XML_ATTRIBUTE_ENABLED, false);
+
+                XmlUtils.nextElement(parser);
+                while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                    String tagName = parser.getName();
+                    if (XML_TAG_INDIVIDUAL_SENSOR_PRIVACY.equals(tagName)) {
+                        int sensor = XmlUtils.readIntAttribute(parser, XML_ATTRIBUTE_SENSOR);
+                        boolean enabled = XmlUtils.readBooleanAttribute(parser,
+                                XML_ATTRIBUTE_ENABLED);
+                        mIndividualEnabled.put(sensor, enabled);
+                        XmlUtils.skipCurrentTag(parser);
+                    } else {
+                        XmlUtils.nextElement(parser);
+                    }
+                }
+
             } catch (IOException | XmlPullParserException e) {
                 Log.e(TAG, "Caught an exception reading the state from storage: ", e);
                 // Delete the file to prevent the same error on subsequent calls and assume sensor
                 // privacy is not enabled.
                 mAtomicFile.delete();
-                enabled = false;
             }
-            return enabled;
         }
 
         /**
@@ -174,20 +327,33 @@
          */
         private void persistSensorPrivacyState() {
             synchronized (mLock) {
-                FileOutputStream outputStream = null;
-                try {
-                    outputStream = mAtomicFile.startWrite();
-                    TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream);
-                    serializer.startDocument(null, true);
-                    serializer.startTag(null, XML_TAG_SENSOR_PRIVACY);
-                    serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, mEnabled);
-                    serializer.endTag(null, XML_TAG_SENSOR_PRIVACY);
-                    serializer.endDocument();
-                    mAtomicFile.finishWrite(outputStream);
-                } catch (IOException e) {
-                    Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e);
-                    mAtomicFile.failWrite(outputStream);
+                persistSensorPrivacyStateLocked();
+            }
+        }
+
+        private void persistSensorPrivacyStateLocked() {
+            FileOutputStream outputStream = null;
+            try {
+                outputStream = mAtomicFile.startWrite();
+                TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream);
+                serializer.startDocument(null, true);
+                serializer.startTag(null, XML_TAG_SENSOR_PRIVACY);
+                serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, mEnabled);
+                int numIndividual = mIndividualEnabled.size();
+                for (int i = 0; i < numIndividual; i++) {
+                    serializer.startTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
+                    int sensor = mIndividualEnabled.keyAt(i);
+                    boolean enabled = mIndividualEnabled.valueAt(i);
+                    serializer.attributeInt(null, XML_ATTRIBUTE_SENSOR, sensor);
+                    serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enabled);
+                    serializer.endTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY);
                 }
+                serializer.endTag(null, XML_TAG_SENSOR_PRIVACY);
+                serializer.endDocument();
+                mAtomicFile.finishWrite(outputStream);
+            } catch (IOException e) {
+                Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e);
+                mAtomicFile.failWrite(outputStream);
             }
         }
 
@@ -212,6 +378,170 @@
             }
             mHandler.removeListener(listener);
         }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            Objects.requireNonNull(fd);
+
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
+            int opti = 0;
+            boolean dumpAsProto = false;
+            while (opti < args.length) {
+                String opt = args[opti];
+                if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+                    break;
+                }
+                opti++;
+                if ("--proto".equals(opt)) {
+                    dumpAsProto = true;
+                } else {
+                    pw.println("Unknown argument: " + opt + "; use -h for help");
+                }
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (dumpAsProto) {
+                    dump(new DualDumpOutputStream(new ProtoOutputStream(fd)));
+                } else {
+                    pw.println("SENSOR PRIVACY MANAGER STATE (dumpsys "
+                            + Context.SENSOR_PRIVACY_SERVICE + ")");
+
+                    dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, "  ")));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        /**
+         * Dump state to {@link DualDumpOutputStream}.
+         *
+         * @param dumpStream The destination to dump to
+         */
+        private void dump(@NonNull DualDumpOutputStream dumpStream) {
+            synchronized (mLock) {
+                dumpStream.write("is_enabled", SensorPrivacyServiceDumpProto.IS_ENABLED, mEnabled);
+
+                int numIndividualEnabled = mIndividualEnabled.size();
+                for (int i = 0; i < numIndividualEnabled; i++) {
+                    long token = dumpStream.start("individual_enabled_sensor",
+                            SensorPrivacyServiceDumpProto.INDIVIDUAL_ENABLED_SENSOR);
+
+                    dumpStream.write("sensor",
+                            SensorPrivacyIndividualEnabledSensorProto.SENSOR,
+                            mIndividualEnabled.keyAt(i));
+                    dumpStream.write("is_enabled",
+                            SensorPrivacyIndividualEnabledSensorProto.IS_ENABLED,
+                            mIndividualEnabled.valueAt(i));
+
+                    dumpStream.end(token);
+                }
+            }
+
+            dumpStream.flush();
+        }
+
+        /**
+         * Convert a string into a {@link SensorPrivacyManager.IndividualSensor id}.
+         *
+         * @param sensor The name to convert
+         *
+         * @return The id corresponding to the name
+         */
+        private @SensorPrivacyManager.IndividualSensor int sensorStrToId(@Nullable String sensor) {
+            if (sensor == null) {
+                return UNKNOWN;
+            }
+
+            switch (sensor) {
+                case "microphone":
+                    return MICROPHONE;
+                case "camera":
+                    return CAMERA;
+                default: {
+                    return UNKNOWN;
+                }
+            }
+        }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out,
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
+            (new ShellCommand() {
+                @Override
+                public int onCommand(String cmd) {
+                    if (cmd == null) {
+                        return handleDefaultCommands(cmd);
+                    }
+
+                    final PrintWriter pw = getOutPrintWriter();
+                    switch (cmd) {
+                        case "enable" : {
+                            int sensor = sensorStrToId(getNextArg());
+                            if (sensor == UNKNOWN) {
+                                pw.println("Invalid sensor");
+                                return -1;
+                            }
+
+                            setIndividualSensorPrivacy(sensor, true);
+                        }
+                        break;
+                        case "disable" : {
+                            int sensor = sensorStrToId(getNextArg());
+                            if (sensor == UNKNOWN) {
+                                pw.println("Invalid sensor");
+                                return -1;
+                            }
+
+                            setIndividualSensorPrivacy(sensor, false);
+                        }
+                        break;
+                        case "reset": {
+                            int sensor = sensorStrToId(getNextArg());
+                            if (sensor == UNKNOWN) {
+                                pw.println("Invalid sensor");
+                                return -1;
+                            }
+
+                            enforceSensorPrivacyPermission();
+
+                            synchronized (mLock) {
+                                mIndividualEnabled.delete(sensor);
+                                persistSensorPrivacyState();
+                            }
+                        }
+                        break;
+                        default:
+                            return handleDefaultCommands(cmd);
+                    }
+
+                    return 0;
+                }
+
+                @Override
+                public void onHelp() {
+                    final PrintWriter pw = getOutPrintWriter();
+
+                    pw.println("Sensor privacy manager (" + Context.SENSOR_PRIVACY_SERVICE
+                            + ") commands:");
+                    pw.println("  help");
+                    pw.println("    Print this help text.");
+                    pw.println("");
+                    pw.println("  enable SENSOR");
+                    pw.println("    Enable privacy for a certain sensor.");
+                    pw.println("");
+                    pw.println("  disable SENSOR");
+                    pw.println("    Disable privacy for a certain sensor.");
+                    pw.println("");
+                    pw.println("  reset SENSOR");
+                    pw.println("    Reset privacy state for a certain sensor.");
+                    pw.println("");
+                }
+            }).exec(this, in, out, err, args, callback, resultReceiver);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dbd27af4..c951fd4 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -177,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;
@@ -206,27 +207,6 @@
     private static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
             "persist.sys.vold_app_data_isolation_enabled";
 
-    // TODO(b/169327180): Will be fetched from the server, but for now, we emulate this in
-    // the system_server since it can write to DeviceConfig and MediaProvider can read it
-    private static final String PROP_TRANSCODE_ENABLED = "transcode_enabled";
-    private static final String PROP_TRANSCODE_DEFAULT = "transcode_default";
-    private static final String PROP_TRANSCODE_COMPAT_MANIFEST = "transcode_compat_manifest";
-    private static final boolean TRANSCODE_ENABLED_VALUE = false;
-    // Determines the default behavior of apps when transcode is enabled, AKA, Option A/Option B.
-    // If true, transcode by default (Option B). If false, don't transcode by default (Option A)
-    // For dogfood, we go with Option B
-    private static final boolean TRANSCODE_DEFAULT_VALUE = true;
-    // Format is <package_name>,<media_capability_bit_mask>,...
-    // media_capability_bit_mask is defined in MediaProvider/../TranscodeHelper.java:
-    // FLAG_HEVC = 1 << 0;
-    // FLAG_SLOW_MOTION = 1 << 1;
-    // FLAG_HDR_10 = 1 << 2;
-    // FLAG_HDR_10_PLUS = 1 << 3;
-    // FLAG_HDR_HLG = 1 << 4;
-    // FLAG_HDR_DOLBY_VISION = 1 << 5;
-    private static final String TRANSCODE_COMPAT_MANIFEST_VALUE =
-            "com.google.android.apps.photos,1";
-
     // How long we wait to reset storage, if we failed to call onMount on the
     // external storage service.
     public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
@@ -902,17 +882,7 @@
             ZramWriteback.scheduleZramWriteback(mContext);
         }
 
-        // TODO(b/169327180): Remove after setting up server-side DeviceConfig flags
-        // Set DeviceConfig values for transcoding that will be read by MediaProvider
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_ENABLED, String.valueOf(TRANSCODE_ENABLED_VALUE),
-                false /* makeDefault */);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_DEFAULT, String.valueOf(TRANSCODE_DEFAULT_VALUE),
-                false /* makeDefault */);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                PROP_TRANSCODE_COMPAT_MANIFEST, TRANSCODE_COMPAT_MANIFEST_VALUE,
-                false /* makeDefault */);
+        updateTranscodeEnabled();
     }
 
     /**
@@ -944,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.
@@ -3568,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) {
@@ -3586,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()]);
@@ -4409,14 +4395,7 @@
 
                     // Create package obb and data dir if it doesn't exist.
                     int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
-                    File file = new File(packageObbDir);
-                    if (!file.exists()) {
-                        vold.setupAppDir(packageObbDir, appUid);
-                    }
-                    file = new File(packageDataDir);
-                    if (!file.exists()) {
-                        vold.setupAppDir(packageDataDir, appUid);
-                    }
+                    vold.ensureAppDirsCreated(new String[] {packageObbDir, packageDataDir}, appUid);
                 }
             } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
                 Slog.e(TAG, "Unable to create obb and data directories for " + processName,e);
@@ -4496,6 +4475,15 @@
             return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid);
         }
 
+        @Override
+        public void freeCache(String volumeUuid, long freeBytes) {
+            try {
+                mStorageSessionController.freeCache(volumeUuid, freeBytes);
+            } catch (ExternalStorageServiceException e) {
+                Log.e(TAG, "Failed to free cache of vol : " + volumeUuid, e);
+            }
+        }
+
         public boolean hasExternalStorage(int uid, String packageName) {
             // No need to check for system uid. This avoids a deadlock between
             // PackageManagerService and AppOpsService.
@@ -4522,10 +4510,13 @@
                 // When using FUSE, we may need to kill the app if the op changes
                 switch(code) {
                     case OP_REQUEST_INSTALL_PACKAGES:
-                        if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) {
-                            // If we transition to/from MODE_ALLOWED, kill the app to make
-                            // sure it has the correct view of /storage. Changing between
-                            // MODE_DEFAULT / MODE_ERRORED is a no-op
+                        // In R, we used to kill the app here if it transitioned to/from
+                        // MODE_ALLOWED, to make sure the app had the correct (writable) OBB
+                        // view. But the majority of apps don't handle OBBs anyway, and for those
+                        // that do, they can restart themselves. Therefore, starting from S,
+                        // only kill the app when it transitions away from MODE_ALLOWED (eg,
+                        // when the permission is taken away).
+                        if (previousMode == MODE_ALLOWED && mode != MODE_ALLOWED) {
                             killAppForOpChange(code, uid);
                         }
                         return;
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 9d60b84..cb6e73a 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -60,12 +60,12 @@
     // Constants used on onUser(...)
     // NOTE: do not change their values, as they're used on Trace calls and changes might break
     // performance tests that rely on them.
-    private static final String USER_STARTING = "Start";
-    private static final String USER_UNLOCKING = "Unlocking";
-    private static final String USER_UNLOCKED = "Unlocked";
-    private static final String USER_SWITCHING = "Switch";
-    private static final String USER_STOPPING = "Stop";
-    private static final String USER_STOPPED = "Cleanup";
+    private static final String USER_STARTING = "Start"; // Logged as onStartUser
+    private static final String USER_UNLOCKING = "Unlocking"; // Logged as onUnlockingUser
+    private static final String USER_UNLOCKED = "Unlocked"; // Logged as onUnlockedUser
+    private static final String USER_SWITCHING = "Switch"; // Logged as onSwitchUser
+    private static final String USER_STOPPING = "Stop"; // Logged as onStopUser
+    private static final String USER_STOPPED = "Cleanup"; // Logged as onCleanupUser
 
     private static File sSystemDir;
     private final Context mContext;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 52eb77d..c476666 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2361,6 +2361,40 @@
         }
     }
 
+    /**
+     * Notify that the data enabled has changed.
+     *
+     * @param enabled True if data is enabled, otherwise disabled.
+     * @param reason  Reason for data enabled/disabled. See {@code DATA_*} in
+     *                {@link TelephonyManager}.
+     */
+    public void notifyDataEnabled(boolean enabled,
+                                  @TelephonyManager.DataEnabledReason int reason) {
+        if (!checkNotifyPermission("notifyDataEnabled()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason);
+        }
+
+        mIsDataEnabled = enabled;
+        mDataEnabledReason = reason;
+        synchronized (mRecords) {
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
+                    try {
+                        r.callback.onDataEnabledChanged(enabled, reason);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2413,6 +2447,8 @@
             pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
             pw.println("mDefaultSubId=" + mDefaultSubId);
             pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs);
+            pw.println("mIsDataEnabled=" + mIsDataEnabled);
+            pw.println("mDataEnabledReason=" + mDataEnabledReason);
 
             pw.decreaseIndent();
 
@@ -2665,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());
@@ -2823,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")
@@ -2848,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/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index a45466d..e8687e5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -61,9 +61,8 @@
 
 /** @hide */
 class TestNetworkService extends ITestNetworkManager.Stub {
-    @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
     @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent";
-    @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG;
+    @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = "TestNetworkProvider";
     @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
 
     @NonNull private final Context mContext;
@@ -108,23 +107,23 @@
 
         String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
         String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
-        return Binder.withCleanCallingIdentity(
-                () -> {
-                    try {
-                        ParcelFileDescriptor tunIntf =
-                                ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
-                        for (LinkAddress addr : linkAddrs) {
-                            mNetd.interfaceAddAddress(
-                                    iface,
-                                    addr.getAddress().getHostAddress(),
-                                    addr.getPrefixLength());
-                        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ParcelFileDescriptor tunIntf =
+                    ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
+            for (LinkAddress addr : linkAddrs) {
+                mNetd.interfaceAddAddress(
+                        iface,
+                        addr.getAddress().getHostAddress(),
+                        addr.getPrefixLength());
+            }
 
-                        return new TestNetworkInterface(tunIntf, iface);
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
-                });
+            return new TestNetworkInterface(tunIntf, iface);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /**
@@ -168,17 +167,15 @@
         private TestNetworkAgent(
                 @NonNull Context context,
                 @NonNull Looper looper,
-                @NonNull NetworkAgentConfig config,
                 @NonNull NetworkCapabilities nc,
                 @NonNull LinkProperties lp,
+                @NonNull NetworkAgentConfig config,
                 int uid,
                 @NonNull IBinder binder,
                 @NonNull NetworkProvider np)
                 throws RemoteException {
             super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np);
-
             mUid = uid;
-
             synchronized (mBinderLock) {
                 mBinder = binder; // Binder null-checks in create()
 
@@ -220,7 +217,7 @@
             // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
             // resources, even for binder death or unwanted calls.
             synchronized (mTestNetworkTracker) {
-                mTestNetworkTracker.remove(getNetwork().netId);
+                mTestNetworkTracker.remove(getNetwork().getNetId());
             }
         }
     }
@@ -286,8 +283,8 @@
             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
         }
 
-        final TestNetworkAgent agent = new TestNetworkAgent(context, looper,
-                new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder,
+        final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp,
+                new NetworkAgentConfig.Builder().build(), callingUid, binder,
                 mNetworkProvider);
         agent.register();
         agent.markConnected();
@@ -320,7 +317,12 @@
 
         try {
             // This requires NETWORK_STACK privileges.
-            Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mNMS.setInterfaceUp(iface);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
 
             // Synchronize all accesses to mTestNetworkTracker to prevent the case where:
             // 1. TestNetworkAgent successfully binds to death of binder
@@ -339,7 +341,7 @@
                                 administratorUids,
                                 binder);
 
-                mTestNetworkTracker.put(agent.getNetwork().netId, agent);
+                mTestNetworkTracker.put(agent.getNetwork().getNetId(), agent);
             }
         } catch (SocketException e) {
             throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 165b6a1..74e3851 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -25,24 +25,44 @@
 import android.net.NetworkRequest;
 import android.net.vcn.IVcnManagementService;
 import android.net.vcn.VcnConfig;
+import android.os.Binder;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.ServiceSpecificException;
+import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
+import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
  *
  * <pre>The internal structure of the VCN Management subsystem is as follows:
  *
- * +------------------------+ 1:1                                 +--------------------------------+
- * |  VcnManagementService  | ------------ Creates -------------> |  TelephonySubscriptionManager  |
- * |                        |                                     |                                |
- * | Manages configs and    |                                     | Tracks subscriptions, carrier  |
- * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps |
- * +------------------------+      carrier privilege changes      +--------------------------------+
+ * +-------------------------+ 1:1                                +--------------------------------+
+ * |  VcnManagementService   | ------------ Creates ------------> |  TelephonySubscriptionManager  |
+ * |                         |                                    |                                |
+ * |   Manages configs and   |                                    | Tracks subscriptions, carrier  |
+ * | Vcn instance lifecycles | <--- Notifies of subscription & -- | privilege changes, caches maps |
+ * +-------------------------+      carrier privilege changes     +--------------------------------+
  *      | 1:N          ^
  *      |              |
  *      |              +-------------------------------+
@@ -54,19 +74,19 @@
  *                      |                      mode state changes
  *                      v                              |
  * +-----------------------------------------------------------------------+
- * |                              VcnInstance                              |
+ * |                                  Vcn                                  |
  * |                                                                       |
- * |   Manages tunnel lifecycles based on fulfillable NetworkRequest(s)    |
- * |                        and overall safe-mode                          |
+ * |       Manages GatewayConnection lifecycles based on fulfillable       |
+ * |                NetworkRequest(s) and overall safe-mode                |
  * +-----------------------------------------------------------------------+
  *                      | 1:N                          ^
  *              Creates to fulfill                     |
- *           NetworkRequest(s), tears        Notifies of VcnTunnel
+ *           NetworkRequest(s), tears   Notifies of VcnGatewayConnection
  *          down when no longer needed   teardown (e.g. Network reaped)
  *                      |                 and safe-mode timer changes
  *                      v                              |
  * +-----------------------------------------------------------------------+
- * |                               VcnTunnel                               |
+ * |                          VcnGatewayConnection                         |
  * |                                                                       |
  * |       Manages a single (IKEv2) tunnel session and NetworkAgent,       |
  * |  handles mobility events, (IPsec) Tunnel setup and safe-mode timers   |
@@ -92,20 +112,72 @@
 
     public static final boolean VDBG = false; // STOPSHIP: if true
 
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String VCN_CONFIG_FILE = "/data/system/vcn/configs.xml";
+
     /* Binder context for this service */
     @NonNull private final Context mContext;
     @NonNull private final Dependencies mDeps;
 
     @NonNull private final Looper mLooper;
+    @NonNull private final Handler mHandler;
     @NonNull private final VcnNetworkProvider mNetworkProvider;
 
+    @GuardedBy("mLock")
+    @NonNull
+    private final Map<ParcelUuid, VcnConfig> mConfigs = new ArrayMap<>();
+
+    @NonNull private final Object mLock = new Object();
+
+    @NonNull private final PersistableBundleUtils.LockingReadWriteHelper mConfigDiskRwHelper;
+
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
         mContext = requireNonNull(context, "Missing context");
         mDeps = requireNonNull(deps, "Missing dependencies");
 
         mLooper = mDeps.getLooper();
+        mHandler = new Handler(mLooper);
         mNetworkProvider = new VcnNetworkProvider(mContext, mLooper);
+
+        mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
+
+        // Run on handler to ensure I/O does not block system server startup
+        mHandler.post(() -> {
+            PersistableBundle configBundle = null;
+            try {
+                configBundle = mConfigDiskRwHelper.readFromDisk();
+            } catch (IOException e1) {
+                Slog.e(TAG, "Failed to read configs from disk; retrying", e1);
+
+                // Retry immediately. The IOException may have been transient.
+                try {
+                    configBundle = mConfigDiskRwHelper.readFromDisk();
+                } catch (IOException e2) {
+                    Slog.wtf(TAG, "Failed to read configs from disk", e2);
+                    return;
+                }
+            }
+
+            if (configBundle != null) {
+                final Map<ParcelUuid, VcnConfig> configs =
+                        PersistableBundleUtils.toMap(
+                                configBundle,
+                                PersistableBundleUtils::toParcelUuid,
+                                VcnConfig::new);
+
+                synchronized (mLock) {
+                    for (Entry<ParcelUuid, VcnConfig> entry : configs.entrySet()) {
+                        // Ensure no new configs are overwritten; a carrier app may have added a new
+                        // config.
+                        if (!mConfigs.containsKey(entry.getKey())) {
+                            mConfigs.put(entry.getKey(), entry.getValue());
+                        }
+                    }
+                    // TODO: Trigger re-evaluation of active VCNs; start/stop VCNs as needed.
+                }
+            }
+        });
     }
 
     // Package-visibility for SystemServer to create instances.
@@ -130,16 +202,81 @@
             }
             return mHandlerThread.getLooper();
         }
+
+        /**
+         * Retrieves the caller's UID
+         *
+         * <p>This call MUST be made before calling {@link Binder#clearCallingIdentity}, otherwise
+         * this will not work properly.
+         *
+         * @return
+         */
+        public int getBinderCallingUid() {
+            return Binder.getCallingUid();
+        }
+
+        /**
+         * Creates and returns a new {@link PersistableBundle.LockingReadWriteHelper}
+         *
+         * @param path the file path to read/write from/to.
+         * @return the {@link PersistableBundleUtils.LockingReadWriteHelper} instance
+         */
+        public PersistableBundleUtils.LockingReadWriteHelper
+                newPersistableBundleLockingReadWriteHelper(@NonNull String path) {
+            return new PersistableBundleUtils.LockingReadWriteHelper(path);
+        }
     }
 
     /** Notifies the VcnManagementService that external dependencies can be set up. */
     public void systemReady() {
-        // TODO: Retrieve existing profiles from KeyStore
-
         mContext.getSystemService(ConnectivityManager.class)
                 .registerNetworkProvider(mNetworkProvider);
     }
 
+    private void enforcePrimaryUser() {
+        final int uid = mDeps.getBinderCallingUid();
+        if (uid == Process.SYSTEM_UID) {
+            throw new IllegalStateException(
+                    "Calling identity was System Server. Was Binder calling identity cleared?");
+        }
+
+        if (!UserHandle.getUserHandleForUid(uid).isSystem()) {
+            throw new SecurityException(
+                    "VcnManagementService can only be used by callers running as the primary user");
+        }
+    }
+
+    private void enforceCallingUserAndCarrierPrivilege(ParcelUuid subscriptionGroup) {
+        // Only apps running in the primary (system) user are allowed to configure the VCN. This is
+        // in line with Telephony's behavior with regards to binding to a Carrier App provided
+        // CarrierConfigService.
+        enforcePrimaryUser();
+
+        // TODO (b/172619301): Check based on events propagated from CarrierPrivilegesTracker
+        final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
+        final List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
+        Binder.withCleanCallingIdentity(
+                () -> {
+                    subscriptionInfos.addAll(subMgr.getSubscriptionsInGroup(subscriptionGroup));
+                });
+
+        final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class);
+        for (SubscriptionInfo info : subscriptionInfos) {
+            // Check subscription is active first; much cheaper/faster check, and an app (currently)
+            // cannot be carrier privileged for inactive subscriptions.
+            if (subMgr.isValidSlotIndex(info.getSimSlotIndex())
+                    && telMgr.hasCarrierPrivileges(info.getSubscriptionId())) {
+                // TODO (b/173717728): Allow configuration for inactive, but manageable
+                // subscriptions.
+                // TODO (b/173718661): Check for whole subscription groups at a time.
+                return;
+            }
+        }
+
+        throw new SecurityException(
+                "Carrier privilege required for subscription group to set VCN Config");
+    }
+
     /**
      * Sets a VCN config for a given subscription group.
      *
@@ -150,7 +287,17 @@
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
         requireNonNull(config, "config was null");
 
-        // TODO: Store VCN configuration, trigger startup as necessary
+        enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+
+        synchronized (mLock) {
+            mConfigs.put(subscriptionGroup, config);
+
+            // Must be done synchronously to ensure that writes do not happen out-of-order.
+            writeConfigsToDiskLocked();
+        }
+
+        // TODO: Clear Binder calling identity
+        // TODO: Trigger startup as necessary
     }
 
     /**
@@ -162,7 +309,40 @@
     public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
 
-        // TODO: Clear VCN configuration, trigger teardown as necessary
+        enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+
+        synchronized (mLock) {
+            mConfigs.remove(subscriptionGroup);
+
+            // Must be done synchronously to ensure that writes do not happen out-of-order.
+            writeConfigsToDiskLocked();
+        }
+
+        // TODO: Clear Binder calling identity
+        // TODO: Trigger teardown as necessary
+    }
+
+    @GuardedBy("mLock")
+    private void writeConfigsToDiskLocked() {
+        try {
+            PersistableBundle bundle =
+                    PersistableBundleUtils.fromMap(
+                            mConfigs,
+                            PersistableBundleUtils::fromParcelUuid,
+                            VcnConfig::toPersistableBundle);
+            mConfigDiskRwHelper.writeToDisk(bundle);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to save configs to disk", e);
+            throw new ServiceSpecificException(0, "Failed to save configs");
+        }
+    }
+
+    /** Get current configuration list for testing purposes */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    Map<ParcelUuid, VcnConfig> getConfigs() {
+        synchronized (mLock) {
+            return Collections.unmodifiableMap(mConfigs);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/VibratorManagerService.java b/services/core/java/com/android/server/VibratorManagerService.java
index f1f2815..eca1dfa 100644
--- a/services/core/java/com/android/server/VibratorManagerService.java
+++ b/services/core/java/com/android/server/VibratorManagerService.java
@@ -16,32 +16,85 @@
 
 package com.android.server;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.vibrator.IVibrator;
 import android.os.CombinedVibrationEffect;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IVibratorManagerService;
+import android.os.Looper;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.Trace;
 import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.os.VibratorInfo;
+import android.util.Slog;
+import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.vibrator.Vibration;
+import com.android.server.vibrator.VibrationScaler;
+import com.android.server.vibrator.VibrationSettings;
+import com.android.server.vibrator.VibratorController;
 
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.Arrays;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 /** System implementation of {@link IVibratorManagerService}. */
 public class VibratorManagerService extends IVibratorManagerService.Stub {
     private static final String TAG = "VibratorManagerService";
     private static final boolean DEBUG = false;
+    private static final VibrationAttributes DEFAULT_ATTRIBUTES =
+            new VibrationAttributes.Builder().build();
 
+    /** Lifecycle responsible for initializing this class at the right system server phases. */
+    public static class Lifecycle extends SystemService {
+        private VibratorManagerService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mService = new VibratorManagerService(getContext(), new Injector());
+            publishBinderService("vibrator_manager", mService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+                mService.systemReady();
+            }
+        }
+    }
+
+    private final Object mLock = new Object();
     private final Context mContext;
+    private final Handler mHandler;
+    private final AppOpsManager mAppOps;
     private final NativeWrapper mNativeWrapper;
     private final int[] mVibratorIds;
+    private final SparseArray<VibratorController> mVibrators;
+    @GuardedBy("mLock")
+    private final SparseArray<AlwaysOnVibration> mAlwaysOnEffects = new SparseArray<>();
+
+    private VibrationSettings mVibrationSettings;
+    private VibrationScaler mVibrationScaler;
 
     static native long nativeInit();
 
@@ -49,19 +102,53 @@
 
     static native int[] nativeGetVibratorIds(long nativeServicePtr);
 
-    VibratorManagerService(Context context) {
-        this(context, new Injector());
-    }
-
     @VisibleForTesting
     VibratorManagerService(Context context, Injector injector) {
         mContext = context;
+        mHandler = injector.createHandler(Looper.myLooper());
         mNativeWrapper = injector.getNativeWrapper();
-
         mNativeWrapper.init();
 
+        mAppOps = mContext.getSystemService(AppOpsManager.class);
+
         int[] vibratorIds = mNativeWrapper.getVibratorIds();
-        mVibratorIds = vibratorIds == null ? new int[0] : vibratorIds;
+        if (vibratorIds == null) {
+            mVibratorIds = new int[0];
+            mVibrators = new SparseArray<>(0);
+        } else {
+            // Keep original vibrator id order, which might be meaningful.
+            mVibratorIds = vibratorIds;
+            mVibrators = new SparseArray<>(mVibratorIds.length);
+            VibrationCompleteListener listener = new VibrationCompleteListener(this);
+            for (int vibratorId : vibratorIds) {
+                mVibrators.put(vibratorId, injector.createVibratorController(vibratorId, listener));
+            }
+        }
+    }
+
+    /** Finish initialization at boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */
+    @VisibleForTesting
+    void systemReady() {
+        Slog.v(TAG, "Initializing VibratorManager service...");
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "systemReady");
+        try {
+            mVibrationSettings = new VibrationSettings(mContext, mHandler);
+            mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
+
+            mVibrationSettings.addListener(this::updateServiceState);
+
+            updateServiceState();
+        } finally {
+            Slog.v(TAG, "VibratorManager service initialized");
+            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+        }
+    }
+
+    @Override // Binder call
+    @Nullable
+    public VibratorInfo getVibratorInfo(int vibratorId) {
+        VibratorController controller = mVibrators.get(vibratorId);
+        return controller == null ? null : controller.getVibratorInfo();
     }
 
     @Override // Binder call
@@ -70,7 +157,48 @@
     }
 
     @Override // Binder call
-    public void vibrate(int uid, String opPkg, CombinedVibrationEffect effect,
+    public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
+            @Nullable CombinedVibrationEffect effect, @Nullable VibrationAttributes attrs) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "setAlwaysOnEffect");
+        try {
+            if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
+                throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
+            }
+            if (effect == null) {
+                synchronized (mLock) {
+                    mAlwaysOnEffects.delete(alwaysOnId);
+                    onAllVibratorsLocked(v -> {
+                        if (v.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+                            v.updateAlwaysOn(alwaysOnId, /* effect= */ null);
+                        }
+                    });
+                }
+                return true;
+            }
+            if (!isEffectValid(effect)) {
+                return false;
+            }
+            attrs = fixupVibrationAttributes(attrs);
+            synchronized (mLock) {
+                SparseArray<VibrationEffect.Prebaked> effects = fixupAlwaysOnEffectsLocked(effect);
+                if (effects == null) {
+                    // Invalid effects set in CombinedVibrationEffect, or always-on capability is
+                    // missing on individual vibrators.
+                    return false;
+                }
+                AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration(
+                        alwaysOnId, uid, opPkg, attrs, effects);
+                mAlwaysOnEffects.put(alwaysOnId, alwaysOnVibration);
+                updateAlwaysOnLocked(alwaysOnVibration);
+            }
+            return true;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+        }
+    }
+
+    @Override // Binder call
+    public void vibrate(int uid, String opPkg, @NonNull CombinedVibrationEffect effect,
             @Nullable VibrationAttributes attrs, String reason, IBinder token) {
         throw new UnsupportedOperationException("Not implemented");
     }
@@ -86,6 +214,201 @@
         new VibratorManagerShellCommand(this).exec(this, in, out, err, args, cb, resultReceiver);
     }
 
+    private void updateServiceState() {
+        synchronized (mLock) {
+            for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
+                updateAlwaysOnLocked(mAlwaysOnEffects.valueAt(i));
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void updateAlwaysOnLocked(AlwaysOnVibration vib) {
+        for (int i = 0; i < vib.effects.size(); i++) {
+            VibratorController vibrator = mVibrators.get(vib.effects.keyAt(i));
+            VibrationEffect.Prebaked effect = vib.effects.valueAt(i);
+            if (vibrator == null) {
+                continue;
+            }
+            Vibration.Status ignoredStatus = shouldIgnoreVibrationLocked(
+                    vib.uid, vib.opPkg, vib.attrs);
+            if (ignoredStatus == null) {
+                effect = mVibrationScaler.scale(effect, vib.attrs.getUsage());
+            } else {
+                // Vibration should not run, use null effect to remove registered effect.
+                effect = null;
+            }
+            vibrator.updateAlwaysOn(vib.alwaysOnId, effect);
+        }
+    }
+
+    /**
+     * Check if a vibration with given {@code uid}, {@code opPkg} and {@code attrs} should be
+     * ignored by this service.
+     *
+     * @param uid   The user id of this vibration
+     * @param opPkg The package name of this vibration
+     * @param attrs The attributes of this vibration
+     * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored.
+     */
+    @GuardedBy("mLock")
+    @Nullable
+    private Vibration.Status shouldIgnoreVibrationLocked(int uid, String opPkg,
+            VibrationAttributes attrs) {
+        if (!mVibrationSettings.shouldVibrateForPowerMode(attrs.getUsage())) {
+            return Vibration.Status.IGNORED_FOR_POWER;
+        }
+
+        int intensity = mVibrationSettings.getCurrentIntensity(attrs.getUsage());
+        if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+            return Vibration.Status.IGNORED_FOR_SETTINGS;
+        }
+
+        if (!mVibrationSettings.shouldVibrateForRingerMode(attrs.getUsage())) {
+            if (DEBUG) {
+                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
+            }
+            return Vibration.Status.IGNORED_RINGTONE;
+        }
+
+        int mode = getAppOpMode(uid, opPkg, attrs);
+        if (mode != AppOpsManager.MODE_ALLOWED) {
+            if (mode == AppOpsManager.MODE_ERRORED) {
+                // We might be getting calls from within system_server, so we don't actually
+                // want to throw a SecurityException here.
+                Slog.w(TAG, "Would be an error: vibrate from uid " + uid);
+                return Vibration.Status.IGNORED_ERROR_APP_OPS;
+            } else {
+                return Vibration.Status.IGNORED_APP_OPS;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Check which mode should be set for a vibration with given {@code uid}, {@code opPkg} and
+     * {@code attrs}. This will return one of the AppOpsManager.MODE_*.
+     */
+    private int getAppOpMode(int uid, String opPkg, VibrationAttributes attrs) {
+        int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
+                attrs.getAudioUsage(), uid, opPkg);
+        if (mode == AppOpsManager.MODE_ALLOWED) {
+            mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, opPkg);
+        }
+        if (mode == AppOpsManager.MODE_IGNORED
+                && attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
+            // If we're just ignoring the vibration op then this is set by DND and we should ignore
+            // if we're asked to bypass. AppOps won't be able to record this operation, so make
+            // sure we at least note it in the logs for debugging.
+            Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid);
+            mode = AppOpsManager.MODE_ALLOWED;
+        }
+        return mode;
+    }
+
+    /**
+     * Validate the incoming {@link CombinedVibrationEffect}.
+     *
+     * We can't throw exceptions here since we might be called from some system_server component,
+     * which would bring the whole system down.
+     *
+     * @return whether the CombinedVibrationEffect is non-null and valid
+     */
+    private static boolean isEffectValid(@Nullable CombinedVibrationEffect effect) {
+        if (effect == null) {
+            Slog.wtf(TAG, "effect must not be null");
+            return false;
+        }
+        try {
+            effect.validate();
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Encountered issue when verifying CombinedVibrationEffect.", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Return new {@link VibrationAttributes} that only applies flags that this user has permissions
+     * to use.
+     */
+    private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs) {
+        if (attrs == null) {
+            attrs = DEFAULT_ATTRIBUTES;
+        }
+        if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
+            if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+                    || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+                    || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
+                final int flags = attrs.getFlags()
+                        & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+                attrs = new VibrationAttributes.Builder(attrs)
+                        .setFlags(flags, attrs.getFlags()).build();
+            }
+        }
+        return attrs;
+    }
+
+    @GuardedBy("mLock")
+    @Nullable
+    private SparseArray<VibrationEffect.Prebaked> fixupAlwaysOnEffectsLocked(
+            CombinedVibrationEffect effect) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "fixupAlwaysOnEffectsLocked");
+        try {
+            SparseArray<VibrationEffect> effects;
+            if (effect instanceof CombinedVibrationEffect.Mono) {
+                VibrationEffect syncedEffect = ((CombinedVibrationEffect.Mono) effect).getEffect();
+                effects = transformAllVibratorsLocked(unused -> syncedEffect);
+            } else if (effect instanceof CombinedVibrationEffect.Stereo) {
+                effects = ((CombinedVibrationEffect.Stereo) effect).getEffects();
+            } else {
+                // Only synced combinations can be used for always-on effects.
+                return null;
+            }
+            SparseArray<VibrationEffect.Prebaked> result = new SparseArray<>();
+            for (int i = 0; i < effects.size(); i++) {
+                VibrationEffect prebaked = effects.valueAt(i);
+                if (!(prebaked instanceof VibrationEffect.Prebaked)) {
+                    Slog.e(TAG, "Only prebaked effects supported for always-on.");
+                    return null;
+                }
+                int vibratorId = effects.keyAt(i);
+                VibratorController vibrator = mVibrators.get(vibratorId);
+                if (vibrator != null && vibrator.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+                    result.put(vibratorId, (VibrationEffect.Prebaked) prebaked);
+                }
+            }
+            if (result.size() == 0) {
+                return null;
+            }
+            return result;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+        }
+    }
+
+    private boolean hasPermission(String permission) {
+        return mContext.checkCallingOrSelfPermission(permission)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    @GuardedBy("mLock")
+    private void onAllVibratorsLocked(Consumer<VibratorController> consumer) {
+        for (int i = 0; i < mVibrators.size(); i++) {
+            consumer.accept(mVibrators.valueAt(i));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private <T> SparseArray<T> transformAllVibratorsLocked(Function<VibratorController, T> fn) {
+        SparseArray<T> ret = new SparseArray<>(mVibrators.size());
+        for (int i = 0; i < mVibrators.size(); i++) {
+            ret.put(mVibrators.keyAt(i), fn.apply(mVibrators.valueAt(i)));
+        }
+        return ret;
+    }
+
     /** Point of injection for test dependencies */
     @VisibleForTesting
     static class Injector {
@@ -93,6 +416,57 @@
         NativeWrapper getNativeWrapper() {
             return new NativeWrapper();
         }
+
+        Handler createHandler(Looper looper) {
+            return new Handler(looper);
+        }
+
+        VibratorController createVibratorController(int vibratorId,
+                VibratorController.OnVibrationCompleteListener listener) {
+            return new VibratorController(vibratorId, listener);
+        }
+    }
+
+    /**
+     * Implementation of {@link VibratorController.OnVibrationCompleteListener} with a weak
+     * reference to this service.
+     */
+    private static final class VibrationCompleteListener implements
+            VibratorController.OnVibrationCompleteListener {
+        private WeakReference<VibratorManagerService> mServiceRef;
+
+        VibrationCompleteListener(VibratorManagerService service) {
+            mServiceRef = new WeakReference<>(service);
+        }
+
+        @Override
+        public void onComplete(int vibratorId, long vibrationId) {
+            VibratorManagerService service = mServiceRef.get();
+            if (service != null) {
+                // TODO(b/159207608): finish vibration if all vibrators finished for this vibration
+            }
+        }
+    }
+
+    /**
+     * Combination of prekabed vibrations on multiple vibrators, with the same {@link
+     * VibrationAttributes}, that can be set for always-on effects.
+     */
+    private static final class AlwaysOnVibration {
+        public final int alwaysOnId;
+        public final int uid;
+        public final String opPkg;
+        public final VibrationAttributes attrs;
+        public final SparseArray<VibrationEffect.Prebaked> effects;
+
+        AlwaysOnVibration(int alwaysOnId, int uid, String opPkg, VibrationAttributes attrs,
+                SparseArray<VibrationEffect.Prebaked> effects) {
+            this.alwaysOnId = alwaysOnId;
+            this.uid = uid;
+            this.opPkg = opPkg;
+            this.attrs = attrs;
+            this.effects = effects;
+        }
     }
 
     /** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */
@@ -120,7 +494,7 @@
         }
     }
 
-    /** Provides limited functionality from {@link VibratorManagerService} as shell commands. */
+    /** Provide limited functionality from {@link VibratorManagerService} as shell commands. */
     private final class VibratorManagerShellCommand extends ShellCommand {
 
         private final IBinder mToken;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index db2b4e4..6a9715e 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
-import android.app.IUidObserver;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -37,9 +36,6 @@
 import android.os.IVibratorStateListener;
 import android.os.Looper;
 import android.os.PowerManager;
-import android.os.PowerManager.ServiceType;
-import android.os.PowerManagerInternal;
-import android.os.PowerSaveState;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -51,9 +47,9 @@
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.os.VibratorInfo;
 import android.os.WorkSource;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
@@ -73,7 +69,6 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /** System implementation of {@link IVibratorService}. */
@@ -95,7 +90,6 @@
     private final LinkedList<Vibration.DebugInfo> mPreviousExternalVibrations;
     private final LinkedList<Vibration.DebugInfo> mPreviousVibrations;
     private final int mPreviousVibrationsLimit;
-    private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
     private final WorkSource mTmpWorkSource = new WorkSource();
     private final Handler mH;
     private final Object mLock = new Object();
@@ -106,7 +100,6 @@
     private final AppOpsManager mAppOps;
     private final IBatteryStats mBatteryStatsService;
     private final String mSystemUiPackage;
-    private PowerManagerInternal mPowerManagerInternal;
     private VibrationSettings mVibrationSettings;
     private VibrationScaler mVibrationScaler;
     private InputDeviceDelegate mInputDeviceDelegate;
@@ -119,31 +112,6 @@
     private VibrationDeathRecipient mCurrentVibrationDeathRecipient;
     private int mCurVibUid = -1;
     private ExternalVibrationHolder mCurrentExternalVibration;
-    private boolean mLowPowerMode;
-    private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>();
-
-    private final IUidObserver mUidObserver = new IUidObserver.Stub() {
-        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
-                int capability) {
-            mProcStatesCache.put(uid, procState);
-        }
-
-        @Override public void onUidGone(int uid, boolean disabled) {
-            mProcStatesCache.delete(uid);
-        }
-
-        @Override
-        public void onUidActive(int uid) {
-        }
-
-        @Override
-        public void onUidIdle(int uid, boolean disabled) {
-        }
-
-        @Override
-        public void onUidCachedChanged(int uid, boolean cached) {
-        }
-    };
 
     /**
      * Implementation of {@link OnVibrationCompleteListener} with a weak reference to this service.
@@ -277,37 +245,15 @@
             mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
             mInputDeviceDelegate = new InputDeviceDelegate(mContext, mH);
 
-            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
-            mPowerManagerInternal.registerLowPowerModeObserver(
-                    new PowerManagerInternal.LowPowerModeListener() {
-                        @Override
-                        public int getServiceType() {
-                            return ServiceType.VIBRATION;
-                        }
-
-                        @Override
-                        public void onLowPowerModeChanged(PowerSaveState result) {
-                            updateVibrators();
-                        }
-            });
-
             mVibrationSettings.addListener(this::updateVibrators);
 
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-                    updateVibrators();
+                    mVibrationSettings.updateSettings();
                 }
             }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
 
-            try {
-                ActivityManager.getService().registerUidObserver(mUidObserver,
-                        ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
-                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
-            } catch (RemoteException e) {
-                // ignored; both services live in system_server
-            }
-
             updateVibrators();
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
@@ -346,6 +292,11 @@
     }
 
     @Override // Binder call
+    public VibratorInfo getVibratorInfo() {
+        return mVibratorController.getVibratorInfo();
+    }
+
+    @Override // Binder call
     public boolean registerVibratorStateListener(IVibratorStateListener listener) {
         if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) {
             throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission");
@@ -369,61 +320,6 @@
                 || mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL);
     }
 
-    @Override // Binder call
-    public int[] areEffectsSupported(int[] effectIds) {
-        return mVibratorController.areEffectsSupported(effectIds);
-    }
-
-    @Override // Binder call
-    public boolean[] arePrimitivesSupported(int[] primitiveIds) {
-        return mVibratorController.arePrimitivesSupported(primitiveIds);
-    }
-
-    private static List<Integer> asList(int... vals) {
-        if (vals == null) {
-            return null;
-        }
-        List<Integer> l = new ArrayList<>(vals.length);
-        for (int val : vals) {
-            l.add(val);
-        }
-        return l;
-    }
-
-    @Override // Binder call
-    public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
-            VibrationAttributes attrs) {
-        if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
-            throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
-        }
-        if (!mVibratorController.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
-            Slog.e(TAG, "Always-on effects not supported.");
-            return false;
-        }
-        if (effect == null) {
-            synchronized (mLock) {
-                mAlwaysOnEffects.delete(alwaysOnId);
-                mVibratorController.updateAlwaysOn(alwaysOnId, /* effect= */ null);
-            }
-        } else {
-            if (!verifyVibrationEffect(effect)) {
-                return false;
-            }
-            if (!(effect instanceof VibrationEffect.Prebaked)) {
-                Slog.e(TAG, "Only prebaked effects supported for always-on.");
-                return false;
-            }
-            attrs = fixupVibrationAttributes(attrs);
-            synchronized (mLock) {
-                Vibration vib = new Vibration(null, mNextVibrationId.getAndIncrement(), effect,
-                        attrs, uid, opPkg, null);
-                mAlwaysOnEffects.put(alwaysOnId, vib);
-                updateAlwaysOnLocked(alwaysOnId, vib);
-            }
-        }
-        return true;
-    }
-
     private void verifyIncomingUid(int uid) {
         if (uid == Binder.getCallingUid()) {
             return;
@@ -543,9 +439,7 @@
                     return;
                 }
 
-                if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
-                        > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-                        && !isNotification(vib) && !isRingtone(vib) && !isAlarm(vib)) {
+                if (!mVibrationSettings.shouldVibrateForUid(uid, vib.attrs.getUsage())) {
                     Slog.e(TAG, "Ignoring incoming vibration as process with"
                             + " uid= " + uid + " is background,"
                             + " attrs= " + vib.attrs);
@@ -582,16 +476,19 @@
 
     private void endVibrationLocked(Vibration vib, Vibration.Status status) {
         final LinkedList<Vibration.DebugInfo> previousVibrations;
-        if (isRingtone(vib)) {
-            previousVibrations = mPreviousRingVibrations;
-        } else if (isNotification(vib)) {
-            previousVibrations = mPreviousNotificationVibrations;
-        } else if (isAlarm(vib)) {
-            previousVibrations = mPreviousAlarmVibrations;
-        } else {
-            previousVibrations = mPreviousVibrations;
+        switch (vib.attrs.getUsage()) {
+            case VibrationAttributes.USAGE_NOTIFICATION:
+                previousVibrations = mPreviousNotificationVibrations;
+                break;
+            case VibrationAttributes.USAGE_RINGTONE:
+                previousVibrations = mPreviousRingVibrations;
+                break;
+            case VibrationAttributes.USAGE_ALARM:
+                previousVibrations = mPreviousAlarmVibrations;
+                break;
+            default:
+                previousVibrations = mPreviousVibrations;
         }
-
         if (previousVibrations.size() > mPreviousVibrationsLimit) {
             previousVibrations.removeFirst();
         }
@@ -706,17 +603,6 @@
         }
     }
 
-    private boolean shouldVibrateForPowerModeLocked(Vibration vib) {
-        if (!mLowPowerMode) {
-            return true;
-        }
-
-        int usage = vib.attrs.getUsage();
-        return usage == VibrationAttributes.USAGE_RINGTONE
-                || usage == VibrationAttributes.USAGE_ALARM
-                || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
-    }
-
     /** Scale the vibration effect by the intensity as appropriate based its intent. */
     private void applyVibrationIntensityScalingLocked(Vibration vib) {
         vib.updateEffect(mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage()));
@@ -744,7 +630,7 @@
     }
 
     private boolean shouldVibrate(Vibration vib) {
-        if (!shouldVibrateForPowerModeLocked(vib)) {
+        if (!mVibrationSettings.shouldVibrateForPowerMode(vib.attrs.getUsage())) {
             endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_POWER);
             return false;
         }
@@ -755,7 +641,7 @@
             return false;
         }
 
-        if (isRingtone(vib) && !mVibrationSettings.shouldVibrateForRingtone()) {
+        if (!mVibrationSettings.shouldVibrateForRingerMode(vib.attrs.getUsage())) {
             if (DEBUG) {
                 Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
             }
@@ -769,7 +655,7 @@
                 // We might be getting calls from within system_server, so we don't actually
                 // want to throw a SecurityException here.
                 Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid);
-                endVibrationLocked(vib, Vibration.Status.ERROR_APP_OPS);
+                endVibrationLocked(vib, Vibration.Status.IGNORED_ERROR_APP_OPS);
             } else {
                 endVibrationLocked(vib, Vibration.Status.IGNORED_APP_OPS);
             }
@@ -821,44 +707,11 @@
 
     private void updateVibrators() {
         synchronized (mLock) {
-            boolean devicesUpdated = mInputDeviceDelegate.updateInputDeviceVibrators(
+            mInputDeviceDelegate.updateInputDeviceVibrators(
                     mVibrationSettings.shouldVibrateInputDevices());
-            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
 
-            if (devicesUpdated || lowPowerModeUpdated) {
-                // If the state changes out from under us then just reset.
-                doCancelVibrateLocked(Vibration.Status.CANCELLED);
-            }
-
-            updateAlwaysOnLocked();
-        }
-    }
-
-    private boolean updateLowPowerModeLocked() {
-        boolean lowPowerMode = mPowerManagerInternal
-                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
-        if (lowPowerMode != mLowPowerMode) {
-            mLowPowerMode = lowPowerMode;
-            return true;
-        }
-        return false;
-    }
-
-    private void updateAlwaysOnLocked(int id, Vibration vib) {
-        VibrationEffect.Prebaked effect;
-        if (!shouldVibrate(vib)) {
-            effect = null;
-        } else {
-            effect = mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage());
-        }
-        mVibratorController.updateAlwaysOn(id, effect);
-    }
-
-    private void updateAlwaysOnLocked() {
-        for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
-            int id = mAlwaysOnEffects.keyAt(i);
-            Vibration vib = mAlwaysOnEffects.valueAt(i);
-            updateAlwaysOnLocked(id, vib);
+            // If the state changes out from under us then just reset.
+            doCancelVibrateLocked(Vibration.Status.CANCELLED);
         }
     }
 
@@ -994,23 +847,10 @@
 
     }
 
-    private static boolean isNotification(Vibration vib) {
-        return vib.attrs.getUsage() == VibrationAttributes.USAGE_NOTIFICATION;
-    }
-
-    private static boolean isRingtone(Vibration vib) {
-        return vib.attrs.getUsage() == VibrationAttributes.USAGE_RINGTONE;
-    }
-
-    private static boolean isHapticFeedback(Vibration vib) {
-        return vib.attrs.getUsage() == VibrationAttributes.USAGE_TOUCH;
-    }
-
-    private static boolean isAlarm(Vibration vib) {
-        return vib.attrs.getUsage() == VibrationAttributes.USAGE_ALARM;
-    }
-
-    private boolean isFromSystem(Vibration vib) {
+    private boolean isSystemHapticFeedback(Vibration vib) {
+        if (vib.attrs.getUsage() != VibrationAttributes.USAGE_TOUCH) {
+            return false;
+        }
         return vib.uid == Process.SYSTEM_UID || vib.uid == 0 || mSystemUiPackage.equals(vib.opPkg);
     }
 
@@ -1050,7 +890,6 @@
             } else {
                 pw.println("null");
             }
-            pw.println("  mLowPowerMode=" + mLowPowerMode);
             pw.println("  mVibratorController=" + mVibratorController);
             pw.println("  mVibrationSettings=" + mVibrationSettings);
             pw.println();
@@ -1097,7 +936,6 @@
             proto.write(VibratorServiceDumpProto.IS_VIBRATING, mVibratorController.isVibrating());
             proto.write(VibratorServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL,
                     mVibratorController.isUnderExternalControl());
-            proto.write(VibratorServiceDumpProto.LOW_POWER_MODE, mLowPowerMode);
             proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
                     mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH));
             proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
@@ -1289,7 +1127,7 @@
     static class Injector {
 
         VibratorController createVibratorController(OnVibrationCompleteListener listener) {
-            return new VibratorController(/* vibratorId= */ 0, listener);
+            return new VibratorController(/* vibratorId= */ -1, listener);
         }
 
         Handler createHandler(Looper looper) {
@@ -1311,9 +1149,7 @@
                     // them.  However it may happen that the system is currently playing
                     // haptic feedback as part of the transition.  So we don't cancel
                     // system vibrations.
-                    if (mCurrentVibration != null
-                            && !(isHapticFeedback(mCurrentVibration)
-                                && isFromSystem(mCurrentVibration))) {
+                    if (mCurrentVibration != null && !isSystemHapticFeedback(mCurrentVibration)) {
                         doCancelVibrateLocked(Vibration.Status.CANCELLED);
                     }
                 }
@@ -1373,7 +1209,7 @@
                 vibHolder.scale = SCALE_MUTE;
                 if (mode == AppOpsManager.MODE_ERRORED) {
                     Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid());
-                    endVibrationLocked(vibHolder, Vibration.Status.ERROR_APP_OPS);
+                    endVibrationLocked(vibHolder, Vibration.Status.IGNORED_ERROR_APP_OPS);
                 } else {
                     endVibrationLocked(vibHolder, Vibration.Status.IGNORED_APP_OPS);
                 }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 9a94e4e..15e31ba 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3085,7 +3085,8 @@
                     .setContentTitle(title)
                     .setContentText(subtitle)
                     .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent,
-                            PendingIntent.FLAG_CANCEL_CURRENT, null, user))
+                            PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+                            null, user))
                     .build();
         installNotification(getCredentialPermissionNotificationId(
                 account, authTokenType, uid), n, packageName, user.getIdentifier());
@@ -5307,7 +5308,8 @@
                         .setContentTitle(String.format(notificationTitleFormat, account.name))
                         .setContentText(message)
                         .setContentIntent(PendingIntent.getActivityAsUser(
-                                mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+                                mContext, 0, intent,
+                                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
                                 null, new UserHandle(userId)))
                         .build();
                 installNotification(id, n, packageName, userId);
diff --git a/services/core/java/com/android/server/adb/OWNERS b/services/core/java/com/android/server/adb/OWNERS
new file mode 100644
index 0000000..b97f795
--- /dev/null
+++ b/services/core/java/com/android/server/adb/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/adb:/OWNERS
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index dffe0ba..5fde046 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -19,7 +19,6 @@
 import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
 import static android.os.Process.NFC_UID;
@@ -168,6 +167,8 @@
     public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION = 16;
     public static final int FGS_FEATURE_ALLOWED_BY_FGS_BINDING = 17;
     public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE = 18;
+    public static final int FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD = 19;
+    public static final int FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES = 20;
 
     @IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = {
             FGS_FEATURE_DENIED,
@@ -187,7 +188,9 @@
             FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST,
             FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION,
             FGS_FEATURE_ALLOWED_BY_FGS_BINDING,
-            FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE
+            FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE,
+            FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD,
+            FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FgsFeatureRetCode {}
@@ -274,6 +277,13 @@
     static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L;
 
     /**
+     * If set to false for a package, the system will *not* exempt it from FGS-BG-start,
+     * even if it's in {#code ActiveServices.sFgsBgStartExemptedPackages}.
+     */
+    @ChangeId
+    static final long FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID = 175801883;
+
+    /**
      * If a service can not become foreground service due to BG-FGS-launch restriction or other
      * reasons, throws an IllegalStateException.
      */
@@ -281,6 +291,25 @@
     @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
     static final long FGS_START_EXCEPTION_CHANGE_ID = 174041399L;
 
+    /**
+     * Special allowlist that contains packages that are allowed to start FGS even if they target S,
+     * without using START_FOREGROUND_SERVICES_FROM_BACKGROUND.
+     *
+     * Note: we exempt FGS starts if either the "callee" or "caller" match any of the emempted
+     * packages. This means:
+     * - Exempted apps could call Context.startForegroundService() for services owned by any other
+     *   apps.
+     * - Any apps could call Context.startForegroundService() for services owned by any exempted
+     *   apps.
+     * And the call would succeed.
+     */
+    private static final ArraySet<String> sFgsBgStartExemptedPackages = new ArraySet<>();
+
+    static {
+        sFgsBgStartExemptedPackages.add("com.google.pixel.exo.bootstrapping"); //STOPSHIP Remove it.
+        sFgsBgStartExemptedPackages.add("com.android.chrome"); // STOPSHIP Remove it.
+    }
+
     final Runnable mLastAnrDumpClearer = new Runnable() {
         @Override public void run() {
             synchronized (mAm) {
@@ -1754,7 +1783,7 @@
                         // The service might have been stopped or exited foreground state
                         // in the interval, so we lazy check whether we still need to show
                         // the notification.
-                        if (r.isForeground) {
+                        if (r.isForeground && r.app != null) {
                             r.postNotification();
                         } else if (DEBUG_FOREGROUND_SERVICE) {
                             Slog.d(TAG_SERVICE, "  - service no longer running/fg, ignoring");
@@ -1859,7 +1888,7 @@
         private final AppOpsManager.OnOpNotedListener mOpNotedCallback =
                 new AppOpsManager.OnOpNotedListener() {
                     @Override
-                    public void onOpNoted(int op, int uid, String pkgName, int result) {
+                    public void onOpNoted(int op, int uid, String pkgName, int flags, int result) {
                         incrementOpCountIfNeeded(op, uid, result);
                     }
         };
@@ -1867,7 +1896,8 @@
         private final AppOpsManager.OnOpStartedListener mOpStartedCallback =
                 new AppOpsManager.OnOpStartedListener() {
                     @Override
-                    public void onOpStarted(int op, int uid, String pkgName, int result) {
+                    public void onOpStarted(int op, int uid, String pkgName, int flags,
+                            int result) {
                         incrementOpCountIfNeeded(op, uid, result);
                     }
         };
@@ -5243,10 +5273,14 @@
         if (ret == FGS_FEATURE_DENIED) {
             for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
                 final ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i);
-                if (pr.uid == callingUid
-                        && pr.mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
-                    ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
-                    break;
+                if (pr.uid == callingUid) {
+                    if (pr.mAllowStartFgs) {
+                        ret = FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD;
+                        break;
+                    } else if (pr.isAllowedStartFgsState()) {
+                        ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+                        break;
+                    }
                 }
             }
         }
@@ -5285,8 +5319,7 @@
         }
 
         if (ret == FGS_FEATURE_DENIED) {
-            if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled
-                    && mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) {
+            if (mAm.isWhitelistedForFgsStartLocked(callingUid)) {
                 // uid is on DeviceIdleController's user/system allowlist
                 // or AMS's FgsStartTempAllowList.
                 ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
@@ -5299,6 +5332,14 @@
             }
         }
 
+        // NOTE this should always be the last check.
+        if (ret == FGS_FEATURE_DENIED) {
+            if (isPackageExemptedFromFgsRestriction(r.appInfo.packageName, r.appInfo.uid)
+                    || isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
+                ret = FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES;
+            }
+        }
+
         final String debugInfo =
                 "[callingPackage: " + callingPackage
                         + "; callingUid: " + callingUid
@@ -5316,6 +5357,13 @@
         return ret;
     }
 
+    private boolean isPackageExemptedFromFgsRestriction(String packageName, int uid) {
+        if (!sFgsBgStartExemptedPackages.contains(packageName)) {
+            return false;
+        }
+        return CompatChanges.isChangeEnabled(FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID, uid);
+    }
+
     private static String fgsCodeToString(@FgsFeatureRetCode int code) {
         switch (code) {
             case FGS_FEATURE_DENIED:
@@ -5354,6 +5402,10 @@
                 return "ALLOWED_BY_FGS_BINDING";
             case FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE:
                 return "ALLOWED_BY_DEVICE_DEMO_MODE";
+            case FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD:
+                return "ALLOWED_BY_PROCESS_RECORD";
+            case FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES:
+                return "FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES";
             default:
                 return "";
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index b4e856b..b0f296f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -167,13 +167,6 @@
             "default_fgs_starts_restriction_enabled";
 
     /**
-     * Default value for mFlagFgsStartTempAllowListEnabled if not explicitly set in
-     * Settings.Global.
-     */
-    private static final String KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED =
-            "default_fgs_starts_temp_allowlist_enabled";
-
-    /**
      * Whether FGS notification display is deferred following the transition into
      * the foreground state.  Default behavior is {@code true} unless overridden.
      */
@@ -372,10 +365,6 @@
     // at all.
     volatile boolean mFlagFgsStartRestrictionEnabled = false;
 
-    // When the foreground service background start restriction is enabled, if the app in
-    // DeviceIdleController's Temp AllowList is allowed to bypass the restriction.
-    volatile boolean mFlagFgsStartTempAllowListEnabled = false;
-
     // Whether we defer FGS notifications a few seconds following their transition to
     // the foreground state.  Applies only to S+ apps; enabled by default.
     volatile boolean mFlagFgsNotificationDeferralEnabled = true;
@@ -540,9 +529,6 @@
                             case KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED:
                                 updateFgsStartsRestriction();
                                 break;
-                            case KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED:
-                                updateFgsStartsTempAllowList();
-                                break;
                             case KEY_DEFERRED_FGS_NOTIFICATIONS_ENABLED:
                                 updateFgsNotificationDeferralEnable();
                                 break;
@@ -809,13 +795,6 @@
                 /*defaultValue*/ false);
     }
 
-    private void updateFgsStartsTempAllowList() {
-        mFlagFgsStartTempAllowListEnabled = DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED,
-                /*defaultValue*/ false);
-    }
-
     private void updateFgsNotificationDeferralEnable() {
         mFlagFgsNotificationDeferralEnabled = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0f9e9ee..1841d67 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -174,6 +174,7 @@
 import android.app.WaitResult;
 import android.app.backup.BackupManager.OperationType;
 import android.app.backup.IBackupManager;
+import android.app.compat.CompatChanges;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStatsManager;
@@ -5674,11 +5675,6 @@
     }
 
     @Override
-    public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
-        return mActivityTaskManager.getTaskSnapshot(taskId, isLowResolution);
-    }
-
-    @Override
     public void resizeTask(int taskId, Rect bounds, int resizeMode) {
         mActivityTaskManager.resizeTask(taskId, bounds, resizeMode);
     }
@@ -11251,6 +11247,10 @@
                 // set on ION VMAs, therefore consider the entire ION heap as used kernel memory
                 kernelUsed += ionHeap;
             }
+            final long gpuUsage = Debug.getGpuTotalUsageKb();
+            if (gpuUsage >= 0) {
+                pw.print("      GPU: "); pw.println(stringifyKBSize(gpuUsage));
+            }
             final long lostRAM = memInfo.getTotalSizeKb()
                     - (ss[INDEX_TOTAL_PSS] - ss[INDEX_TOTAL_SWAP_PSS])
                     - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
@@ -12045,6 +12045,12 @@
             // set on ION VMAs, therefore consider the entire ION heap as used kernel memory
             kernelUsed += ionHeap;
         }
+        final long gpuUsage = Debug.getGpuTotalUsageKb();
+        if (gpuUsage >= 0) {
+            memInfoBuilder.append("       GPU: ");
+            memInfoBuilder.append(stringifyKBSize(gpuUsage));
+            memInfoBuilder.append("\n");
+        }
         memInfoBuilder.append("  Used RAM: ");
         memInfoBuilder.append(stringifyKBSize(
                                   totalPss - cachedPss + kernelUsed));
@@ -13713,6 +13719,37 @@
                     forceStopPackageLocked(packageName, -1, false, true, true,
                             false, false, userId, "package unstartable");
                     break;
+                case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
+                    if (!canCloseSystemDialogs(callingPid, callingUid, callerApp)) {
+                        // The app can't close system dialogs, throw only if it targets S+
+                        if (CompatChanges.isChangeEnabled(
+                                ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, callingUid)) {
+                            throw new SecurityException(
+                                    "Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
+                                            + " broadcast from " + callerPackage + " (pid="
+                                            + callingPid + ", uid=" + callingUid + ")"
+                                            + " requires "
+                                            + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + ".");
+                        } else if (CompatChanges.isChangeEnabled(
+                                ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, callingUid)) {
+                            Slog.w(TAG, "Permission Denial: " + intent.getAction()
+                                    + " broadcast from " + callerPackage + " (pid=" + callingPid
+                                    + ", uid=" + callingUid + ")"
+                                    + " requires "
+                                    + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
+                                    + ", dropping broadcast.");
+                            // Returning success seems to be the pattern here
+                            return ActivityManager.BROADCAST_SUCCESS;
+                        } else {
+                            Slog.w(TAG, intent.getAction()
+                                    + " broadcast from " + callerPackage + " (pid=" + callingPid
+                                    + ", uid=" + callingUid + ")"
+                                    + " will require  "
+                                    + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
+                                    + " in future builds.");
+                        }
+                    }
+                    break;
             }
 
             if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
@@ -14005,6 +14042,32 @@
         return ActivityManager.BROADCAST_SUCCESS;
     }
 
+    private boolean canCloseSystemDialogs(int pid, int uid, @Nullable ProcessRecord callerApp) {
+        if (checkPermission(permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, pid, uid)
+                == PERMISSION_GRANTED) {
+            return true;
+        }
+        if (callerApp == null) {
+            synchronized (mPidsSelfLocked) {
+                callerApp = mPidsSelfLocked.get(pid);
+            }
+        }
+        // Check if the instrumentation of the process has the permission. This covers the usual
+        // test started from the shell (which has the permission) case. This is needed for apps
+        // targeting SDK level < S but we are also allowing for targetSdk S+ as a convenience to
+        // avoid breaking a bunch of existing tests and asking them to adopt shell permissions to do
+        // this.
+        if (callerApp != null) {
+            ActiveInstrumentation instrumentation = callerApp.getActiveInstrumentation();
+            if (instrumentation != null && checkPermission(
+                    permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, -1, instrumentation.mSourceUid)
+                    == PERMISSION_GRANTED) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1
      */
@@ -14610,11 +14673,11 @@
 
     @Override
     public int getLaunchedFromUid(IBinder activityToken) {
-        return mActivityTaskManager.getLaunchedFromUid(activityToken);
+        return ActivityClient.getInstance().getLaunchedFromUid(activityToken);
     }
 
     public String getLaunchedFromPackage(IBinder activityToken) {
-        return mActivityTaskManager.getLaunchedFromPackage(activityToken);
+        return ActivityClient.getInstance().getLaunchedFromPackage(activityToken);
     }
 
     // =========================================================
@@ -15704,6 +15767,11 @@
         return mUserController.getCurrentUser();
     }
 
+    @Override
+    public @UserIdInt int getCurrentUserId() {
+        return mUserController.getCurrentUserIdChecked();
+    }
+
     String getStartedUserState(int userId) {
         final UserState userState = mUserController.getStartedUserState(userId);
         return UserState.stateToString(userState.state);
@@ -16322,7 +16390,7 @@
             final ActivityClient ac = ActivityClient.getInstance();
             return new ActivityPresentationInfo(ac.getTaskForActivity(token,
                     /*onlyRoot=*/ false), ac.getDisplayId(token),
-                    mActivityTaskManager.getActivityClassForToken(token));
+                    mAtmInternal.getActivityName(token));
         }
 
         @Override
@@ -17225,8 +17293,6 @@
                     throw new SecurityException("Shell can delegate permissions only "
                             + "to one instrumentation at a time");
                 }
-                delegate.setPermissions(permissions);
-                return;
             }
 
             final int instrCount = mActiveInstrumentation.size();
@@ -17269,7 +17335,8 @@
 
     private class ShellDelegate implements CheckOpsDelegate {
         private final int mTargetUid;
-        private @Nullable String[] mPermissions;
+        @Nullable
+        private final String[] mPermissions;
 
         ShellDelegate(int targetUid, @Nullable String[] permissions) {
             mTargetUid = targetUid;
@@ -17280,11 +17347,6 @@
             return mTargetUid;
         }
 
-        void setPermissions(@Nullable String[] permissions) {
-            mPermissions = permissions;
-            PackageManager.invalidatePackageInfoCache();
-        }
-
         @Override
         public int checkOperation(int code, int uid, String packageName, boolean raw,
                 QuadFunction<Integer, Integer, String, Boolean, Integer> superImpl) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index e3c071f..12fe3ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -118,7 +118,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -1842,9 +1841,11 @@
     }
 
     int runGetCurrentUser(PrintWriter pw) throws RemoteException {
-        UserInfo currentUser = Objects.requireNonNull(mInterface.getCurrentUser(),
-                "Current user not set");
-        pw.println(currentUser.id);
+        int userId = mInterface.getCurrentUserId();
+        if (userId == UserHandle.USER_NULL) {
+            throw new IllegalStateException("Current user not set");
+        }
+        pw.println(userId);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 0b4d27f..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;
         }
     }
 
@@ -756,8 +772,9 @@
     boolean handleAppCrashLocked(ProcessRecord app, String reason,
             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
         final long now = SystemClock.uptimeMillis();
-        final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+        final boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ANR_SHOW_BACKGROUND, 0,
+                mService.mUserController.getCurrentUserId()) != 0;
 
         final boolean procIsBoundForeground =
             (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
@@ -812,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);
                 }
@@ -889,8 +904,9 @@
 
     void handleShowAppErrorUi(Message msg) {
         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
-        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+        boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ANR_SHOW_BACKGROUND, 0,
+                mService.mUserController.getCurrentUserId()) != 0;
 
         final int userId;
         synchronized (mService) {
@@ -982,8 +998,9 @@
                 return;
             }
 
-            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+            boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.ANR_SHOW_BACKGROUND, 0,
+                    mService.mUserController.getCurrentUserId()) != 0;
             if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
                 proc.getDialogController().showAnrDialogs(data);
             } else {
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index ca20224..6fe934e 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.am;
 
+import static com.android.internal.power.MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
+
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
@@ -34,6 +36,7 @@
 import android.telephony.TelephonyManager;
 import android.util.IntArray;
 import android.util.Slog;
+import android.util.SparseLongArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BatteryStatsImpl;
@@ -43,6 +46,8 @@
 
 import libcore.util.EmptyArray;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -129,9 +134,13 @@
     // WiFi keeps an accumulated total of stats, unlike Bluetooth.
     // Keep the last WiFi stats so we can compute a delta.
     @GuardedBy("mWorkerLock")
-    private WifiActivityEnergyInfo mLastInfo =
+    private WifiActivityEnergyInfo mLastWifiInfo =
             new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
 
+    /** Snapshot of measured energies, or null if no measured energies are supported. */
+    @GuardedBy("mWorkerLock")
+    private final @Nullable MeasuredEnergySnapshot mMeasuredEnergySnapshot;
+
     /**
      * Timestamp at which all external stats were last collected in
      * {@link SystemClock#elapsedRealtime()} time base.
@@ -139,9 +148,13 @@
     @GuardedBy("this")
     private long mLastCollectionTimeStamp;
 
-    BatteryExternalStatsWorker(Context context, BatteryStatsImpl stats) {
+    BatteryExternalStatsWorker(Context context, BatteryStatsImpl stats,
+            @Nullable MeasuredEnergyArray initialMeasuredEnergies) {
         mContext = context;
         mStats = stats;
+
+        mMeasuredEnergySnapshot = initialMeasuredEnergies == null ?
+                null : new MeasuredEnergySnapshot(initialMeasuredEnergies);
     }
 
     @Override
@@ -417,7 +430,6 @@
         SynchronousResultReceiver bluetoothReceiver = null;
         CompletableFuture<ModemActivityInfo> modemFuture = CompletableFuture.completedFuture(null);
         boolean railUpdated = false;
-        MeasuredEnergyArray energyArray = null;
 
         if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
             // We were asked to fetch WiFi data.
@@ -495,13 +507,6 @@
             }
         }
 
-        if ((updateFlags & UPDATE_ENERGY) != 0) {
-            synchronized (mStats) {
-                // TODO(b/172934873) evaluate a safe way to query the HAL without holding mStats
-                energyArray = mStats.getEnergyConsumptionDataLocked();
-            }
-        }
-
         final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
         final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
         ModemActivityInfo modemInfo = null;
@@ -513,6 +518,9 @@
         } catch (ExecutionException e) {
             Slog.w(TAG, "exception reading modem stats: " + e.getCause());
         }
+        final SparseLongArray energyDeltas = mMeasuredEnergySnapshot == null ? null :
+                mMeasuredEnergySnapshot.updateAndGetDelta(getMeasuredEnergyLocked(updateFlags));
+
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
         final long elapsedRealtimeUs = elapsedRealtime * 1000;
@@ -542,6 +550,13 @@
                 mStats.updateRpmStatsLocked(elapsedRealtimeUs);
             }
 
+            // Inform mStats about each applicable measured energy.
+            if (energyDeltas != null) {
+                final long displayEnergy = energyDeltas.get(SUBSYSTEM_DISPLAY, 0L);
+                // Always pass in what BatteryExternalStatsWorker thinks screenState is.
+                mStats.updateDisplayEnergyLocked(displayEnergy, screenState, elapsedRealtime);
+            }
+
             if (bluetoothInfo != null) {
                 if (bluetoothInfo.isValid()) {
                     mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime);
@@ -549,11 +564,6 @@
                     Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo);
                 }
             }
-
-            if ((updateFlags & UPDATE_ENERGY) != 0 && energyArray != null) {
-                // Always use what BatteryExternalStatsWorker thinks screenState is.
-                mStats.updateMeasuredEnergyStatsLocked(energyArray, screenState);
-            }
         }
 
         // WiFi and Modem state are updated without the mStats lock held, because they
@@ -561,7 +571,9 @@
 
         if (wifiInfo != null) {
             if (wifiInfo.isValid()) {
-                mStats.updateWifiState(extractDeltaLocked(wifiInfo), elapsedRealtime, uptime);
+                // TODO: wifiEnergyDelta = energyDeltas.get(MeasuredEnergyArray.SUBSYSTEM_WIFI, 0L);
+                mStats.updateWifiState(extractDeltaLocked(wifiInfo)
+                        /*, TODO: wifiEnergyDelta */, elapsedRealtime, uptime);
             } else {
                 Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
             }
@@ -570,6 +582,11 @@
         if (modemInfo != null) {
             mStats.updateMobileRadioState(modemInfo, elapsedRealtime, uptime);
         }
+
+        if (updateFlags == UPDATE_ALL) {
+            // This helps mStats deal with ignoring data from prior to resets.
+            mStats.informThatAllExternalStatsAreFlushed();
+        }
     }
 
     /**
@@ -604,12 +621,12 @@
     @GuardedBy("mWorkerLock")
     private WifiActivityEnergyInfo extractDeltaLocked(WifiActivityEnergyInfo latest) {
         final long timePeriodMs = latest.getTimeSinceBootMillis()
-                - mLastInfo.getTimeSinceBootMillis();
-        final long lastScanMs = mLastInfo.getControllerScanDurationMillis();
-        final long lastIdleMs = mLastInfo.getControllerIdleDurationMillis();
-        final long lastTxMs = mLastInfo.getControllerTxDurationMillis();
-        final long lastRxMs = mLastInfo.getControllerRxDurationMillis();
-        final long lastEnergy = mLastInfo.getControllerEnergyUsedMicroJoules();
+                - mLastWifiInfo.getTimeSinceBootMillis();
+        final long lastScanMs = mLastWifiInfo.getControllerScanDurationMillis();
+        final long lastIdleMs = mLastWifiInfo.getControllerIdleDurationMillis();
+        final long lastTxMs = mLastWifiInfo.getControllerTxDurationMillis();
+        final long lastRxMs = mLastWifiInfo.getControllerRxDurationMillis();
+        final long lastEnergy = mLastWifiInfo.getControllerEnergyUsedMicroJoules();
 
         final long deltaTimeSinceBootMillis = latest.getTimeSinceBootMillis();
         final int deltaStackState = latest.getStackState();
@@ -657,7 +674,7 @@
             wasReset = false;
         }
 
-        mLastInfo = latest;
+        mLastWifiInfo = latest;
         WifiActivityEnergyInfo delta = new WifiActivityEnergyInfo(
                 deltaTimeSinceBootMillis,
                 deltaStackState,
@@ -671,4 +688,39 @@
         }
         return delta;
     }
+
+    // TODO(b/172934873): Evaluate a safe way to query the HAL without holding mStats
+    /** Fetch MeasuredEnergyArray for supported subsystems based on the given updateFlags. */
+    @GuardedBy("mWorkerLock")
+    private @Nullable MeasuredEnergyArray getMeasuredEnergyLocked(@ExternalUpdateFlag int flags) {
+        if (mMeasuredEnergySnapshot == null) return null;
+
+        if (flags == UPDATE_ALL) {
+            // Gotta catch 'em all... including custom (non-specific) subsystems
+            synchronized (mStats) {
+                return mStats.getEnergyConsumptionDataLocked();
+            }
+        }
+
+        final List<Integer> energyConsumerIds = new ArrayList<>();
+        if ((flags & UPDATE_DISPLAY) != 0) {
+            addEnergyConsumerIdLocked(energyConsumerIds, SUBSYSTEM_DISPLAY);
+        }
+        // TODO: Wifi, Bluetooth, etc., go here
+        if (energyConsumerIds.isEmpty()) {
+            return null;
+        }
+        synchronized (mStats) {
+            // TODO: Query *specific* subsystems from HAL based on energyConsumerIds.toArray()
+            return mStats.getEnergyConsumptionDataLocked();
+        }
+    }
+
+    @GuardedBy("mWorkerLock")
+    private void addEnergyConsumerIdLocked(List<Integer> energyConsumerIds,
+            @MeasuredEnergyArray.MeasuredEnergySubsystem int consumerId) {
+        if (mMeasuredEnergySnapshot.hasSubsystem(consumerId)) {
+            energyConsumerIds.add(consumerId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3b6f0ac..083e970 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -26,6 +27,7 @@
 import android.os.BatteryStats;
 import android.os.BatteryStatsInternal;
 import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -64,6 +66,8 @@
 import com.android.internal.os.RailStats;
 import com.android.internal.os.RpmStats;
 import com.android.internal.power.MeasuredEnergyArray;
+import com.android.internal.power.MeasuredEnergyArray.MeasuredEnergySubsystem;
+import com.android.internal.power.MeasuredEnergyStats;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.ParseUtils;
@@ -196,7 +200,7 @@
     }
 
     @Override
-    public MeasuredEnergyArray getEnergyConsumptionData() {
+    public @Nullable MeasuredEnergyArray getEnergyConsumptionData() {
         final EnergyConsumerResult[] results = mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
         if (results == null) return null;
         final int size = results.length;
@@ -254,9 +258,11 @@
         mPowerStatsHALWrapper = new PowerStatsHALWrapper.PowerStatsHALWrapperImpl();
         mPowerStatsHALWrapper.initialize();
 
+        final MeasuredEnergyArray initialEnergies = getEnergyConsumptionData();
+        final boolean[] supportedBuckets = getSupportedEnergyBuckets(initialEnergies);
         mStats = new BatteryStatsImpl(systemDir, handler, this,
-                this, mUserManagerUserInfoProvider);
-        mWorker = new BatteryExternalStatsWorker(context, mStats);
+                this, supportedBuckets, mUserManagerUserInfoProvider);
+        mWorker = new BatteryExternalStatsWorker(context, mStats, initialEnergies);
         mStats.setExternalStatsSyncLocked(mWorker);
         mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_radioScanningTimeout) * 1000L);
@@ -264,6 +270,30 @@
         mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats);
     }
 
+    /**
+     * Map the {@link MeasuredEnergySubsystem}s in the given energyArray to their corresponding
+     * {@link MeasuredEnergyStats.EnergyBucket}s.
+     *
+     * @return array with true for index i if energy bucket i is supported.
+     */
+    private static @Nullable boolean[] getSupportedEnergyBuckets(MeasuredEnergyArray energyArray) {
+        if (energyArray == null) {
+            return null;
+        }
+        final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
+        final int size = energyArray.size();
+        for (int energyIdx = 0; energyIdx < size; energyIdx++) {
+            switch (energyArray.getSubsystem(energyIdx)) {
+                case MeasuredEnergyArray.SUBSYSTEM_DISPLAY:
+                    buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON] = true;
+                    buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE] = true;
+                    buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER] = true;
+                    break;
+            }
+        }
+        return buckets;
+    }
+
     public void publish() {
         LocalServices.addService(BatteryStatsInternal.class, new LocalService());
         ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
@@ -558,10 +588,10 @@
      * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
      * and per-UID basis.
      */
-    public BatteryUsageStats getBatteryUsageStats() {
+    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.BATTERY_STATS, null);
-        return mBatteryUsageStatsProvider.getBatteryUsageStats();
+        return mBatteryUsageStatsProvider.getBatteryUsageStats(query);
     }
 
     public byte[] getStatistics() {
@@ -1095,6 +1125,8 @@
                 }
             });
         }
+        FrameworkStatsLog.write_non_chained(
+                FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
     }
 
     public void notePhoneOn() {
@@ -1400,6 +1432,8 @@
                 }
             });
         }
+        FrameworkStatsLog.write_non_chained(
+                FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
     }
 
     public void noteWifiRunning(final WorkSource ws) {
@@ -2029,7 +2063,7 @@
     private void dumpMeasuredEnergyStats(PrintWriter pw) {
         // Wait for the completion of pending works if there is any
         awaitCompletion();
-        syncStats("dump", BatteryExternalStatsWorker.UPDATE_ENERGY);
+        syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
         synchronized (mStats) {
             mStats.dumpMeasuredEnergyStatsLocked(pw);
         }
@@ -2129,7 +2163,6 @@
                         pw.println("Battery stats reset.");
                         noOutput = true;
                     }
-                    mWorker.scheduleSync("dump", BatteryExternalStatsWorker.UPDATE_ALL);
                 } else if ("--write".equals(arg)) {
                     awaitCompletion();
                     syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
@@ -2239,6 +2272,7 @@
                                 in.setDataPosition(0);
                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
                                         null, mStats.mHandler, null, null,
+                                        null /* energy buckets not currently in checkin anyway */,
                                         mUserManagerUserInfoProvider);
                                 checkinStats.readSummaryFromParcel(in);
                                 in.recycle();
@@ -2279,6 +2313,7 @@
                                 in.setDataPosition(0);
                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
                                         null, mStats.mHandler, null, null,
+                                        null /* energy buckets not currently in checkin anyway */,
                                         mUserManagerUserInfoProvider);
                                 checkinStats.readSummaryFromParcel(in);
                                 in.recycle();
diff --git a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
new file mode 100644
index 0000000..b915c0c
--- /dev/null
+++ b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
@@ -0,0 +1,148 @@
+/*
+ * 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.am;
+
+
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.util.SparseLongArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.power.MeasuredEnergyArray;
+import com.android.internal.power.MeasuredEnergyArray.MeasuredEnergySubsystem;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Keeps snapshots of data from previously pulled MeasuredEnergyArrays.
+ */
+@VisibleForTesting
+public class MeasuredEnergySnapshot {
+    private static final String TAG = "MeasuredEnergySnapshot";
+
+    private static final long UNAVAILABLE = -1;
+
+    /**
+     * Energy snapshots from the last time each {@link MeasuredEnergySubsystem} was updated.
+     *
+     * Note that the snapshots for different subsystems may have been taken at different times.
+     *
+     * A snapshot is {@link #UNAVAILABLE} if the subsystem has never been updated (ie. unsupported).
+     */
+    private final long[] mMeasuredEnergySnapshots;
+
+    /**
+     * Constructor that initializes to the given energyArray;
+     * all subsystems not mentioned in initialEnergyArray are set to UNAVAILABLE.
+     */
+    public MeasuredEnergySnapshot(MeasuredEnergyArray initialEnergyArray) {
+        this(MeasuredEnergyArray.NUMBER_SUBSYSTEMS, initialEnergyArray);
+    }
+
+    /**
+     * Constructor (for testing) that initializes to the given energyArray and numSubsystems;
+     * all subsystems not mentioned in initialEnergyArray are set to UNAVAILABLE.
+     */
+    @VisibleForTesting
+    MeasuredEnergySnapshot(int numSubsystems, MeasuredEnergyArray initialEnergyArray) {
+        if (initialEnergyArray.size() > numSubsystems) {
+            throw new IllegalArgumentException("Energy array contains " + initialEnergyArray.size()
+                    + " subsystems, which exceeds the maximum allowed of " + numSubsystems);
+        }
+        mMeasuredEnergySnapshots = new long[numSubsystems];
+        Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
+        fillGivenSubsystems(initialEnergyArray);
+    }
+
+    /**
+     * For the subsystems present in energyArray, overwrites mMeasuredEnergySnapshots with their
+     * energy values from energyArray.
+     */
+    private void fillGivenSubsystems(MeasuredEnergyArray energyArray) {
+        final int size = energyArray.size();
+        for (int i = 0; i < size; i++) {
+            final int subsystem = energyArray.getSubsystem(i);
+            mMeasuredEnergySnapshots[subsystem] = energyArray.getEnergy(i);
+        }
+    }
+
+    /**
+     * Update with the some freshly measured energies and return the difference (delta)
+     * between the previously stored values and the passed-in values.
+     *
+     * @param energyArray measured energy array for some (possibly not all) subsystems.
+     *
+     * @return a map from the updated subsystems to their corresponding energy deltas.
+     *         Subsystems not present in energyArray will not appear.
+     *         Subsystems with no difference in energy will not appear.
+     *         Returns null, if energyArray is null.
+     */
+    public @Nullable SparseLongArray updateAndGetDelta(MeasuredEnergyArray energyArray) {
+        if (energyArray == null) {
+            return null;
+        }
+        final SparseLongArray delta = new SparseLongArray();
+        final int size = energyArray.size();
+        for (int i = 0; i < size; i++) {
+            final int updatedSubsystem = energyArray.getSubsystem(i);
+            final long newEnergyUJ = energyArray.getEnergy(i);
+            final long oldEnergyUJ = mMeasuredEnergySnapshots[updatedSubsystem];
+
+            // If this is the first valid energy, there is no delta to take.
+            if (oldEnergyUJ < 0) continue;
+            final long deltaUJ = newEnergyUJ - oldEnergyUJ;
+            if (deltaUJ == 0) continue;
+            if (deltaUJ < 0) {
+                Slog.e(TAG, "For subsystem " + updatedSubsystem + ", new energy (" + newEnergyUJ
+                        + ") is less than old energy (" + oldEnergyUJ + "). Skipping. ");
+                continue;
+            }
+            delta.put(updatedSubsystem, deltaUJ);
+        }
+
+        fillGivenSubsystems(energyArray);
+
+        return delta;
+    }
+
+    /**
+     * Check if a subsystem's measured energy is available.
+     * @param subsystem which subsystem.
+     * @return true if subsystem is available.
+     */
+    public boolean hasSubsystem(@MeasuredEnergySubsystem int subsystem) {
+        return mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE;
+    }
+
+    /** Dump debug data. */
+    public void dump(PrintWriter pw) {
+        pw.println("Measured energy snapshot (microjoules):");
+        pw.print("   ");
+        for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
+            final long energyUJ = mMeasuredEnergySnapshots[i];
+            if (energyUJ == UNAVAILABLE) continue;
+            pw.print(MeasuredEnergyArray.SUBSYSTEM_NAMES[i]);
+            pw.print(" : ");
+            pw.print(energyUJ);
+            if (i != MeasuredEnergyArray.NUMBER_SUBSYSTEMS - 1) {
+                pw.print(", ");
+            }
+        }
+        pw.println();
+    }
+}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 60530c4..9e79b02 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -23,6 +23,8 @@
 
 # Battery Stats
 joeo@google.com
+per-file BatteryStats* = file:/BATTERY_STATS_OWNERS
+per-file BatteryExternalStats* = file:/BATTERY_STATS_OWNERS
 
 # Londoners
 michaelwr@google.com
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 771f273..5b3e651 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1329,7 +1329,7 @@
         app.setCached(false);
         app.shouldNotFreeze = false;
 
-        app.mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
+        app.resetAllowStartFgs();
 
         final int appUid = app.info.uid;
         final int logUid = mService.mCurOomAdjUid;
@@ -1351,7 +1351,6 @@
             app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
             app.curCapability = PROCESS_CAPABILITY_ALL;
             app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
-            app.bumpAllowStartFgsState(PROCESS_STATE_PERSISTENT);
             // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
             // facilitate this, here we need to determine whether or not it
@@ -1382,6 +1381,8 @@
             app.setCurRawProcState(app.getCurProcState());
             app.curAdj = app.maxAdj;
             app.completedAdjSeq = app.adjSeq;
+            app.bumpAllowStartFgsState(app.getCurProcState());
+            app.setAllowStartFgs();
             // if curAdj is less than prevAppAdj, then this process was promoted
             return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
         }
@@ -1773,6 +1774,11 @@
                     int clientAdj = client.getCurRawAdj();
                     int clientProcState = client.getCurRawProcState();
 
+                    // pass client's mAllowStartFgs to the app if client is not persistent process.
+                    if (client.mAllowStartFgs && client.maxAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+                        app.mAllowStartFgs = true;
+                    }
+
                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                         if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
                             continue;
@@ -2236,7 +2242,7 @@
         app.setCurRawProcState(procState);
         app.setHasForegroundActivities(foregroundActivities);
         app.completedAdjSeq = mAdjSeq;
-
+        app.setAllowStartFgs();
         // if curAdj or curProcState improved, then this process was promoted
         return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState
                 || app.curCapability != prevCapability ;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index cf4adc6..255badd 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -16,7 +16,16 @@
 
 package com.android.server.am;
 
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
+import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
+import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
 
 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
@@ -361,6 +370,17 @@
 
     private final ArraySet<Binder> mBackgroundFgsStartTokens = new ArraySet<>();
 
+    // The list of permissions that can start FGS from background.
+    private static String[] ALLOW_BG_START_FGS_PERMISSIONS =
+            {START_ACTIVITIES_FROM_BACKGROUND, START_FOREGROUND_SERVICES_FROM_BACKGROUND,
+                    SYSTEM_ALERT_WINDOW};
+    // Does the process has permission to start FGS from background.
+    boolean mAllowStartFgsByPermission;
+    // Can this process start FGS from background?
+    // If this process has the ability to start FGS from background, this ability can be passed to
+    // another process through service binding.
+    boolean mAllowStartFgs;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
         this.startUid = startUid;
@@ -476,6 +496,9 @@
                 pw.println();
         pw.print(prefix); pw.print("allowStartFgsState=");
                 pw.println(mAllowStartFgsState);
+        if (mAllowStartFgs) {
+            pw.print(prefix); pw.print("allowStartFgs="); pw.println(mAllowStartFgs);
+        }
         if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) {
             pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
                     pw.print(" pendingUiClean="); pw.print(mPendingUiClean);
@@ -672,6 +695,7 @@
         mWindowProcessController = new WindowProcessController(
                 mService.mActivityTaskManager, info, processName, uid, userId, this, this);
         pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
+        setAllowStartFgsByPermission();
     }
 
     public void setPid(int _pid) {
@@ -1983,12 +2007,78 @@
         return mDialogController;
     }
 
+    void resetAllowStartFgs() {
+        mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
+        mAllowStartFgs = mAllowStartFgsByPermission;
+    }
+
     void bumpAllowStartFgsState(int newProcState) {
         if (newProcState < mAllowStartFgsState) {
             mAllowStartFgsState = newProcState;
         }
     }
 
+    void setAllowStartFgsByPermission() {
+        boolean ret = false;
+        if (!ret) {
+            boolean isSystem = false;
+            final int uid = UserHandle.getAppId(info.uid);
+            switch (uid) {
+                case ROOT_UID:
+                case SYSTEM_UID:
+                case NFC_UID:
+                case SHELL_UID:
+                    isSystem = true;
+                    break;
+                default:
+                    isSystem = false;
+                    break;
+            }
+
+            if (isSystem) {
+                ret = true;
+            }
+        }
+
+        if (!ret) {
+            for (int i = 0; i < ALLOW_BG_START_FGS_PERMISSIONS.length; ++i) {
+                if (ActivityManager.checkComponentPermission(ALLOW_BG_START_FGS_PERMISSIONS[i],
+                        info.uid, -1, true)
+                        == PERMISSION_GRANTED) {
+                    ret = true;
+                    break;
+                }
+            }
+        }
+        mAllowStartFgs = mAllowStartFgsByPermission = ret;
+    }
+
+    boolean isAllowedStartFgsState() {
+        return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+    }
+
+    void setAllowStartFgs() {
+        if (mAllowStartFgs) {
+            return;
+        }
+        if (!mAllowStartFgs) {
+            mAllowStartFgs = isAllowedStartFgsState();
+        }
+
+        if (!mAllowStartFgs) {
+            // Is the calling UID a device owner app?
+            if (mService.mInternal != null) {
+                mAllowStartFgs = mService.mInternal.isDeviceOwner(info.uid);
+            }
+        }
+
+        if (!mAllowStartFgs) {
+            // uid is on DeviceIdleController's user/system allowlist
+            // or AMS's FgsStartTempAllowList.
+            mAllowStartFgs = mService.isWhitelistedForFgsStartLocked(info.uid);
+        }
+    }
+
     /** A controller to generate error dialogs in {@link ProcessRecord} */
     class ErrorDialogController {
         /** dialogs being displayed due to crash */
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 12fcc9c..c04f6ff 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2173,7 +2173,7 @@
         }
     }
 
-    UserInfo getCurrentUser() {
+    private void checkGetCurrentUserPermissions() {
         if ((mInjector.checkCallingPermission(INTERACT_ACROSS_USERS)
                 != PackageManager.PERMISSION_GRANTED) && (
                 mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
@@ -2185,8 +2185,12 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
+    }
 
-        // Optimization - if there is no pending user switch, return current id
+    UserInfo getCurrentUser() {
+        checkGetCurrentUserPermissions();
+
+        // Optimization - if there is no pending user switch, return user for current id
         // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile)
         if (mTargetUserId == UserHandle.USER_NULL) {
             return getUserInfo(mCurrentUserId);
@@ -2196,9 +2200,23 @@
         }
     }
 
+    /**
+     * Gets the current user id, but checking that caller has the proper permissions.
+     */
+    int getCurrentUserIdChecked() {
+        checkGetCurrentUserPermissions();
+
+        // Optimization - if there is no pending user switch, return current id
+        // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile)
+        if (mTargetUserId == UserHandle.USER_NULL) {
+            return mCurrentUserId;
+        }
+        return getCurrentOrTargetUserId();
+    }
+
     @GuardedBy("mLock")
     UserInfo getCurrentUserLU() {
-        int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
+        int userId = getCurrentOrTargetUserIdLU();
         return getUserInfo(userId);
     }
 
@@ -2213,7 +2231,6 @@
         return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
     }
 
-
     @GuardedBy("mLock")
     int getCurrentUserIdLU() {
         return mCurrentUserId;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index d4e2d27..360ed9d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -93,6 +93,7 @@
 import android.app.AsyncNotedAppOp;
 import android.app.RuntimeAppOpAccessMessage;
 import android.app.SyncNotedAppOp;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -273,6 +274,8 @@
 
     private final AppOpsManagerInternalImpl mAppOpsManagerInternal
             = new AppOpsManagerInternalImpl();
+    @Nullable private final DevicePolicyManagerInternal dpmi =
+            LocalServices.getService(DevicePolicyManagerInternal.class);
 
     private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface(
             ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
@@ -2690,6 +2693,10 @@
                     Ops pkgOps = ent.getValue();
                     for (int j=pkgOps.size()-1; j>=0; j--) {
                         Op curOp = pkgOps.valueAt(j);
+                        if (shouldDeferResetOpToDpm(curOp.op)) {
+                            deferResetOpToDpm(curOp.op, reqPackageName, reqUserId);
+                            continue;
+                        }
                         if (AppOpsManager.opAllowsReset(curOp.op)
                                 && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
                             int previousMode = curOp.mode;
@@ -2739,16 +2746,27 @@
             }
         }
 
-        if (allChanges != null) {
-            int numChanges = allChanges.size();
-            for (int i = 0; i < numChanges; i++) {
-                ChangeRec change = allChanges.get(i);
-                notifyOpChangedSync(change.op, change.uid, change.pkg,
-                        AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
-            }
+        int numChanges = allChanges.size();
+        for (int i = 0; i < numChanges; i++) {
+            ChangeRec change = allChanges.get(i);
+            notifyOpChangedSync(change.op, change.uid, change.pkg,
+                    AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
         }
     }
 
+    private boolean shouldDeferResetOpToDpm(int op) {
+        // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
+        //  pre-grants to a role-based mechanism or another general-purpose mechanism.
+        return dpmi != null && dpmi.supportsResetOp(op);
+    }
+
+    /** Assumes {@link #shouldDeferResetOpToDpm(int)} is true. */
+    private void deferResetOpToDpm(int op, String packageName, @UserIdInt int userId) {
+        // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
+        //  pre-grants to a role-based mechanism or another general-purpose mechanism.
+        dpmi.resetOp(op, packageName, userId);
+    }
+
     private void evalAllForegroundOpsLocked() {
         for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
             final UidState uidState = mUidStates.valueAt(uidi);
@@ -3090,7 +3108,7 @@
             final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass,
                     true /* edit */);
             if (ops == null) {
-                scheduleOpNotedIfNeededLocked(code, uid, packageName,
+                scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
                         AppOpsManager.MODE_IGNORED);
                 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -3098,7 +3116,7 @@
             }
             final Op op = getOpLocked(ops, code, uid, true);
             if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
-                scheduleOpNotedIfNeededLocked(code, uid, packageName,
+                scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
                         AppOpsManager.MODE_IGNORED);
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -3120,7 +3138,7 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
                     attributedOp.rejected(uidState.state, flags);
-                    scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
+                    scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, uidMode);
                     return uidMode;
                 }
             } else {
@@ -3132,7 +3150,7 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
                     attributedOp.rejected(uidState.state, flags);
-                    scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
+                    scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, mode);
                     return mode;
                 }
             }
@@ -3142,7 +3160,8 @@
                                 + packageName + (attributionTag == null ? ""
                                 : "." + attributionTag));
             }
-            scheduleOpNotedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED);
+            scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+                    AppOpsManager.MODE_ALLOWED);
             attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state,
                     flags);
 
@@ -3545,7 +3564,7 @@
             if (ops == null) {
                 if (!dryRun) {
                     scheduleOpStartedIfNeededLocked(code, uid, packageName,
-                            AppOpsManager.MODE_IGNORED);
+                            flags, AppOpsManager.MODE_IGNORED);
                 }
                 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -3555,7 +3574,7 @@
             if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
                 if (!dryRun) {
                     scheduleOpStartedIfNeededLocked(code, uid, packageName,
-                            AppOpsManager.MODE_IGNORED);
+                            flags, AppOpsManager.MODE_IGNORED);
                 }
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -3575,7 +3594,7 @@
                     }
                     if (!dryRun) {
                         attributedOp.rejected(uidState.state, flags);
-                        scheduleOpStartedIfNeededLocked(code, uid, packageName, uidMode);
+                        scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, uidMode);
                     }
                     return uidMode;
                 }
@@ -3590,7 +3609,7 @@
                             + packageName);
                     if (!dryRun) {
                         attributedOp.rejected(uidState.state, flags);
-                        scheduleOpStartedIfNeededLocked(code, uid, packageName, mode);
+                        scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, mode);
                     }
                     return mode;
                 }
@@ -3598,7 +3617,8 @@
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
             if (!dryRun) {
-                scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED);
+                scheduleOpStartedIfNeededLocked(code, uid, packageName, flags,
+                        AppOpsManager.MODE_ALLOWED);
                 try {
                     attributedOp.started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
                             uidState.state, flags);
@@ -3736,7 +3756,8 @@
         }
     }
 
-    private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, int result) {
+    private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName,
+            @OpFlags int flags, @Mode int result) {
         ArraySet<StartedCallback> dispatchedCallbacks = null;
         final int callbackListCount = mStartedWatchers.size();
         for (int i = 0; i < callbackListCount; i++) {
@@ -3761,18 +3782,18 @@
 
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 AppOpsService::notifyOpStarted,
-                this, dispatchedCallbacks, code, uid, pkgName, result));
+                this, dispatchedCallbacks, code, uid, pkgName, flags, result));
     }
 
     private void notifyOpStarted(ArraySet<StartedCallback> callbacks,
-            int code, int uid, String packageName, int result) {
+            int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
             for (int i = 0; i < callbackCount; i++) {
                 final StartedCallback callback = callbacks.valueAt(i);
                 try {
-                    callback.mCallback.opStarted(code, uid, packageName, result);
+                    callback.mCallback.opStarted(code, uid, packageName, flags, result);
                 } catch (RemoteException e) {
                     /* do nothing */
                 }
@@ -3783,7 +3804,7 @@
     }
 
     private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
-            int result) {
+            @OpFlags int flags, @Mode int result) {
         ArraySet<NotedCallback> dispatchedCallbacks = null;
         final int callbackListCount = mNotedWatchers.size();
         for (int i = 0; i < callbackListCount; i++) {
@@ -3804,11 +3825,11 @@
         }
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 AppOpsService::notifyOpChecked,
-                this, dispatchedCallbacks, code, uid, packageName, result));
+                this, dispatchedCallbacks, code, uid, packageName, flags, result));
     }
 
     private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
-            int code, int uid, String packageName, int result) {
+            int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
         // There are features watching for checks in our process. The callbacks in
         // these features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
@@ -3817,7 +3838,7 @@
             for (int i = 0; i < callbackCount; i++) {
                 final NotedCallback callback = callbacks.valueAt(i);
                 try {
-                    callback.mCallback.opNoted(code, uid, packageName, result);
+                    callback.mCallback.opNoted(code, uid, packageName, flags, result);
                 } catch (RemoteException e) {
                     /* do nothing */
                 }
diff --git a/services/core/java/com/android/server/appop/OWNERS b/services/core/java/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/core/java/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/core/java/com/android/server/attention/OWNERS b/services/core/java/com/android/server/attention/OWNERS
new file mode 100644
index 0000000..51fc9bd
--- /dev/null
+++ b/services/core/java/com/android/server/attention/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/attention/OWNERS
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 3b407f1..26f5c4c 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -16,6 +16,7 @@
 package com.android.server.audio;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
@@ -31,14 +32,17 @@
 import android.media.AudioSystem;
 import android.media.IAudioRoutesObserver;
 import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
 import android.media.IStrategyPreferredDevicesDispatcher;
 import android.media.MediaMetrics;
+import android.media.audiopolicy.AudioProductStrategy;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -49,6 +53,7 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -75,7 +80,8 @@
     private final @NonNull Context mContext;
 
     /** Forced device usage for communications sent to AudioSystem */
-    private int mForcedUseForComm;
+    private AudioDeviceAttributes mPreferredDeviceforComm;
+    private int mCommunicationStrategyId = -1;
 
     // Manages all connected devices, only ever accessed on the message loop
     private final AudioDeviceInventory mDeviceInventory;
@@ -131,10 +137,23 @@
         init();
     }
 
+    private void initCommunicationStrategyId() {
+        List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies();
+        for (AudioProductStrategy strategy : strategies) {
+            if (strategy.getAudioAttributesForLegacyStreamType(AudioSystem.STREAM_VOICE_CALL)
+                    != null) {
+                mCommunicationStrategyId = strategy.getId();
+                return;
+            }
+        }
+        mCommunicationStrategyId = -1;
+    }
+
     private void init() {
         setupMessaging(mContext);
 
-        mForcedUseForComm = AudioSystem.FORCE_NONE;
+        mPreferredDeviceforComm = null;
+        initCommunicationStrategyId();
     }
 
     /*package*/ Context getContext() {
@@ -219,8 +238,7 @@
             synchronized (mDeviceStateLock) {
                 AudioDeviceAttributes device = null;
                 if (on) {
-                    device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
-                            AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
+                    device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
                 } else {
                     CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
                     if (client == null || !client.requestsSpeakerphone()) {
@@ -233,6 +251,38 @@
         }
     }
 
+    /**
+     * Select device for use for communication use cases.
+     * @param cb Client binder for death detection
+     * @param pid Client pid
+     * @param device Device selected or null to unselect.
+     * @param eventSource for logging purposes
+     */
+    /*package*/ boolean setDeviceForCommunication(
+            IBinder cb, int pid, AudioDeviceInfo device, String eventSource) {
+
+        if (AudioService.DEBUG_COMM_RTE) {
+            Log.v(TAG, "setDeviceForCommunication, device: " + device + ", pid: " + pid);
+        }
+
+        synchronized (mSetModeLock) {
+            synchronized (mDeviceStateLock) {
+                AudioDeviceAttributes deviceAttr = null;
+                if (device != null) {
+                    deviceAttr = new AudioDeviceAttributes(device);
+                } else {
+                    CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
+                    if (client == null) {
+                        return false;
+                    }
+                }
+                setCommunicationRouteForClient(
+                        cb, pid, deviceAttr, BtHelper.SCO_MODE_UNDEFINED, eventSource);
+            }
+        }
+        return true;
+    }
+
     @GuardedBy("mDeviceStateLock")
     /*package*/ void setCommunicationRouteForClient(
                             IBinder cb, int pid, AudioDeviceAttributes device,
@@ -241,6 +291,10 @@
         if (AudioService.DEBUG_COMM_RTE) {
             Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
         }
+        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                                        "setCommunicationRouteForClient for pid: " + pid
+                                        + " device: " + device
+                                        + " from API: " + eventSource)).printLog(TAG));
 
         final boolean wasBtScoRequested = isBluetoothScoRequested();
         final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
@@ -278,6 +332,7 @@
                 } else {
                     removeCommunicationRouteClient(cb, true);
                 }
+                postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
             }
         } else if (!isBtScoRequested && wasBtScoRequested) {
             mBtHelper.stopBluetoothSco(eventSource);
@@ -325,6 +380,20 @@
     }
 
     /**
+     * Returns the device currently requested for communication use case.
+     * @return AudioDeviceInfo the requested device for communication.
+     */
+    AudioDeviceInfo getDeviceForCommunication() {
+        synchronized (mDeviceStateLock) {
+            AudioDeviceAttributes device = requestedCommunicationDevice();
+            if (device == null) {
+                return null;
+            }
+            return AudioManager.getDeviceInfoFromType(device.getType());
+        }
+    }
+
+    /**
      * Helper method on top of requestedCommunicationDevice() indicating if
      * speakerphone ON is currently requested or not.
      * @return true if speakerphone ON requested, false otherwise.
@@ -344,7 +413,11 @@
      * @return true if speakerphone is active, false otherwise.
      */
     /*package*/ boolean isSpeakerphoneOn() {
-        return getForcedUseForComm() == AudioSystem.FORCE_SPEAKER;
+        AudioDeviceAttributes device = getPreferredDeviceForComm();
+        if (device == null) {
+            return false;
+        }
+        return device.getInternalType() == AudioSystem.DEVICE_OUT_SPEAKER;
     }
 
     /**
@@ -511,7 +584,11 @@
      * @return true if Bluetooth SCO is active , false otherwise.
      */
     /*package*/ boolean isBluetoothScoOn() {
-        return getForcedUseForComm() == AudioSystem.FORCE_BT_SCO;
+        AudioDeviceAttributes device = getPreferredDeviceForComm();
+        if (device == null) {
+            return false;
+        }
+        return AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType());
     }
 
     /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
@@ -563,14 +640,9 @@
 
         synchronized (mSetModeLock) {
             synchronized (mDeviceStateLock) {
-                AudioDeviceAttributes device = new AudioDeviceAttributes(
-                        AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "");
+                AudioDeviceAttributes device =
+                        new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
                 setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
-                if (!isBluetoothScoRequested()) {
-                    Log.w(TAG, "startBluetoothScoForClient_Sync: rejected for pid: "
-                            + pid + " mode owner pid: " + mModeOwnerPid);
-                    postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
-                }
             }
         }
     }
@@ -599,10 +671,19 @@
         return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
     }
 
+    /*package*/ void postSetPreferredDevicesForStrategy(int strategy,
+            @NonNull List<AudioDeviceAttributes> devices) {
+        sendILMsgNoDelay(MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy, devices);
+    }
+
     /*package*/ int removePreferredDevicesForStrategySync(int strategy) {
         return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
     }
 
+    /*package*/ void postRemovePreferredDevicesForStrategy(int strategy) {
+        sendIMsgNoDelay(MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy);
+    }
+
     /*package*/ void registerStrategyPreferredDevicesDispatcher(
             @NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
         mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
@@ -632,6 +713,45 @@
         mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
     }
 
+    /*package*/ void registerCommunicationDeviceDispatcher(
+            @NonNull ICommunicationDeviceDispatcher dispatcher) {
+        mCommDevDispatchers.register(dispatcher);
+    }
+
+    /*package*/ void unregisterCommunicationDeviceDispatcher(
+            @NonNull ICommunicationDeviceDispatcher dispatcher) {
+        mCommDevDispatchers.unregister(dispatcher);
+    }
+
+    // Monitoring of communication device
+    final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers =
+            new RemoteCallbackList<ICommunicationDeviceDispatcher>();
+
+    // portId of the device currently selected for communication: avoids broadcasting changes
+    // when same communication route is applied
+    @GuardedBy("mDeviceStateLock")
+    int mCurCommunicationPortId = -1;
+
+    @GuardedBy("mDeviceStateLock")
+    private void dispatchCommunicationDevice() {
+        AudioDeviceInfo device = getDeviceForCommunication();
+        int portId = (getDeviceForCommunication() == null) ? 0 : device.getId();
+        if (portId == mCurCommunicationPortId) {
+            return;
+        }
+        mCurCommunicationPortId = portId;
+
+        final int nbDispatchers = mCommDevDispatchers.beginBroadcast();
+        for (int i = 0; i < nbDispatchers; i++) {
+            try {
+                mCommDevDispatchers.getBroadcastItem(i)
+                        .dispatchCommunicationDeviceChanged(portId);
+            } catch (RemoteException e) {
+            }
+        }
+        mCommDevDispatchers.finishBroadcast();
+    }
+
     //---------------------------------------------------------------------
     // Communication with (to) AudioService
     //TODO check whether the AudioService methods are candidates to move here
@@ -888,9 +1008,12 @@
             pw.println("  " + prefix + "pid: " + cl.getPid() + " device: "
                         + cl.getDevice() + " cb: " + cl.getBinder()); });
 
-        pw.println("\n" + prefix + "mForcedUseForComm: "
-                +  AudioSystem.forceUseConfigToString(mForcedUseForComm));
-        pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
+        pw.println("\n" + prefix + "mPreferredDeviceforComm: "
+                +  mPreferredDeviceforComm);
+        pw.println(prefix + "mCommunicationStrategyId: "
+                +  mCommunicationStrategyId);
+
+        pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid);
 
         mBtHelper.dump(pw, prefix);
     }
@@ -985,6 +1108,7 @@
                 case MSG_RESTORE_DEVICES:
                     synchronized (mSetModeLock) {
                         synchronized (mDeviceStateLock) {
+                            initCommunicationStrategyId();
                             mDeviceInventory.onRestoreDevices();
                             mBtHelper.onAudioServerDiedRestoreA2dp();
                             onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
@@ -1194,6 +1318,17 @@
                     final int strategy = msg.arg1;
                     mDeviceInventory.onSaveRemovePreferredDevices(strategy);
                 } break;
+                case MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY: {
+                    final int strategy = msg.arg1;
+                    final List<AudioDeviceAttributes> devices =
+                            (List<AudioDeviceAttributes>) msg.obj;
+                    setPreferredDevicesForStrategySync(strategy, devices);
+
+                } break;
+                case MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
+                    final int strategy = msg.arg1;
+                    removePreferredDevicesForStrategySync(strategy);
+                } break;
                 case MSG_CHECK_MUTE_MUSIC:
                     checkMessagesMuteMusic(0);
                     break;
@@ -1286,7 +1421,8 @@
     private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
 
     private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39;
-
+    private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
+    private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
@@ -1526,16 +1662,25 @@
      * @return selected forced usage for communication.
      */
     @GuardedBy("mDeviceStateLock")
-    private int getForcedUseForComm() {
+    @Nullable private AudioDeviceAttributes getPreferredDeviceForComm() {
         boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
-
         if (btSCoOn) {
-            return AudioSystem.FORCE_BT_SCO;
+            // Use the SCO device known to BtHelper so that it matches exactly
+            // what has been communicated to audio policy manager. The device
+            // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy
+            // APIs are used to start SCO audio.
+            AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice();
+            if (device != null) {
+                return device;
+            }
         }
-        if (isSpeakerphoneRequested()) {
-            return AudioSystem.FORCE_SPEAKER;
+        AudioDeviceAttributes device = requestedCommunicationDevice();
+        if (device == null
+                || AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType())) {
+            // Do not indicate BT SCO selection if SCO is requested but SCO is not ON
+            return null;
         }
-        return AudioSystem.FORCE_NONE;
+        return device;
     }
 
     /**
@@ -1545,32 +1690,27 @@
     // @GuardedBy("mSetModeLock")
     @GuardedBy("mDeviceStateLock")
     private void onUpdateCommunicationRoute(String eventSource) {
-        mForcedUseForComm = getForcedUseForComm();
-
+        mPreferredDeviceforComm = getPreferredDeviceForComm();
         if (AudioService.DEBUG_COMM_RTE) {
-            Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm
-                    + " eventSource: " + eventSource);
+            Log.v(TAG, "onUpdateCommunicationRoute, mPreferredDeviceforComm: "
+                    + mPreferredDeviceforComm + " eventSource: " + eventSource);
         }
 
-        if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
-            AudioSystem.setParameters("BT_SCO=on");
-            setForceUse_Async(
-                    AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource);
-            setForceUse_Async(
-                    AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
-        } else {
+        if (mPreferredDeviceforComm == null
+                || !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(
+                        mPreferredDeviceforComm.getInternalType())) {
             AudioSystem.setParameters("BT_SCO=off");
-            setForceUse_Async(
-                    AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
-            if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
-                setForceUse_Async(
-                        AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER, eventSource);
-            } else {
-                setForceUse_Async(
-                        AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource);
-            }
+        } else {
+            AudioSystem.setParameters("BT_SCO=on");
+        }
+        if (mPreferredDeviceforComm == null) {
+            postRemovePreferredDevicesForStrategy(mCommunicationStrategyId);
+        } else {
+            postSetPreferredDevicesForStrategy(
+                    mCommunicationStrategyId, Arrays.asList(mPreferredDeviceforComm));
         }
         mAudioService.postUpdateRingerModeServiceInt();
+        dispatchCommunicationDevice();
     }
 
     private CommunicationRouteClient removeCommunicationRouteClient(
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 33a8a30..82586b8 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -648,6 +648,10 @@
     /*package*/ int setPreferredDevicesForStrategySync(int strategy,
             @NonNull List<AudioDeviceAttributes> devices) {
         final long identity = Binder.clearCallingIdentity();
+
+        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                                "setPreferredDevicesForStrategySync, strategy: " + strategy
+                                + " devices: " + devices)).printLog(TAG));
         final int status = mAudioSystem.setDevicesRoleForStrategy(
                 strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
         Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4d971a5..4444de0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -85,6 +85,7 @@
 import android.media.IAudioServerStateDispatcher;
 import android.media.IAudioService;
 import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
 import android.media.IPlaybackConfigDispatcher;
 import android.media.IRecordingConfigDispatcher;
 import android.media.IRingtonePlayer;
@@ -2108,6 +2109,24 @@
         return getDevicesForAttributesInt(attributes);
     }
 
+    /**
+     * @see AudioManager#isMusicActive()
+     * @param remotely true if query is for remote playback (cast), false for local playback.
+     */
+    public boolean isMusicActive(boolean remotely) {
+        // no permission required
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (remotely) {
+                return AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0);
+            } else {
+                return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
@@ -4399,6 +4418,115 @@
         restoreDeviceVolumeBehavior();
     }
 
+    private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
+        AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+        AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
+        AudioDeviceInfo.TYPE_WIRED_HEADSET,
+        AudioDeviceInfo.TYPE_USB_HEADSET,
+        AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
+        AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
+        AudioDeviceInfo.TYPE_HEARING_AID,
+        AudioDeviceInfo.TYPE_BLE_HEADSET,
+        AudioDeviceInfo.TYPE_USB_DEVICE,
+        AudioDeviceInfo.TYPE_BLE_SPEAKER,
+        AudioDeviceInfo.TYPE_LINE_ANALOG,
+        AudioDeviceInfo.TYPE_HDMI,
+        AudioDeviceInfo.TYPE_AUX_LINE
+    };
+
+    private boolean isValidCommunicationDevice(AudioDeviceInfo device) {
+        for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
+            if (device.getType() == type) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** @see AudioManager#setDeviceForCommunication(int) */
+    public boolean setDeviceForCommunication(IBinder cb, int portId) {
+        final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
+
+        AudioDeviceInfo device = null;
+        if (portId != 0) {
+            device = AudioManager.getDeviceForPortId(portId, AudioManager.GET_DEVICES_OUTPUTS);
+            if (device == null) {
+                throw new IllegalArgumentException("invalid portID " + portId);
+            }
+            if (!isValidCommunicationDevice(device)) {
+                throw new IllegalArgumentException("invalid device type " + device.getType());
+            }
+        }
+        final String eventSource = new StringBuilder("setDeviceForCommunication(")
+                .append(") from u/pid:").append(uid).append("/")
+                .append(pid).toString();
+
+        int deviceType = AudioSystem.DEVICE_OUT_DEFAULT;
+        String deviceAddress = null;
+        if (device != null) {
+            deviceType = device.getPort().type();
+            deviceAddress = device.getAddress();
+        } else {
+            AudioDeviceInfo curDevice = mDeviceBroker.getDeviceForCommunication();
+            if (curDevice != null) {
+                deviceType = curDevice.getPort().type();
+                deviceAddress = curDevice.getAddress();
+            }
+        }
+        // do not log metrics if clearing communication device while no communication device
+        // was selected
+        if (deviceType != AudioSystem.DEVICE_OUT_DEFAULT) {
+            new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
+                    + MediaMetrics.SEPARATOR + "setDeviceForCommunication")
+                    .set(MediaMetrics.Property.DEVICE,
+                            AudioSystem.getDeviceName(deviceType))
+                    .set(MediaMetrics.Property.ADDRESS, deviceAddress)
+                    .set(MediaMetrics.Property.STATE, device != null
+                            ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
+                    .record();
+        }
+
+        final long ident = Binder.clearCallingIdentity();
+        boolean status =
+                mDeviceBroker.setDeviceForCommunication(cb, pid, device, eventSource);
+        Binder.restoreCallingIdentity(ident);
+        return status;
+    }
+
+    /** @see AudioManager#getDeviceForCommunication() */
+    public int getDeviceForCommunication() {
+        final long ident = Binder.clearCallingIdentity();
+        AudioDeviceInfo device = mDeviceBroker.getDeviceForCommunication();
+        Binder.restoreCallingIdentity(ident);
+        if (device == null) {
+            return 0;
+        }
+        return device.getId();
+    }
+
+    /** @see AudioManager#addOnCommunicationDeviceChangedListener(
+     *               Executor, AudioManager.OnCommunicationDeviceChangedListener)
+     */
+    public void registerCommunicationDeviceDispatcher(
+            @Nullable ICommunicationDeviceDispatcher dispatcher) {
+        if (dispatcher == null) {
+            return;
+        }
+        mDeviceBroker.registerCommunicationDeviceDispatcher(dispatcher);
+    }
+
+    /** @see AudioManager#removeOnCommunicationDeviceChangedListener(
+     *               AudioManager.OnCommunicationDeviceChangedListener)
+     */
+    public void unregisterCommunicationDeviceDispatcher(
+            @Nullable ICommunicationDeviceDispatcher dispatcher) {
+        if (dispatcher == null) {
+            return;
+        }
+        mDeviceBroker.unregisterCommunicationDeviceDispatcher(dispatcher);
+    }
+
     /** @see AudioManager#setSpeakerphoneOn(boolean) */
     public void setSpeakerphoneOn(IBinder cb, boolean on) {
         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
@@ -4993,8 +5121,7 @@
         switch (mPlatformType) {
         case AudioSystem.PLATFORM_VOICE:
             if (isInCommunication()) {
-                if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
-                        == AudioSystem.FORCE_BT_SCO) {
+                if (mDeviceBroker.isBluetoothScoOn()) {
                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
                     return AudioSystem.STREAM_BLUETOOTH_SCO;
                 } else {
@@ -5030,8 +5157,7 @@
             }
         default:
             if (isInCommunication()) {
-                if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
-                        == AudioSystem.FORCE_BT_SCO) {
+                if (mDeviceBroker.isBluetoothScoOn()) {
                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
                     return AudioSystem.STREAM_BLUETOOTH_SCO;
                 } else {
@@ -5175,7 +5301,7 @@
     /** only public for mocking/spying, do not call outside of AudioService */
     @VisibleForTesting
     public int getDeviceForStream(int stream) {
-        int device = getDevicesForStream(stream);
+        int device = getDevicesForStreamInt(stream);
         if ((device & (device - 1)) != 0) {
             // Multiple device selection is either:
             //  - speaker + one other device: give priority to speaker in this case.
@@ -5204,14 +5330,23 @@
         return device;
     }
 
-    private int getDevicesForStream(int stream) {
-        return getDevicesForStream(stream, true /*checkOthers*/);
+    /**
+     * @see AudioManager#getDevicesForStream(int)
+     */
+    public int getDevicesForStream(int streamType) {
+        ensureValidStreamType(streamType);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return mAudioSystem.getDevicesForStream(streamType);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
-    private int getDevicesForStream(int stream, boolean checkOthers) {
+    private int getDevicesForStreamInt(int stream) {
         ensureValidStreamType(stream);
         synchronized (VolumeStreamState.class) {
-            return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
+            return mStreamStates[stream].observeDevicesForStream_syncVSS(true);
         }
     }
 
@@ -6396,10 +6531,10 @@
             }
             pw.println();
             pw.print("   Devices: ");
-            final int devices = getDevicesForStream(mStreamType);
+            final int devices = getDevicesForStreamInt(mStreamType);
             int device, i = 0, n = 0;
             // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
-            // (the default device is not returned by getDevicesForStream)
+            // (the default device is not returned by getDevicesForStreamInt)
             while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
                 if ((devices & device) != 0) {
                     if (n++ > 0) {
@@ -7444,8 +7579,8 @@
     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
     private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
-    // check playback or record activity every 3 seconds for UIDs owning mode IN_COMMUNICATION
-    private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 3000;
+    // check playback or record activity every 6 seconds for UIDs owning mode IN_COMMUNICATION
+    private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 6000;
 
     private int safeMediaVolumeIndex(int device) {
         if (!mSafeMediaVolumeDevices.contains(device)) {
@@ -7631,7 +7766,7 @@
                     mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
                             "setHdmiSystemAudioSupported");
                 }
-                device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
+                device = getDevicesForStreamInt(AudioSystem.STREAM_MUSIC);
             }
         }
         return device;
@@ -8771,8 +8906,14 @@
         mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
     }
 
-    public void playerEvent(int piid, int event) {
-        mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
+    /**
+     * Update player event
+     * @param piid Player id to update
+     * @param event The new player event
+     * @param deviceId The new player device id
+     */
+    public void playerEvent(int piid, int event, int deviceId) {
+        mPlaybackMonitor.playerEvent(piid, event, deviceId, Binder.getCallingUid());
     }
 
     public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index ae0e805..c57d5af 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -27,6 +27,7 @@
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.os.Binder;
@@ -530,46 +531,64 @@
         mDeviceBroker.postBroadcastScoConnectionState(state);
     }
 
-    private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
-        if (btDevice == null) {
-            return true;
+    @Nullable AudioDeviceAttributes getHeadsetAudioDevice() {
+        if (mBluetoothHeadsetDevice == null) {
+            return null;
         }
+        return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice);
+    }
+
+    private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
         String address = btDevice.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
         BluetoothClass btClass = btDevice.getBluetoothClass();
-        int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-        int[] outDeviceTypes = {
-                AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
-                AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
-                AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
-        };
+        int nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
         if (btClass != null) {
             switch (btClass.getDeviceClass()) {
                 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
                 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
-                    outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET };
+                    nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
                     break;
                 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
-                    outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT };
+                    nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                     break;
             }
         }
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            address = "";
+        if (AudioService.DEBUG_DEVICES) {
+            Log.i(TAG, "btHeadsetDeviceToAudioDevice btDevice: " + btDevice
+                    + " btClass: " + (btClass == null ? "Unknown" : btClass)
+                    + " nativeType: " + nativeType + " address: " + address);
         }
+        return new AudioDeviceAttributes(nativeType, address);
+    }
+
+    private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
+        if (btDevice == null) {
+            return true;
+        }
+        int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        AudioDeviceAttributes audioDevice =  btHeadsetDeviceToAudioDevice(btDevice);
         String btDeviceName =  getName(btDevice);
         boolean result = false;
         if (isActive) {
-            result |= mDeviceBroker.handleDeviceConnection(
-                    isActive, outDeviceTypes[0], address, btDeviceName);
+            result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(),
+                    audioDevice.getAddress(), btDeviceName);
         } else {
+            int[] outDeviceTypes = {
+                    AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
+                    AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                    AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
+            };
             for (int outDeviceType : outDeviceTypes) {
                 result |= mDeviceBroker.handleDeviceConnection(
-                        isActive, outDeviceType, address, btDeviceName);
+                        isActive, outDeviceType, audioDevice.getAddress(), btDeviceName);
             }
         }
         // handleDeviceConnection() && result to make sure the method get executed
         result = mDeviceBroker.handleDeviceConnection(
-                isActive, inDevice, address, btDeviceName) && result;
+                isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result;
         return result;
     }
 
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index a577883..36c67cd 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -233,15 +233,25 @@
         }
     }
 
-    public void playerEvent(int piid, int event, int binderUid) {
-        if (DEBUG) { Log.v(TAG, String.format("playerEvent(piid=%d, event=%d)", piid, event)); }
+    /**
+     * Update player event
+     * @param piid Player id to update
+     * @param event The new player event
+     * @param deviceId The new player device id
+     * @param binderUid Calling binder uid
+     */
+    public void playerEvent(int piid, int event, int deviceId, int binderUid) {
+        if (DEBUG) {
+            Log.v(TAG, String.format("playerEvent(piid=%d, deviceId=%d, event=%d)",
+                    piid, deviceId, event));
+        }
         final boolean change;
         synchronized(mPlayerLock) {
             final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
             if (apc == null) {
                 return;
             }
-            sEventLogger.log(new PlayerEvent(piid, event));
+            sEventLogger.log(new PlayerEvent(piid, event, deviceId));
             if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                 for (Integer uidInteger: mBannedUids) {
                     if (checkBanPlayer(apc, uidInteger.intValue())) {
@@ -259,7 +269,7 @@
             if (checkConfigurationCaller(piid, apc, binderUid)) {
                 //TODO add generation counter to only update to the latest state
                 checkVolumeForPrivilegedAlarm(apc, event);
-                change = apc.handleStateEvent(event);
+                change = apc.handleStateEvent(event, deviceId);
             } else {
                 Log.e(TAG, "Error handling event " + event);
                 change = false;
@@ -289,7 +299,8 @@
                 mPlayers.remove(new Integer(piid));
                 mDuckingManager.removeReleased(apc);
                 checkVolumeForPrivilegedAlarm(apc, AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
-                change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
+                change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED,
+                        AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID);
             }
         }
         if (change) {
@@ -868,16 +879,19 @@
         // only keeping the player interface ID as it uniquely identifies the player in the event
         final int mPlayerIId;
         final int mState;
+        final int mDeviceId;
 
-        PlayerEvent(int piid, int state) {
+        PlayerEvent(int piid, int state, int deviceId) {
             mPlayerIId = piid;
             mState = state;
+            mDeviceId = deviceId;
         }
 
         @Override
         public String eventToString() {
             return new StringBuilder("player piid:").append(mPlayerIId).append(" state:")
-                    .append(AudioPlaybackConfiguration.toLogFriendlyPlayerState(mState)).toString();
+                    .append(AudioPlaybackConfiguration.toLogFriendlyPlayerState(mState))
+                    .append(" DeviceId:").append(mDeviceId).toString();
         }
     }
 
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 0d34c53..90246f8 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-    "presubmit": [
+    "presubmit-large": [
         {
             "name": "CtsMediaTestCases",
             "options": [
diff --git a/services/core/java/com/android/server/backup/OWNERS b/services/core/java/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/core/java/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/core/java/com/android/server/camera/OWNERS b/services/core/java/com/android/server/camera/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/services/core/java/com/android/server/camera/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index ff31931..a8aa9aa 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -143,6 +143,9 @@
      * @return {@code true} if the change should be enabled for the package.
      */
     boolean isEnabled(ApplicationInfo app) {
+        if (app == null) {
+            return defaultValue();
+        }
         if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) {
             return mPackageOverrides.get(app.packageName);
         }
@@ -156,6 +159,15 @@
     }
 
     /**
+     * Returns the default value for the change id, assuming there are no overrides.
+     *
+     * @return {@code false} if it's a default disabled change, {@code true} otherwise.
+     */
+    boolean defaultValue() {
+        return !getDisabled();
+    }
+
+    /**
      * Checks whether a change has an override for a package.
      * @param packageName name of the package
      * @return true if there is such override
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index d80c58b..8511118 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -392,6 +392,14 @@
         return alreadyKnown;
     }
 
+    boolean defaultChangeIdValue(long changeId) {
+        CompatChange c = mChanges.get(changeId);
+        if (c == null) {
+            return true;
+        }
+        return c.defaultValue();
+    }
+
     @VisibleForTesting
     void clearChanges() {
         synchronized (mChanges) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 77d5411..4bd01d4 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -120,10 +120,12 @@
      * permission check.
      */
     public boolean isChangeEnabledInternal(long changeId, ApplicationInfo appInfo) {
-        boolean value = isChangeEnabledInternalNoLogging(changeId, appInfo);
-        reportChange(changeId, appInfo.uid,
-                value ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
-        return value;
+        boolean enabled = isChangeEnabledInternalNoLogging(changeId, appInfo);
+        if (appInfo != null) {
+            reportChange(changeId, appInfo.uid,
+                    enabled ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
+        }
+        return enabled;
     }
 
     @Override
@@ -131,9 +133,6 @@
             @UserIdInt int userId) {
         checkCompatChangeReadAndLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
-        if (appInfo == null) {
-            return true;
-        }
         return isChangeEnabled(changeId, appInfo);
     }
 
@@ -142,7 +141,7 @@
         checkCompatChangeReadAndLogPermission();
         String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
         if (packages == null || packages.length == 0) {
-            return true;
+            return mCompatConfig.defaultChangeIdValue(changeId);
         }
         boolean enabled = true;
         for (String packageName : packages) {
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index 4fb6607..995bb24 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -166,7 +166,7 @@
 
     private static void fillLinkInfo(DefaultNetworkEvent ev, NetworkAgentInfo nai) {
         LinkProperties lp = nai.linkProperties;
-        ev.netId = nai.network().netId;
+        ev.netId = nai.network().getNetId();
         ev.transports |= BitUtils.packBits(nai.networkCapabilities.getTransportTypes());
         ev.ipv4 |= lp.hasIpv4Address() && lp.hasIpv4DefaultRoute();
         ev.ipv6 |= lp.hasGlobalIpv6Address() && lp.hasIpv6DefaultRoute();
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 1f0fb5e..c70bb08 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -34,7 +34,6 @@
 import android.net.IDnsResolver;
 import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.ResolverOptionsParcel;
 import android.net.ResolverParamsParcel;
 import android.net.Uri;
@@ -50,6 +49,7 @@
 
 import java.net.InetAddress;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -59,7 +59,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
-
 /**
  * Encapsulate the management of DNS settings for networks.
  *
@@ -266,23 +265,23 @@
     }
 
     public void removeNetwork(Network network) {
-        mPrivateDnsMap.remove(network.netId);
-        mPrivateDnsValidationMap.remove(network.netId);
-        mTransportsMap.remove(network.netId);
-        mLinkPropertiesMap.remove(network.netId);
+        mPrivateDnsMap.remove(network.getNetId());
+        mPrivateDnsValidationMap.remove(network.getNetId());
+        mTransportsMap.remove(network.getNetId());
+        mLinkPropertiesMap.remove(network.getNetId());
     }
 
     // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which
     // is not on the ConnectivityService handler thread.
     public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) {
-        return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF);
+        return mPrivateDnsMap.getOrDefault(network.getNetId(), PRIVATE_DNS_OFF);
     }
 
     public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
         Log.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
         return (cfg != null)
-                ? mPrivateDnsMap.put(network.netId, cfg)
-                : mPrivateDnsMap.remove(network.netId);
+                ? mPrivateDnsMap.put(network.getNetId(), cfg)
+                : mPrivateDnsMap.remove(network.getNetId());
     }
 
     public void updatePrivateDnsStatus(int netId, LinkProperties lp) {
@@ -309,8 +308,7 @@
     }
 
     public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) {
-        final PrivateDnsValidationStatuses statuses =
-                mPrivateDnsValidationMap.get(update.netId);
+        final PrivateDnsValidationStatuses statuses = mPrivateDnsValidationMap.get(update.netId);
         if (statuses == null) return;
         statuses.updateStatus(update);
     }
@@ -364,12 +362,11 @@
         paramsParcel.successThreshold = mSuccessThreshold;
         paramsParcel.minSamples = mMinSamples;
         paramsParcel.maxSamples = mMaxSamples;
-        paramsParcel.servers =
-                NetworkUtils.makeStrings(lp.getDnsServers());
+        paramsParcel.servers = makeStrings(lp.getDnsServers());
         paramsParcel.domains = getDomainStrings(lp.getDomains());
         paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
         paramsParcel.tlsServers =
-                strictMode ? NetworkUtils.makeStrings(
+                strictMode ? makeStrings(
                         Arrays.stream(privateDnsCfg.ips)
                               .filter((ip) -> lp.isReachable(ip))
                               .collect(Collectors.toList()))
@@ -460,6 +457,21 @@
         return Settings.Global.getInt(mContentResolver, which, dflt);
     }
 
+    /**
+     * Create a string array of host addresses from a collection of InetAddresses
+     *
+     * @param addrs a Collection of InetAddresses
+     * @return an array of Strings containing their host addresses
+     */
+    private String[] makeStrings(Collection<InetAddress> addrs) {
+        String[] result = new String[addrs.size()];
+        int i = 0;
+        for (InetAddress addr : addrs) {
+            result[i++] = addr.getHostAddress();
+        }
+        return result;
+    }
+
     private static String getPrivateDnsMode(ContentResolver cr) {
         String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
         if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE);
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 8625a6f..96cbfde 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -40,11 +40,11 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.net.ISocketKeepaliveCallback;
+import android.net.InetAddresses;
 import android.net.InvalidPacketException;
 import android.net.KeepalivePacketData;
 import android.net.NattKeepalivePacketData;
 import android.net.NetworkAgent;
-import android.net.NetworkUtils;
 import android.net.SocketKeepalive.InvalidSocketException;
 import android.net.TcpKeepalivePacketData;
 import android.net.util.KeepaliveUtils;
@@ -625,8 +625,8 @@
 
         InetAddress srcAddress, dstAddress;
         try {
-            srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
-            dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
+            srcAddress = InetAddresses.parseNumericAddress(srcAddrString);
+            dstAddress = InetAddresses.parseNumericAddress(dstAddrString);
         } catch (IllegalArgumentException e) {
             notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
             return;
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index f99f4c6..adec7ad 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -114,7 +114,7 @@
 
     private int getNotificationSource(NetworkAgentInfo toNai) {
         for (int i = 0; i < mNotifications.size(); i++) {
-            if (mNotifications.valueAt(i) == toNai.network.netId) {
+            if (mNotifications.valueAt(i) == toNai.network.getNetId()) {
                 return mNotifications.keyAt(i);
             }
         }
@@ -122,7 +122,7 @@
     }
 
     private boolean everNotified(NetworkAgentInfo nai) {
-        return mEverNotified.get(nai.network.netId, false);
+        return mEverNotified.get(nai.network.getNetId(), false);
     }
 
     @VisibleForTesting
@@ -153,7 +153,7 @@
     }
 
     private void showNotification(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
-        mNotifier.showNotification(fromNai.network.netId, NotificationType.NETWORK_SWITCH,
+        mNotifier.showNotification(fromNai.network.getNetId(), NotificationType.NETWORK_SWITCH,
                 fromNai, toNai, createNotificationIntent(), true);
     }
 
@@ -208,8 +208,8 @@
                     + " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")"));
         }
 
-        mNotifications.put(fromNai.network.netId, toNai.network.netId);
-        mEverNotified.put(fromNai.network.netId, true);
+        mNotifications.put(fromNai.network.getNetId(), toNai.network.getNetId());
+        mEverNotified.put(fromNai.network.getNetId(), true);
     }
 
     /**
@@ -295,8 +295,8 @@
     }
 
     public void noteDisconnect(NetworkAgentInfo nai) {
-        mNotifications.delete(nai.network.netId);
-        mEverNotified.delete(nai.network.netId);
+        mNotifications.delete(nai.network.getNetId());
+        mEverNotified.delete(nai.network.getNetId());
         maybeStopNotifying(nai);
         // No need to cancel notifications on nai: NetworkMonitor does that on disconnect.
     }
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index d9c2e80..c1b1b6a 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -528,6 +528,6 @@
 
     @VisibleForTesting
     protected int getNetId() {
-        return mNetwork.network.netId;
+        return mNetwork.network.getNetId();
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 3270dd5..52b9f5c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -138,9 +138,10 @@
     // not guaranteed to be current or correct, or even to exist.
     public @Nullable Network[] declaredUnderlyingNetworks;
 
-    // Whether this network is always metered even if its underlying networks are unmetered.
-    // Only relevant if #supportsUnderlyingNetworks is true.
-    public boolean declaredMetered;
+    // The capabilities originally announced by the NetworkAgent, regardless of any capabilities
+    // that were added or removed due to this network's underlying networks.
+    // Only set if #supportsUnderlyingNetworks is true.
+    public @Nullable NetworkCapabilities declaredCapabilities;
 
     // Indicates if netd has been told to create this Network. From this point on the appropriate
     // routing rules are setup and routes are added so packets can begin flowing over the Network.
@@ -610,7 +611,7 @@
         if (newExpiry > 0) {
             mLingerMessage = new WakeupMessage(
                     mContext, mHandler,
-                    "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */,
+                    "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
                     EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
                     0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
                     this /* obj (NetworkAgentInfo) */);
@@ -701,7 +702,7 @@
      * This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]".
      */
     public String toShortString() {
-        return "[" + network.netId + " "
+        return "[" + network.getNetId() + " "
                 + transportNamesOf(networkCapabilities.getTransportTypes()) + "]";
     }
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 49c16ad..a7be657 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -20,10 +20,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.InetAddresses;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.TrafficStats;
 import android.net.shared.PrivateDnsConfig;
@@ -97,8 +97,8 @@
 public class NetworkDiagnostics {
     private static final String TAG = "NetworkDiagnostics";
 
-    private static final InetAddress TEST_DNS4 = NetworkUtils.numericToInetAddress("8.8.8.8");
-    private static final InetAddress TEST_DNS6 = NetworkUtils.numericToInetAddress(
+    private static final InetAddress TEST_DNS4 = InetAddresses.parseNumericAddress("8.8.8.8");
+    private static final InetAddress TEST_DNS6 = InetAddresses.parseNumericAddress(
             "2001:4860:4860::8888");
 
     // For brevity elsewhere.
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/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 4c63eb4..d507b5f 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -35,7 +35,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
 import android.net.INetd;
 import android.net.UidRange;
 import android.os.Build;
@@ -174,11 +173,9 @@
             netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
         }
 
-        List<UserInfo> users = mUserManager.getAliveUsers();
-        if (users != null) {
-            for (UserInfo user : users) {
-                mUsers.add(user.id);
-            }
+        final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */);
+        for (UserHandle user : users) {
+            mUsers.add(user.getIdentifier());
         }
 
         final SparseArray<ArraySet<String>> systemPermission =
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/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3445275..228ad588 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -48,6 +48,7 @@
 import android.content.pm.UserInfo;
 import android.net.ConnectivityManager;
 import android.net.DnsResolver;
+import android.net.INetd;
 import android.net.INetworkManagementEventObserver;
 import android.net.Ikev2VpnProfile;
 import android.net.IpPrefix;
@@ -68,6 +69,7 @@
 import android.net.NetworkRequest;
 import android.net.RouteInfo;
 import android.net.UidRange;
+import android.net.UidRangeParcel;
 import android.net.VpnManager;
 import android.net.VpnService;
 import android.net.ipsec.ike.ChildSessionCallback;
@@ -188,7 +190,8 @@
 
     private PendingIntent mStatusIntent;
     private volatile boolean mEnableTeardown = true;
-    private final INetworkManagementService mNetd;
+    private final INetworkManagementService mNms;
+    private final INetd mNetd;
     @VisibleForTesting
     protected VpnConfig mConfig;
     private final NetworkProvider mNetworkProvider;
@@ -234,7 +237,7 @@
      * @see mLockdown
      */
     @GuardedBy("this")
-    private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>();
+    private final Set<UidRangeParcel> mBlockedUidsAsToldToNetd = new ArraySet<>();
 
     // The user id of initiating VPN.
     private final int mUserId;
@@ -243,7 +246,12 @@
         void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException;
     }
 
-    static class Dependencies {
+    @VisibleForTesting
+    public static class Dependencies {
+        public boolean isCallerSystem() {
+            return Binder.getCallingUid() == Process.SYSTEM_UID;
+        }
+
         public void startService(final String serviceName) {
             SystemService.start(serviceName);
         }
@@ -264,6 +272,10 @@
             return new File("/data/misc/vpn/state");
         }
 
+        public DeviceIdleInternal getDeviceIdleInternal() {
+            return LocalServices.getService(DeviceIdleInternal.class);
+        }
+
         public void sendArgumentsToDaemon(
                 final String daemon, final LocalSocket socket, final String[] arguments,
                 final RetryScheduler retryScheduler) throws IOException, InterruptedException {
@@ -363,22 +375,31 @@
         }
     }
 
-    public Vpn(Looper looper, Context context, INetworkManagementService netService,
+    public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
             @UserIdInt int userId, @NonNull KeyStore keyStore) {
-        this(looper, context, new Dependencies(), netService, userId, keyStore,
+        this(looper, context, new Dependencies(), netService, netd, userId, keyStore,
+                new SystemServices(context), new Ikev2SessionCreator());
+    }
+
+    @VisibleForTesting
+    public Vpn(Looper looper, Context context, Dependencies deps,
+            INetworkManagementService netService, INetd netd, @UserIdInt int userId,
+            @NonNull KeyStore keyStore) {
+        this(looper, context, deps, netService, netd, userId, keyStore,
                 new SystemServices(context), new Ikev2SessionCreator());
     }
 
     @VisibleForTesting
     protected Vpn(Looper looper, Context context, Dependencies deps,
-            INetworkManagementService netService,
+            INetworkManagementService netService, INetd netd,
             int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
             Ikev2SessionCreator ikev2SessionCreator) {
         mContext = context;
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
         mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
         mDeps = deps;
-        mNetd = netService;
+        mNms = netService;
+        mNetd = netd;
         mUserId = userId;
         mLooper = looper;
         mSystemServices = systemServices;
@@ -768,8 +789,7 @@
 
             // Tell the OS that background services in this app need to be allowed for
             // a short time, so we can bootstrap the VPN service.
-            DeviceIdleInternal idleController =
-                    LocalServices.getService(DeviceIdleInternal.class);
+            DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
             idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
                     VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, "vpn");
 
@@ -912,7 +932,7 @@
             }
 
             try {
-                mNetd.denyProtect(mOwnerUID);
+                mNms.denyProtect(mOwnerUID);
             } catch (Exception e) {
                 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
             }
@@ -922,7 +942,7 @@
             mOwnerUID = getAppUid(newPackage, mUserId);
             mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
             try {
-                mNetd.allowProtect(mOwnerUID);
+                mNms.allowProtect(mOwnerUID);
             } catch (Exception e) {
                 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
             }
@@ -1062,7 +1082,7 @@
         if (null == agent) return NETID_UNSET;
         final Network network = agent.getNetwork();
         if (null == network) return NETID_UNSET;
-        return network.netId;
+        return network.getNetId();
     }
 
     private LinkProperties makeLinkProperties() {
@@ -1253,7 +1273,7 @@
 
             final PackageManager packageManager = mUserIdContext.getPackageManager();
             if (packageManager == null) {
-                throw new UnsupportedOperationException("Cannot get PackageManager.");
+                throw new IllegalStateException("Cannot get PackageManager.");
             }
             final ResolveInfo info = packageManager.resolveService(intent, 0 /* flags */);
             if (info == null) {
@@ -1579,24 +1599,25 @@
             exemptedPackages = new ArrayList<>(mLockdownAllowlist);
             exemptedPackages.add(mPackage);
         }
-        final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd);
+        final Set<UidRangeParcel> rangesToTellNetdToRemove =
+                new ArraySet<>(mBlockedUidsAsToldToNetd);
 
-        final Set<UidRange> rangesToTellNetdToAdd;
+        final Set<UidRangeParcel> rangesToTellNetdToAdd;
         if (enforce) {
-            final Set<UidRange> rangesThatShouldBeBlocked =
+            final Set<UidRange> restrictedProfilesRanges =
                     createUserAndRestrictedProfilesRanges(mUserId,
-                            /* allowedApplications */ null,
-                            /* disallowedApplications */ exemptedPackages);
+                    /* allowedApplications */ null,
+                    /* disallowedApplications */ exemptedPackages);
+            final Set<UidRangeParcel> rangesThatShouldBeBlocked = new ArraySet<>();
 
             // The UID range of the first user (0-99999) would block the IPSec traffic, which comes
             // directly from the kernel and is marked as uid=0. So we adjust the range to allow
             // it through (b/69873852).
-            for (UidRange range : rangesThatShouldBeBlocked) {
-                if (range.start == 0) {
-                    rangesThatShouldBeBlocked.remove(range);
-                    if (range.stop != 0) {
-                        rangesThatShouldBeBlocked.add(new UidRange(1, range.stop));
-                    }
+            for (UidRange range : restrictedProfilesRanges) {
+                if (range.start == 0 && range.stop != 0) {
+                    rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop));
+                } else if (range.start != 0) {
+                    rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop));
                 }
             }
 
@@ -1628,13 +1649,13 @@
      *         including added ranges that already existed or removed ones that didn't.
      */
     @GuardedBy("this")
-    private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
+    private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges) {
         if (ranges.size() == 0) {
             return true;
         }
-        final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
+        final UidRangeParcel[] stableRanges = ranges.toArray(new UidRangeParcel[ranges.size()]);
         try {
-            mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
+            mNetd.networkRejectNonSecureVpn(enforce, stableRanges);
         } catch (RemoteException | RuntimeException e) {
             Log.e(TAG, "Updating blocked=" + enforce
                     + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
@@ -1778,7 +1799,7 @@
                 if (networks[i] == null) {
                     mConfig.underlyingNetworks[i] = null;
                 } else {
-                    mConfig.underlyingNetworks[i] = new Network(networks[i].netId);
+                    mConfig.underlyingNetworks[i] = new Network(networks[i].getNetId());
                 }
             }
         }
@@ -1849,10 +1870,20 @@
         if (mNetworkInfo.isConnected()) {
             return !appliesToUid(uid);
         } else {
-            return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid);
+            return containsUid(mBlockedUidsAsToldToNetd, uid);
         }
     }
 
+    private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) {
+        if (ranges == null) return false;
+        for (UidRangeParcel range : ranges) {
+            if (range.start <= uid && uid <= range.stop) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void updateAlwaysOnNotification(DetailedState networkState) {
         final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
 
@@ -1944,10 +1975,6 @@
             return mContext.createContextAsUser(
                     UserHandle.of(userId), 0 /* flags */).getContentResolver();
         }
-
-        public boolean isCallerSystem() {
-            return Binder.getCallingUid() == Process.SYSTEM_UID;
-        }
     }
 
     private native int jniCreate(int mtu);
@@ -2495,7 +2522,7 @@
                                     address /* unused */,
                                     address /* unused */,
                                     network);
-                    mNetd.setInterfaceUp(mTunnelIface.getInterfaceName());
+                    mNms.setInterfaceUp(mTunnelIface.getInterfaceName());
 
                     mSession = mIkev2SessionCreator.createIkeSession(
                             mContext,
@@ -3097,7 +3124,7 @@
     @VisibleForTesting
     @Nullable
     VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) {
-        if (!mSystemServices.isCallerSystem()) {
+        if (!mDeps.isCallerSystem()) {
             Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID ");
             return null;
         }
diff --git a/services/core/java/com/android/server/contentcapture/OWNERS b/services/core/java/com/android/server/contentcapture/OWNERS
new file mode 100644
index 0000000..a28e00a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contentcapture/OWNERS
diff --git a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
index 0f1e666..d74c702 100644
--- a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
+++ b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
@@ -217,7 +217,6 @@
                 }
 
                 final LocalDate cutOffDate = mInjector.getLocalDate().minusDays(MAX_DAYS_TO_TRACK);
-                parser.next();
                 int outerDepth = parser.getDepth();
                 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                         && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 7a8ba9f..2375f74 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -622,7 +622,6 @@
 
             final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;
 
-            parser.next();
             int outerDepth = parser.getDepth();
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a8e56a1..574d8c6 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -21,6 +21,7 @@
 import android.view.DisplayAddress;
 
 import com.android.server.display.config.DisplayConfiguration;
+import com.android.server.display.config.DisplayQuirks;
 import com.android.server.display.config.NitsMap;
 import com.android.server.display.config.Point;
 import com.android.server.display.config.XmlParser;
@@ -32,6 +33,7 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -45,6 +47,8 @@
 
     public static final float HIGH_BRIGHTNESS_MODE_UNSUPPORTED = Float.NaN;
 
+    public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
+
     private static final String ETC_DIR = "etc";
     private static final String DISPLAY_CONFIG_DIR = "displayconfig";
     private static final String CONFIG_FILE_FORMAT = "display_%s.xml";
@@ -55,6 +59,7 @@
 
     private float[] mNits;
     private float[] mBrightness;
+    private List<String> mQuirks;
 
     private DisplayDeviceConfig() {
     }
@@ -134,11 +139,21 @@
         return mBrightness;
     }
 
+    /**
+     * @param quirkValue The quirk to test.
+     * @return {@code true} if the specified quirk is present in this configuration,
+     * {@code false} otherwise.
+     */
+    public boolean hasQuirk(String quirkValue) {
+        return mQuirks != null && mQuirks.contains(quirkValue);
+    }
+
     @Override
     public String toString() {
         String str = "DisplayDeviceConfig{"
                 + "mBrightness=" + Arrays.toString(mBrightness)
                 + ", mNits=" + Arrays.toString(mNits)
+                + ", mQuirks=" + mQuirks
                 + "}";
         return str;
     }
@@ -173,6 +188,7 @@
         try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
             final DisplayConfiguration config = XmlParser.read(in);
             loadBrightnessMap(config);
+            loadQuirks(config);
         } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
             Slog.e(TAG, "Encountered an error while reading/parsing display config file: "
                     + configFile, e);
@@ -210,4 +226,11 @@
         mNits = nits;
         mBrightness = backlight;
     }
+
+    private void loadQuirks(DisplayConfiguration config) {
+        final DisplayQuirks quirks = config.getQuirks();
+        if (quirks != null) {
+            mQuirks = new ArrayList<>(quirks.getQuirk());
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d4a19d6..2c7cd5b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -403,7 +403,7 @@
         mUiHandler = UiThread.getHandler();
         mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
         mLogicalDisplayMapper = new LogicalDisplayMapper(context, mDisplayDeviceRepo,
-                new LogicalDisplayListener(), mPersistentDataStore);
+                new LogicalDisplayListener());
         mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
         Resources resources = mContext.getResources();
         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 74ea2d7..9b8ed3a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -177,14 +177,15 @@
 
     private final class LocalDisplayDevice extends DisplayDevice {
         private final long mPhysicalDisplayId;
-        private final LogicalLight mBacklight;
         private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
         private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
         private final boolean mIsDefaultDisplay;
+        private final BacklightAdapter mBacklightAdapter;
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
         private int mState = Display.STATE_UNKNOWN;
+        // This is only set in the runnable returned from requestDisplayStateLocked.
         private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         private int mDefaultModeId;
         private int mDefaultConfigGroup;
@@ -205,7 +206,6 @@
         private SurfaceControl.DisplayConfig[] mDisplayConfigs;
         private Spline mSystemBrightnessToNits;
         private Spline mNitsToHalBrightness;
-
         private DisplayDeviceConfig mDisplayDeviceConfig;
 
         private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
@@ -222,18 +222,13 @@
             updateDisplayPropertiesLocked(info, configs, activeConfigId, configSpecs, colorModes,
                     activeColorMode, hdrCapabilities);
             mSidekickInternal = LocalServices.getService(SidekickInternal.class);
-            if (mIsDefaultDisplay) {
-                LightsManager lights = LocalServices.getService(LightsManager.class);
-                mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
-            } else {
-                mBacklight = null;
-            }
+            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay);
             mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
             mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
             mDisplayDeviceConfig = null;
             // Defer configuration file loading
             BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
-                    LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this));
+                    LocalDisplayDevice::loadDisplayConfiguration, this));
         }
 
         @Override
@@ -415,7 +410,7 @@
             return mDisplayDeviceConfig;
         }
 
-        private void loadDisplayConfigurationBrightnessMapping() {
+        private void loadDisplayConfiguration() {
             Spline nitsToHal = null;
             Spline sysToNits = null;
 
@@ -425,6 +420,9 @@
                 return;
             }
 
+            mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
+                    DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC));
+
             final float[] halNits = mDisplayDeviceConfig.getNits();
             final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
             if (halNits == null || halBrightness == null) {
@@ -643,8 +641,7 @@
                     brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT);
             final boolean stateChanged = (mState != state);
             final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
-                    mBrightnessState, brightnessState))
-                    && mBacklight != null;
+                    mBrightnessState, brightnessState));
             if (stateChanged || brightnessChanged) {
                 final long physicalDisplayId = mPhysicalDisplayId;
                 final IBinder token = getDisplayTokenLocked();
@@ -655,10 +652,6 @@
                     updateDeviceInfoLocked();
                 }
 
-                if (brightnessChanged) {
-                    mBrightnessState = brightnessState;
-                }
-
                 // Defer actually setting the display state until after we have exited
                 // the critical section since it can take hundreds of milliseconds
                 // to complete.
@@ -698,6 +691,7 @@
                         // Apply brightness changes given that we are in a non-suspended state.
                         if (brightnessChanged || vrModeChange) {
                             setDisplayBrightness(brightnessState);
+                            mBrightnessState = brightnessState;
                         }
 
                         // Enter the final desired state, possibly suspended.
@@ -712,9 +706,7 @@
                                     + "id=" + physicalDisplayId
                                     + ", state=" + Display.stateToString(state) + ")");
                         }
-                        if (mBacklight != null) {
-                            mBacklight.setVrMode(isVrEnabled);
-                        }
+                        mBacklightAdapter.setVrMode(isVrEnabled);
                     }
 
                     private void setDisplayState(int state) {
@@ -770,13 +762,8 @@
                         Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                                 + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
                         try {
-                            if (isHalBrightnessRangeSpecified()) {
-                                brightness = displayBrightnessToHalBrightness(
-                                        BrightnessSynchronizer.brightnessFloatToIntRange(brightness));
-                            }
-                            if (mBacklight != null) {
-                                mBacklight.setBrightness(brightness);
-                            }
+                            brightness = displayBrightnessToHalBrightness(brightness);
+                            mBacklightAdapter.setBrightness(brightness);
                             Trace.traceCounter(Trace.TRACE_TAG_POWER,
                                     "ScreenBrightness",
                                     BrightnessSynchronizer.brightnessFloatToInt(brightness));
@@ -785,26 +772,33 @@
                         }
                     }
 
-                    private boolean isHalBrightnessRangeSpecified() {
-                        return !(mSystemBrightnessToNits == null || mNitsToHalBrightness == null);
-                    }
-
                     /**
                      * Converts brightness range from the framework's brightness space to the
                      * Hal brightness space if the HAL brightness space has been provided via
                      * a display device configuration file.
                      */
                     private float displayBrightnessToHalBrightness(float brightness) {
-                        if (!isHalBrightnessRangeSpecified()) {
-                            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+                        // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness
+                        // relationship should be specified in display-config OR config.xml, but not
+                        // both, and no nits-space conversion should be necessary.
+                        //
+                        // Only do a conversion if there exists a unique system brightness and a
+                        // unique HAL brightness-to-nits range defined.
+                        if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) {
+                            return brightness;
                         }
 
+                        // Sys brightness in this conversion is always specified in the old 1-255
+                        // range, so convert that here before the translation.
+                        final float brightnessInt =
+                                BrightnessSynchronizer.brightnessFloatToIntRange(brightness);
+
                         if (BrightnessSynchronizer.floatEquals(
-                                brightness, PowerManager.BRIGHTNESS_OFF)) {
+                                brightnessInt, PowerManager.BRIGHTNESS_OFF)) {
                             return PowerManager.BRIGHTNESS_OFF_FLOAT;
                         }
 
-                        final float nits = mSystemBrightnessToNits.interpolate(brightness);
+                        final float nits = mSystemBrightnessToNits.interpolate(brightnessInt);
                         final float halBrightness = mNitsToHalBrightness.interpolate(nits);
                         return halBrightness;
                     }
@@ -988,7 +982,7 @@
             pw.println("mDefaultModeId=" + mDefaultModeId);
             pw.println("mState=" + Display.stateToString(mState));
             pw.println("mBrightnessState=" + mBrightnessState);
-            pw.println("mBacklight=" + mBacklight);
+            pw.println("mBacklightAdapter=" + mBacklightAdapter);
             pw.println("mAllmSupported=" + mAllmSupported);
             pw.println("mAllmRequested=" + mAllmRequested);
             pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported);
@@ -1209,4 +1203,57 @@
             }
         }
     }
+
+    static class BacklightAdapter {
+        private final IBinder mDisplayToken;
+        private final LogicalLight mBacklight;
+        private final boolean mUseSurfaceControlBrightness;
+
+        private boolean mForceSurfaceControl = false;
+
+        /**
+         * @param displayToken Token for display associated with this backlight.
+         * @param isDefaultDisplay {@code true} if it is the default display.
+         * @param forceSurfaceControl {@code true} if brightness should always be
+         *                            set via SurfaceControl API.
+         */
+        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
+            mDisplayToken = displayToken;
+
+            mUseSurfaceControlBrightness =
+                    SurfaceControl.getDisplayBrightnessSupport(mDisplayToken);
+
+            if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
+                LightsManager lights = LocalServices.getService(LightsManager.class);
+                mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+            } else {
+                mBacklight = null;
+            }
+        }
+
+        void setBrightness(float brightness) {
+            if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
+                SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
+            } else if (mBacklight != null) {
+                mBacklight.setBrightness(brightness);
+            }
+        }
+
+        void setVrMode(boolean isVrModeEnabled) {
+            if (mBacklight != null) {
+                mBacklight.setVrMode(isVrModeEnabled);
+            }
+        }
+
+        void setForceSurfaceControl(boolean forceSurfaceControl) {
+            mForceSurfaceControl = forceSurfaceControl;
+        }
+
+        @Override
+        public String toString() {
+            return "BacklightAdapter [useSurfaceControl=" + mUseSurfaceControlBrightness
+                    + " (force_anyway? " + mForceSurfaceControl + ")"
+                    + ", backlight=" + mBacklight + "]";
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index cdcbb4f..a127858 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -20,13 +20,13 @@
 import android.os.Process;
 import android.os.SystemProperties;
 import android.text.TextUtils;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayEventReceiver;
 import android.view.DisplayInfo;
 
-import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -102,13 +102,10 @@
     private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>();
 
     private final DisplayDeviceRepository mDisplayDeviceRepo;
-    private final PersistentDataStore mPersistentDataStore;
     private final Listener mListener;
 
-    LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener,
-            PersistentDataStore persistentDataStore) {
+    LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener) {
         mDisplayDeviceRepo = repo;
-        mPersistentDataStore = persistentDataStore;
         mListener = listener;
         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
         mDisplayDeviceRepo.addListener(this);
@@ -238,7 +235,7 @@
         // Find the associated LogicalDisplays for the configured "folding" DeviceDisplays.
         final LogicalDisplay displayFolded = getLocked(deviceFolded);
         final LogicalDisplay displayUnfolded = getLocked(deviceUnfolded);
-        if (displayFolded == null || displayFolded == null) {
+        if (displayFolded == null || displayUnfolded == null) {
             // If the expected displays are not present, return early.
             return;
         }
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 92a3ccf..727944d 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -77,7 +77,6 @@
 import com.android.server.DisplayThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
@@ -119,6 +118,7 @@
     private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 3;
     private static final int MSG_APPLY_GLOBAL_SATURATION = 4;
     private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 5;
+    private static final int MSG_APPLY_REDUCE_BRIGHT_COLORS = 6;
 
     /**
      * Return value if a setting has not been set.
@@ -129,17 +129,6 @@
      * Evaluator used to animate color matrix transitions.
      */
     private static final ColorMatrixEvaluator COLOR_MATRIX_EVALUATOR = new ColorMatrixEvaluator();
-
-    private final NightDisplayTintController mNightDisplayTintController =
-            new NightDisplayTintController();
-
-    @VisibleForTesting
-    final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
-            new DisplayWhiteBalanceTintController();
-
-    private final TintController mGlobalSaturationTintController =
-            new GlobalSaturationTintController();
-
     /**
      * Matrix and offset used for converting color to grayscale.
      */
@@ -163,6 +152,16 @@
             1f, 1f, 1f, 1f
     };
 
+    @VisibleForTesting
+    final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
+            new DisplayWhiteBalanceTintController();
+    private final NightDisplayTintController mNightDisplayTintController =
+            new NightDisplayTintController();
+    private final TintController mGlobalSaturationTintController =
+            new GlobalSaturationTintController();
+    private final ReduceBrightColorsTintController mReduceBrightColorsTintController =
+            new ReduceBrightColorsTintController();
+
     private final Handler mHandler;
 
     private final AppSaturationController mAppSaturationController = new AppSaturationController();
@@ -354,6 +353,14 @@
                             case Secure.DISPLAY_WHITE_BALANCE_ENABLED:
                                 updateDisplayWhiteBalanceStatus();
                                 break;
+                            case Secure.REDUCE_BRIGHT_COLORS_ACTIVATED:
+                                onReduceBrightColorsActivationChanged();
+                                mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+                                break;
+                            case Secure.REDUCE_BRIGHT_COLORS_LEVEL:
+                                onReduceBrightColorsStrengthLevelChanged();
+                                mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+                                break;
                         }
                     }
                 }
@@ -372,17 +379,19 @@
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
         cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
-        cr.registerContentObserver(
-                Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+        cr.registerContentObserver(Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
         cr.registerContentObserver(
                 Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
-        cr.registerContentObserver(
-                Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER),
+        cr.registerContentObserver(Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
         cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED),
                 false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+        cr.registerContentObserver(Secure.getUriFor(Secure.REDUCE_BRIGHT_COLORS_ACTIVATED),
+                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+        cr.registerContentObserver(Secure.getUriFor(Secure.REDUCE_BRIGHT_COLORS_LEVEL),
+                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
 
         // Apply the accessibility settings first, since they override most other settings.
         onAccessibilityInversionChanged();
@@ -420,6 +429,17 @@
 
             updateDisplayWhiteBalanceStatus();
         }
+
+        if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+            mReduceBrightColorsTintController
+                    .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
+            onReduceBrightColorsStrengthLevelChanged();
+            final boolean reset = resetReduceBrightColors();
+            if (!reset) {
+                onReduceBrightColorsActivationChanged();
+                mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+            }
+        }
     }
 
     private void tearDown() {
@@ -444,6 +464,27 @@
         if (mGlobalSaturationTintController.isAvailable(getContext())) {
             mGlobalSaturationTintController.setActivated(null);
         }
+
+        if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+            mReduceBrightColorsTintController.setActivated(null);
+        }
+    }
+
+    private boolean resetReduceBrightColors() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return false;
+        }
+
+        final boolean isSettingActivated = Secure.getIntForUser(getContext().getContentResolver(),
+                Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1;
+        final boolean shouldResetOnReboot = Secure.getIntForUser(getContext().getContentResolver(),
+                Secure.REDUCE_BRIGHT_COLORS_PERSIST_ACROSS_REBOOTS, 0, mCurrentUser) == 0;
+        if (isSettingActivated && mReduceBrightColorsTintController.isActivatedStateNotSet()
+                && shouldResetOnReboot) {
+            return Secure.putIntForUser(getContext().getContentResolver(),
+                    Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser);
+        }
+        return false;
     }
 
     private void onNightDisplayAutoModeChanged(int autoMode) {
@@ -572,6 +613,24 @@
                 isAccessiblityInversionEnabled() ? MATRIX_INVERT_COLOR : null);
     }
 
+    private void onReduceBrightColorsActivationChanged() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return;
+        }
+        mReduceBrightColorsTintController.setActivated(
+                Secure.getIntForUser(getContext().getContentResolver(),
+                        Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1);
+    }
+
+    private void onReduceBrightColorsStrengthLevelChanged() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return;
+        }
+        mReduceBrightColorsTintController.setMatrix(
+                Secure.getIntForUser(getContext().getContentResolver(),
+                        Secure.REDUCE_BRIGHT_COLORS_LEVEL, 0, mCurrentUser));
+    }
+
     /**
      * Applies current color temperature matrix, or removes it if deactivated.
      *
@@ -937,6 +996,14 @@
             pw.println("    Not available");
         }
 
+        pw.println("Reduce bright colors:");
+        if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+            pw.println("    Activated: " + mReduceBrightColorsTintController.isActivated());
+            mReduceBrightColorsTintController.dump(pw);
+        } else {
+            pw.println("    Not available");
+        }
+
         pw.println("Color mode: " + getColorModeInternal());
     }
 
@@ -1438,6 +1505,9 @@
                     mGlobalSaturationTintController.setMatrix(msg.arg1);
                     applyTint(mGlobalSaturationTintController, false);
                     break;
+                case MSG_APPLY_REDUCE_BRIGHT_COLORS:
+                    applyTint(mReduceBrightColorsTintController, true);
+                    break;
                 case MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE:
                     applyTint(mNightDisplayTintController, true);
                     break;
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index 3b0069c..5c68c51 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -59,6 +59,10 @@
      */
     public static final int LEVEL_COLOR_MATRIX_GRAYSCALE = 200;
     /**
+     * Color transform level used by A11y services to reduce bright colors.
+     */
+    public static final int LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS = 250;
+    /**
      * Color transform level used by A11y services to invert the display colors.
      */
     public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300;
@@ -97,7 +101,7 @@
      * Map of level -> color transformation matrix.
      */
     @GuardedBy("mColorMatrix")
-    private final SparseArray<float[]> mColorMatrix = new SparseArray<>(5);
+    private final SparseArray<float[]> mColorMatrix = new SparseArray<>(6);
     /**
      * Temporary matrix used internally by {@link #computeColorMatrixLocked()}.
      */
diff --git a/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
new file mode 100644
index 0000000..7e120c9
--- /dev/null
+++ b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
@@ -0,0 +1,113 @@
+/*
+ * 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.display.color;
+
+import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS;
+
+import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
+import android.opengl.Matrix;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Control the color transform for bright color reduction.
+ */
+public class ReduceBrightColorsTintController extends TintController {
+
+    private final float[] mMatrix = new float[16];
+    private final float[] mCoefficients = new float[9];
+
+    private int mStrength;
+
+    @Override
+    public void setUp(Context context, boolean needsLinear) {
+        final String[] coefficients = context.getResources().getStringArray(
+                needsLinear ? R.array.config_reduceBrightColorsCoefficients
+                        : R.array.config_reduceBrightColorsCoefficientsNative);
+        for (int i = 0; i < 9 && i < coefficients.length; i++) {
+            mCoefficients[i] = Float.parseFloat(coefficients[i]);
+        }
+    }
+
+    @Override
+    public float[] getMatrix() {
+        return isActivated() ? Arrays.copyOf(mMatrix, mMatrix.length)
+                : ColorDisplayService.MATRIX_IDENTITY;
+    }
+
+    @Override
+    public void setMatrix(int strengthLevel) {
+        // Clamp to valid range.
+        if (strengthLevel < 0) {
+            strengthLevel = 0;
+        } else if (strengthLevel > 100) {
+            strengthLevel = 100;
+        }
+        Slog.d(ColorDisplayService.TAG, "Setting bright color reduction level: " + strengthLevel);
+        mStrength = strengthLevel;
+
+        Matrix.setIdentityM(mMatrix, 0);
+
+        final float percentageStrength = strengthLevel / 100f;
+        final float squaredPercentageStrength = percentageStrength * percentageStrength;
+        final float red =
+                squaredPercentageStrength * mCoefficients[0] + percentageStrength * mCoefficients[1]
+                        + mCoefficients[2];
+        final float green =
+                squaredPercentageStrength * mCoefficients[3] + percentageStrength * mCoefficients[4]
+                        + mCoefficients[5];
+        final float blue =
+                squaredPercentageStrength * mCoefficients[6] + percentageStrength * mCoefficients[7]
+                        + mCoefficients[8];
+        mMatrix[0] = clamp(red);
+        mMatrix[5] = clamp(green);
+        mMatrix[10] = clamp(blue);
+    }
+
+    private float clamp(float value) {
+        if (value > 1f) {
+            return 1f;
+        } else if (value < 0f) {
+            return 0f;
+        }
+        return value;
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.println("    mStrength = " + mStrength);
+    }
+
+    @Override
+    public int getLevel() {
+        return LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS;
+    }
+
+    @Override
+    public boolean isAvailable(Context context) {
+        return ColorDisplayManager.isColorTransformAccelerated(context);
+    }
+
+    public int getStrength() {
+        return mStrength;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
index b52ab76..1a0a639 100644
--- a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
@@ -20,6 +20,7 @@
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiPlaybackClient.DisplayStatusCallback;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.os.RemoteException;
 import android.util.Slog;
 
@@ -42,6 +43,10 @@
     private final int mTargetAddress;
     private final List<IHdmiControlCallback> mCallbacks = new ArrayList<>();
 
+    // Retry the power status query as it might happen when the target device is waking up. In
+    // that case a device may be quite busy and can fail to respond within the 2s timeout.
+    private int mRetriesOnTimeout = 1;
+
     static DevicePowerStatusAction create(HdmiCecLocalDevice source,
             int targetAddress, IHdmiControlCallback callback) {
         if (source == null || callback == null) {
@@ -68,13 +73,21 @@
 
     private void queryDevicePowerStatus() {
         sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
-                mTargetAddress));
+                mTargetAddress), error -> {
+                // Don't retry on timeout if the remote device didn't even ACK the message. Assume
+                // the device is not present or not capable of CEC.
+                if (error == SendMessageResult.NACK) {
+                    // Got no response from TV. Report status 'unknown'.
+                    invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN);
+                    finish();
+                }
+            });
     }
 
     @Override
     boolean processCommand(HdmiCecMessage cmd) {
         if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS
-               || mTargetAddress != cmd.getSource()) {
+                || mTargetAddress != cmd.getSource()) {
             return false;
         }
         if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) {
@@ -92,6 +105,12 @@
             return;
         }
         if (state == STATE_WAITING_FOR_REPORT_POWER_STATUS) {
+            if (mRetriesOnTimeout > 0) {
+                mRetriesOnTimeout--;
+                start();
+                return;
+            }
+
             // Got no response from TV. Report status 'unknown'.
             invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN);
             finish();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
index 98d130f..371fd3d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
@@ -85,7 +85,7 @@
 
     @NonNull private final Context mContext;
     @NonNull private final StorageAdapter mStorageAdapter;
-    @Nullable private final CecSettings mProductConfig;
+    @Nullable private final CecSettings mSystemConfig;
     @Nullable private final CecSettings mVendorOverride;
 
     /**
@@ -162,14 +162,14 @@
     @VisibleForTesting
     HdmiCecConfig(@NonNull Context context,
                   @NonNull StorageAdapter storageAdapter,
-                  @Nullable CecSettings productConfig,
+                  @Nullable CecSettings systemConfig,
                   @Nullable CecSettings vendorOverride) {
         mContext = context;
         mStorageAdapter = storageAdapter;
-        mProductConfig = productConfig;
+        mSystemConfig = systemConfig;
         mVendorOverride = vendorOverride;
-        if (mProductConfig == null) {
-            Slog.i(TAG, "CEC master configuration XML missing.");
+        if (mSystemConfig == null) {
+            Slog.i(TAG, "CEC system configuration XML missing.");
         }
         if (mVendorOverride == null) {
             Slog.i(TAG, "CEC OEM configuration override XML missing.");
@@ -178,7 +178,7 @@
 
     HdmiCecConfig(@NonNull Context context) {
         this(context, new StorageAdapter(context),
-             readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(),
+             readSettingsFromFile(Environment.buildPath(Environment.getRootDirectory(),
                                                         ETC_DIR, CONFIG_FILE)),
              readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(),
                                                         ETC_DIR, CONFIG_FILE)));
@@ -226,7 +226,7 @@
 
     @Nullable
     private Setting getSetting(@NonNull String name) {
-        if (mProductConfig == null) {
+        if (mSystemConfig == null) {
             return null;
         }
         if (mVendorOverride != null) {
@@ -237,8 +237,8 @@
                 }
             }
         }
-        // If not found, try the product config.
-        for (Setting setting : mProductConfig.getSetting()) {
+        // If not found, try the system config.
+        for (Setting setting : mSystemConfig.getSetting()) {
             if (setting.getName().equals(name)) {
                 return setting;
             }
@@ -322,11 +322,11 @@
      * Returns a list of all settings based on the XML metadata.
      */
     public @CecSettingName List<String> getAllSettings() {
-        if (mProductConfig == null) {
+        if (mSystemConfig == null) {
             return new ArrayList<String>();
         }
         List<String> allSettings = new ArrayList<String>();
-        for (Setting setting : mProductConfig.getSetting()) {
+        for (Setting setting : mSystemConfig.getSetting()) {
             allSettings.add(setting.getName());
         }
         return allSettings;
@@ -336,12 +336,12 @@
      * Returns a list of user-modifiable settings based on the XML metadata.
      */
     public @CecSettingName List<String> getUserSettings() {
-        if (mProductConfig == null) {
+        if (mSystemConfig == null) {
             return new ArrayList<String>();
         }
         Set<String> userSettings = new HashSet<String>();
-        // First read from the product config.
-        for (Setting setting : mProductConfig.getSetting()) {
+        // First read from the system config.
+        for (Setting setting : mSystemConfig.getSetting()) {
             if (setting.getUserConfigurable()) {
                 userSettings.add(setting.getName());
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index bbd5ac3..ddb0141 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -26,6 +26,8 @@
 import android.hardware.tv.cec.V1_0.IHdmiCecCallback;
 import android.hardware.tv.cec.V1_0.Result;
 import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.icu.util.IllformedLocaleException;
+import android.icu.util.ULocale;
 import android.os.Handler;
 import android.os.IHwBinder;
 import android.os.Looper;
@@ -33,6 +35,7 @@
 import android.stats.hdmi.HdmiStatsEnums;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
@@ -49,8 +52,6 @@
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.function.Predicate;
 
-import sun.util.locale.LanguageTag;
-
 /**
  * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
  * and pass it to CEC HAL so that it sends message to other device. For incoming
@@ -352,13 +353,31 @@
     @ServiceThreadOnly
     void setLanguage(String language) {
         assertRunOnServiceThread();
-        if (!LanguageTag.isLanguage(language)) {
+        if (!isLanguage(language)) {
             return;
         }
         mNativeWrapperImpl.nativeSetLanguage(language);
     }
 
     /**
+     * Returns true if the language code is well-formed.
+     */
+    @VisibleForTesting static boolean isLanguage(String language) {
+        // Handle null and empty string because because ULocale.Builder#setLanguage accepts them.
+        if (language == null || language.isEmpty()) {
+            return false;
+        }
+
+        ULocale.Builder builder = new ULocale.Builder();
+        try {
+            builder.setLanguage(language);
+            return true;
+        } catch (IllformedLocaleException e) {
+            return false;
+        }
+    }
+
+    /**
      * Configure ARC circuit in the hardware logic to start or stop the feature.
      *
      * @param port ID of HDMI port to which AVR is connected
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 9b3f788..52121f3 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -282,6 +282,8 @@
                 return handleGiveOsdName(message);
             case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
                 return handleGiveDeviceVendorId(null);
+            case Constants.MESSAGE_CEC_VERSION:
+                return handleCecVersion();
             case Constants.MESSAGE_GET_CEC_VERSION:
                 return handleGetCecVersion(message);
             case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
@@ -406,6 +408,14 @@
     }
 
     @ServiceThreadOnly
+    private boolean handleCecVersion() {
+        assertRunOnServiceThread();
+
+        // Return true to avoid <Feature Abort> responses. Cec Version is tracked in HdmiCecNetwork.
+        return true;
+    }
+
+    @ServiceThreadOnly
     protected boolean handleActiveSource(HdmiCecMessage message) {
         return false;
     }
@@ -613,6 +623,14 @@
             return false;
         }
 
+        if (isPowerOffOrToggleCommand(message) || isPowerOnOrToggleCommand(message)) {
+            // Power commands should already be handled above. Don't continue and convert the CEC
+            // keycode to Android keycode.
+            // Do not <Feature Abort> as the local device should already be in the correct power
+            // state.
+            return true;
+        }
+
         final long downTime = SystemClock.uptimeMillis();
         final byte[] params = message.getParams();
         final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index d2a2d72..2bf74c9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -156,7 +156,6 @@
         addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT);
         addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT);
 
-        // TODO: Handle messages for the Tuner Control.
         addValidationInfo(
                 Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT);
         addValidationInfo(
@@ -167,6 +166,10 @@
                 Constants.MESSAGE_SELECT_DIGITAL_SERVICE,
                 new SelectDigitalServiceValidator(),
                 DEST_DIRECT);
+        addValidationInfo(
+                Constants.MESSAGE_TUNER_DEVICE_STATUS,
+                new TunerDeviceStatusValidator(),
+                DEST_DIRECT);
 
         // Messages for the Vendor Specific Commands.
         VariableLengthValidator maxLengthValidator = new VariableLengthValidator(0, 14);
@@ -317,7 +320,14 @@
     }
 
     private boolean isValidPhysicalAddress(byte[] params, int offset) {
-        // TODO: Add more logic like validating 1.0.1.0.
+        int physicalAddress = HdmiUtils.twoBytesToInt(params, offset);
+        while (physicalAddress != 0) {
+            int maskedAddress = physicalAddress & 0xF000;
+            physicalAddress = (physicalAddress << 4) & 0xFFFF;
+            if (maskedAddress == 0 && physicalAddress != 0) {
+                return false;
+            }
+        }
 
         if (!mService.isTvDevice()) {
             // If the device is not TV, we can't convert path to port-id, so stop here.
@@ -733,6 +743,35 @@
                 || (isWithinRange(value, 0xC1, 0xC3)));
     }
 
+    /*
+     * Check if the given value is a valid Tuner Device info. A valid value is one which falls
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions
+     * (Section 17)
+     *
+     * @param params Tuner device info
+     * @return true if the Tuner device info is valid
+     */
+    private boolean isValidTunerDeviceInfo(byte[] params) {
+        int tunerDisplayInfo = params[0] & 0x7F;
+        if (tunerDisplayInfo == 0x00) {
+            // Displaying digital tuner
+            if (params.length >= 5) {
+                return isValidDigitalServiceIdentification(params, 1);
+            }
+        } else if (tunerDisplayInfo == 0x01) {
+            // Not displaying Tuner
+            return true;
+        } else if (tunerDisplayInfo == 0x02) {
+            // Displaying Analogue tuner
+            if (params.length >= 5) {
+                return (isValidAnalogueBroadcastType(params[1])
+                        && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 2))
+                        && isValidBroadcastSystem(params[4]));
+            }
+        }
+        return false;
+    }
+
     private class PhysicalAddressValidator implements ParameterValidator {
         @Override
         public int isValid(byte[] params) {
@@ -1011,6 +1050,21 @@
         }
     }
 
+    /**
+     * Check if the given tuner device status parameter is valid. A valid parameter should lie
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
+     * 17)
+     */
+    private class TunerDeviceStatusValidator implements ParameterValidator {
+        @Override
+        public int isValid(byte[] params) {
+            if (params.length < 1) {
+                return ERROR_PARAMETER_SHORT;
+            }
+            return toErrorCode(isValidTunerDeviceInfo(params));
+        }
+    }
+
     /** Check if the given user control press parameter is valid. */
     private class UserControlPressedValidator implements ParameterValidator {
         @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
index fc21724..b748ae0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java
@@ -166,7 +166,6 @@
         }
         return false;
     }
-
     /**
      * Clear all logical addresses registered in the device.
      *
@@ -523,11 +522,32 @@
             case Constants.MESSAGE_DEVICE_VENDOR_ID:
                 handleDeviceVendorId(message);
                 break;
-
+            case Constants.MESSAGE_CEC_VERSION:
+                handleCecVersion(message);
+                break;
+            case Constants.MESSAGE_REPORT_FEATURES:
+                handleReportFeatures(message);
+                break;
         }
     }
 
     @ServiceThreadOnly
+    private void handleReportFeatures(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+
+        int version = Byte.toUnsignedInt(message.getParams()[0]);
+        updateDeviceCecVersion(message.getSource(), version);
+    }
+
+    @ServiceThreadOnly
+    private void handleCecVersion(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+
+        int version = Byte.toUnsignedInt(message.getParams()[0]);
+        updateDeviceCecVersion(message.getSource(), version);
+    }
+
+    @ServiceThreadOnly
     private void handleReportPhysicalAddress(HdmiCecMessage message) {
         assertRunOnServiceThread();
         int logicalAddress = message.getSource();
@@ -543,7 +563,8 @@
             HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(),
                     physicalAddress,
                     physicalAddressToPortId(physicalAddress), type, deviceInfo.getVendorId(),
-                    deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus());
+                    deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(),
+                    deviceInfo.getCecVersion());
             updateCecDevice(updatedDeviceInfo);
         }
     }
@@ -554,6 +575,31 @@
         // Update power status of device
         int newStatus = message.getParams()[0] & 0xFF;
         updateDevicePowerStatus(message.getSource(), newStatus);
+
+        if (message.getDestination() == Constants.ADDR_BROADCAST) {
+            updateDeviceCecVersion(message.getSource(), HdmiControlManager.HDMI_CEC_VERSION_2_0);
+        }
+    }
+
+    @ServiceThreadOnly
+    private void updateDeviceCecVersion(int logicalAddress, int hdmiCecVersion) {
+        assertRunOnServiceThread();
+        HdmiDeviceInfo deviceInfo = getCecDeviceInfo(logicalAddress);
+        if (deviceInfo == null) {
+            Slog.w(TAG, "Can not update CEC version of non-existing device:" + logicalAddress);
+            return;
+        }
+
+        if (deviceInfo.getCecVersion() == hdmiCecVersion) {
+            return;
+        }
+
+        HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(),
+                deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(),
+                deviceInfo.getVendorId(),
+                deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(),
+                hdmiCecVersion);
+        updateCecDevice(updatedDeviceInfo);
     }
 
     @ServiceThreadOnly
@@ -586,7 +632,7 @@
         updateCecDevice(new HdmiDeviceInfo(deviceInfo.getLogicalAddress(),
                 deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(),
                 deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName,
-                deviceInfo.getDevicePowerStatus()));
+                deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion()));
     }
 
     @ServiceThreadOnly
@@ -602,7 +648,8 @@
             HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(),
                     deviceInfo.getPhysicalAddress(),
                     deviceInfo.getPortId(), deviceInfo.getDeviceType(), vendorId,
-                    deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus());
+                    deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(),
+                    deviceInfo.getCecVersion());
             updateCecDevice(updatedDeviceInfo);
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a1d13e9..c15fdca 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -66,6 +66,8 @@
 import android.os.PowerManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -813,7 +815,7 @@
                                 // with system.
                                 HdmiDeviceInfo deviceInfo = createDeviceInfo(logicalAddress,
                                         deviceType,
-                                        HdmiControlManager.POWER_STATUS_ON);
+                                        HdmiControlManager.POWER_STATUS_ON, getCecVersion());
                                 localDevice.setDeviceInfo(deviceInfo);
                                 mHdmiCecNetwork.addLocalDevice(deviceType, localDevice);
                                 mCecController.addLogicalAddress(logicalAddress);
@@ -1222,11 +1224,12 @@
         }
     }
 
-    private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus) {
+    private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus,
+            int cecVersion) {
         String displayName = readStringSetting(Global.DEVICE_NAME, Build.MODEL);
         return new HdmiDeviceInfo(logicalAddress,
                 getPhysicalAddress(), pathToPortId(getPhysicalAddress()), deviceType,
-                getVendorId(), displayName, powerStatus);
+                getVendorId(), displayName, powerStatus, cecVersion);
     }
 
     // Set the display name in HdmiDeviceInfo of the current devices to content provided by
@@ -1240,7 +1243,7 @@
             device.setDeviceInfo(new HdmiDeviceInfo(
                     deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(),
                     deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(),
-                    newDisplayName, deviceInfo.getDevicePowerStatus()));
+                    newDisplayName, deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion()));
             sendCecCommand(HdmiCecMessageBuilder.buildSetOsdNameCommand(
                     device.mAddress, Constants.ADDR_TV, newDisplayName));
         }
@@ -1652,6 +1655,12 @@
         }
 
         @Override
+        public boolean shouldHandleTvPowerKey() {
+            enforceAccessPermission();
+            return HdmiControlService.this.shouldHandleTvPowerKey();
+        }
+
+        @Override
         public void queryDisplayStatus(final IHdmiControlCallback callback) {
             enforceAccessPermission();
             runOnServiceThread(new Runnable() {
@@ -2142,6 +2151,16 @@
         }
 
         @Override
+        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err, String[] args,
+                @Nullable ShellCallback callback, ResultReceiver resultReceiver)
+                throws RemoteException {
+            enforceAccessPermission();
+            new HdmiControlShellCommand(this)
+                    .exec(this, in, out, err, args, callback, resultReceiver);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2333,6 +2352,24 @@
         source.toggleAndFollowTvPower();
     }
 
+    @VisibleForTesting
+    protected boolean shouldHandleTvPowerKey() {
+        if (isTvDevice()) {
+            return false;
+        }
+        String powerControlMode = getHdmiCecConfig().getStringValue(
+                HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE);
+        if (powerControlMode.equals(HdmiControlManager.POWER_CONTROL_MODE_NONE)) {
+            return false;
+        }
+        int hdmiCecEnabled = getHdmiCecConfig().getIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
+        if (hdmiCecEnabled != HdmiControlManager.HDMI_CEC_CONTROL_ENABLED) {
+            return false;
+        }
+        return true;
+    }
+
     @ServiceThreadOnly
     protected void queryDisplayStatus(final IHdmiControlCallback callback) {
         assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
new file mode 100644
index 0000000..ee3427f
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -0,0 +1,160 @@
+/*
+ * 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.hdmi;
+
+
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.hdmi.IHdmiControlService;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+final class HdmiControlShellCommand extends ShellCommand {
+
+    private static final String TAG = "HdmiShellCommand";
+
+    private final IHdmiControlService.Stub mBinderService;
+
+
+    HdmiControlShellCommand(IHdmiControlService.Stub binderService) {
+        mBinderService = binderService;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+
+        try {
+            return handleShellCommand(cmd);
+        } catch (Exception e) {
+            getErrPrintWriter().println(
+                    "Caught error for command '" + cmd + "': " + e.getMessage());
+            Slog.e(TAG, "Error handling hdmi_control shell command: " + cmd, e);
+            return 1;
+        }
+    }
+
+    @Override
+    public void onHelp() {
+        PrintWriter pw = getOutPrintWriter();
+
+        pw.println("HdmiControlManager (hdmi_control) commands:");
+        pw.println("  help");
+        pw.println("      Print this help text.");
+        pw.println("  onetouchplay, otp");
+        pw.println("      Send the \"One Touch Play\" feature from a source to the TV");
+        pw.println("  vendorcommand --device_type <originating device type>");
+        pw.println("                --destination <destination device>");
+        pw.println("                --args <vendor specific arguments>");
+        pw.println("                [--id <true if vendor command should be sent with vendor id>]");
+        pw.println("      Send a Vendor Command to the given target device");
+    }
+
+    private int handleShellCommand(String cmd) throws RemoteException {
+        PrintWriter pw = getOutPrintWriter();
+
+        switch (cmd) {
+            case "otp":
+            case "onetouchplay":
+                return oneTouchPlay(pw);
+            case "vendorcommand":
+                return vendorCommand(pw);
+        }
+
+        getErrPrintWriter().println("Unhandled command: " + cmd);
+        return 1;
+    }
+
+    private int oneTouchPlay(PrintWriter pw) throws RemoteException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        AtomicInteger cecResult = new AtomicInteger();
+        pw.print("Sending One Touch Play...");
+        mBinderService.oneTouchPlay(new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                pw.println(" done (" + result + ")");
+                latch.countDown();
+                cecResult.set(result);
+            }
+        });
+
+        try {
+            if (!latch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                getErrPrintWriter().println("One Touch Play timed out.");
+                return 1;
+            }
+        } catch (InterruptedException e) {
+            getErrPrintWriter().println("Caught InterruptedException");
+            Thread.currentThread().interrupt();
+        }
+        return cecResult.get() == HdmiControlManager.RESULT_SUCCESS ? 0 : 1;
+    }
+
+    private int vendorCommand(PrintWriter pw) throws RemoteException {
+        if (6 > getRemainingArgsCount()) {
+            throw new IllegalArgumentException("Expected 3 arguments.");
+        }
+
+        int deviceType = -1;
+        int destination = -1;
+        String parameters = "";
+        boolean hasVendorId = false;
+
+        String arg = getNextOption();
+        while (arg != null) {
+            switch (arg) {
+                case "-t":
+                case "--device_type":
+                    deviceType = Integer.parseInt(getNextArgRequired());
+                    break;
+                case "-d":
+                case "--destination":
+                    destination = Integer.parseInt(getNextArgRequired());
+                    break;
+                case "-a":
+                case "--args":
+                    parameters = getNextArgRequired();
+                    break;
+                case "-i":
+                case "--id":
+                    hasVendorId = Boolean.parseBoolean(getNextArgRequired());
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown argument: " + arg);
+            }
+            arg = getNextArg();
+        }
+
+        String[] parts = parameters.split(":");
+        byte[] params = new byte[parts.length];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = (byte) Integer.parseInt(parts[i], 16);
+        }
+
+        pw.println("Sending <Vendor Command>");
+        mBinderService.sendVendorCommand(deviceType, destination, params, hasVendorId);
+        return 0;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 52a804a..03e5de8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -396,7 +396,7 @@
     static HdmiDeviceInfo cloneHdmiDeviceInfo(HdmiDeviceInfo info, int newPowerStatus) {
         return new HdmiDeviceInfo(info.getLogicalAddress(),
                 info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(),
-                info.getVendorId(), info.getDisplayName(), newPowerStatus);
+                info.getVendorId(), info.getDisplayName(), newPowerStatus, info.getCecVersion());
     }
 
     /**
diff --git a/services/core/java/com/android/server/hdmi/OWNERS b/services/core/java/com/android/server/hdmi/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/services/core/java/com/android/server/hdmi/cec_config.xml b/services/core/java/com/android/server/hdmi/cec_config.xml
new file mode 100644
index 0000000..480e0ec
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/cec_config.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<cec-settings>
+  <setting name="hdmi_cec_enabled"
+           value-type="int"
+           user-configurable="true">
+    <allowed-values>
+      <value int-value="0" />
+      <value int-value="1" />
+    </allowed-values>
+    <default-value int-value="1" />
+  </setting>
+  <setting name="hdmi_cec_version"
+           value-type="int"
+           user-configurable="true">
+    <allowed-values>
+      <value int-value="0x05" />
+      <value int-value="0x06" />
+    </allowed-values>
+    <default-value int-value="0x05" />
+  </setting>
+  <setting name="send_standby_on_sleep"
+           value-type="string"
+           user-configurable="true">
+    <allowed-values>
+      <value string-value="to_tv" />
+      <value string-value="broadcast" />
+      <value string-value="none" />
+    </allowed-values>
+    <default-value string-value="to_tv" />
+  </setting>
+  <setting name="power_state_change_on_active_source_lost"
+           value-type="string"
+           user-configurable="true">
+    <allowed-values>
+      <value string-value="none" />
+      <value string-value="standby_now" />
+    </allowed-values>
+    <default-value string-value="none" />
+  </setting>
+  <setting name="system_audio_mode_muting"
+           value-type="int"
+           user-configurable="true">
+    <allowed-values>
+      <value int-value="0" />
+      <value int-value="1" />
+    </allowed-values>
+    <default-value int-value="1" />
+  </setting>
+</cec-settings>
diff --git a/services/core/java/com/android/server/incident/OWNERS b/services/core/java/com/android/server/incident/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/services/core/java/com/android/server/incident/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 42aad7d..bff81e6 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -41,16 +41,19 @@
 import android.hardware.display.DisplayViewport;
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.IInputManager;
+import android.hardware.input.IInputSensorEventListener;
 import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerInternal;
 import android.hardware.input.InputManagerInternal.LidSwitchCallback;
+import android.hardware.input.InputSensorInfo;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.TouchCalibration;
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CombinedVibrationEffect;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -116,6 +119,7 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -180,12 +184,24 @@
     private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
             new ArrayList<>();
 
+    private final Object mSensorEventLock = new Object();
+    // List of currently registered sensor event listeners by process id
+    @GuardedBy("mSensorEventLock")
+    private final SparseArray<SensorEventListenerRecord> mSensorEventListeners =
+            new SparseArray<>();
+    private final List<SensorEventListenerRecord> mSensorEventListenersToNotify =
+            new ArrayList<>();
+    private final List<SensorEventListenerRecord> mSensorAccuracyListenersToNotify =
+            new ArrayList<>();
+
     // Persistent data store.  Must be locked each time during use.
     private final PersistentDataStore mDataStore = new PersistentDataStore();
 
     // List of currently registered input devices changed listeners by process id.
     private Object mInputDevicesLock = new Object();
+    @GuardedBy("mInputDevicesLock")
     private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
+    @GuardedBy("mInputDevicesLock")
     private InputDevice[] mInputDevices = new InputDevice[0];
     private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
             new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
@@ -203,7 +219,12 @@
     private int mNextVibratorTokenValue;
 
     // State for lid switch
+    // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events
+    // are delivered in order. For ex, when a new lid switch callback is registered the lock is held
+    // while the callback is processing the initial lid switch event which guarantees that any
+    // events that occur at the same time are delivered after the callback has returned.
     private final Object mLidSwitchLock = new Object();
+    @GuardedBy("mLidSwitchLock")
     private List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>();
 
     // State for the currently installed input filter.
@@ -238,7 +259,7 @@
             int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
     private static native InputChannel nativeCreateInputChannel(long ptr, String name);
     private static native InputChannel nativeCreateInputMonitor(long ptr, int displayId,
-            boolean isGestureMonitor, String name);
+            boolean isGestureMonitor, String name, int pid);
     private static native void nativeRemoveInputChannel(long ptr, IBinder connectionToken);
     private static native void nativePilferPointers(long ptr, IBinder token);
     private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
@@ -264,7 +285,11 @@
     private static native void nativeReloadCalibration(long ptr);
     private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
             int[] amplitudes, int repeat, int token);
+    private static native void nativeVibrateCombined(long ptr, int deviceId, long[] pattern,
+            SparseArray<int[]> amplitudes, int repeat, int token);
     private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
+    private static native boolean nativeIsVibrating(long ptr, int deviceId);
+    private static native int[] nativeGetVibratorIds(long ptr, int deviceId);
     private static native void nativeReloadKeyboardLayouts(long ptr);
     private static native void nativeReloadDeviceAliases(long ptr);
     private static native String nativeDump(long ptr);
@@ -275,10 +300,16 @@
     private static native void nativeSetPointerIconType(long ptr, int iconId);
     private static native void nativeReloadPointerIcons(long ptr);
     private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
-    private static native void nativeSetPointerCapture(long ptr, boolean detached);
+    private static native void nativeRequestPointerCapture(long ptr, IBinder windowToken,
+            boolean enabled);
     private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
     private static native void nativeNotifyPortAssociationsChanged(long ptr);
     private static native void nativeSetMotionClassifierEnabled(long ptr, boolean enabled);
+    private static native InputSensorInfo[] nativeGetSensorList(long ptr, int deviceId);
+    private static native boolean nativeFlushSensor(long ptr, int deviceId, int sensorType);
+    private static native boolean nativeEnableSensor(long ptr, int deviceId, int sensorType,
+            int samplingPeriodUs, int maxBatchReportLatencyUs);
+    private static native void nativeDisableSensor(long ptr, int deviceId, int sensorType);
 
     // Maximum number of milliseconds to wait for input event injection.
     private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
@@ -343,9 +374,6 @@
     public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
     public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE;
 
-    /** Indicates an open state for the lid switch. */
-    public static final int SW_STATE_LID_OPEN = 0;
-
     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
     final boolean mUseDevInputEventForAudioJack;
 
@@ -381,13 +409,18 @@
     }
 
     void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
-        boolean lidOpen;
         synchronized (mLidSwitchLock) {
             mLidSwitchCallbacks.add(callback);
-            lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
-                    == SW_STATE_LID_OPEN;
+
+            // Skip triggering the initial callback if the system is not yet ready as the switch
+            // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in
+            // systemRunning().
+            if (mSystemReady) {
+                boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
+                        == KEY_STATE_UP;
+                callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
+            }
         }
-        callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
     }
 
     void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
@@ -435,7 +468,18 @@
         }
         mNotificationManager = (NotificationManager)mContext.getSystemService(
                 Context.NOTIFICATION_SERVICE);
-        mSystemReady = true;
+
+        synchronized (mLidSwitchLock) {
+            mSystemReady = true;
+
+            // Send the initial lid switch state to any callback registered before the system was
+            // ready.
+            int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID);
+            for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
+                LidSwitchCallback callback = mLidSwitchCallbacks.get(i);
+                callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP);
+            }
+        }
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -563,7 +607,7 @@
         }
 
         return nativeCreateInputMonitor(mPtr, displayId, false /* isGestureMonitor */,
-                inputChannelName);
+                inputChannelName, Binder.getCallingPid());
     }
 
     /**
@@ -591,7 +635,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             InputChannel inputChannel = nativeCreateInputMonitor(
-                    mPtr, displayId, true /*isGestureMonitor*/, inputChannelName);
+                    mPtr, displayId, true /*isGestureMonitor*/, inputChannelName, pid);
             InputMonitorHost host = new InputMonitorHost(inputChannel.getToken());
             synchronized (mGestureMonitorPidsLock) {
                 mGestureMonitorPidsByToken.put(inputChannel.getToken(), pid);
@@ -1588,12 +1632,12 @@
     }
 
     @Override
-    public void requestPointerCapture(IBinder windowToken, boolean enabled) {
-        boolean requestConfigurationRefresh =
-                mWindowManagerCallbacks.requestPointerCapture(windowToken, enabled);
-        if (requestConfigurationRefresh) {
-            nativeSetPointerCapture(mPtr, enabled);
+    public void requestPointerCapture(IBinder inputChannelToken, boolean enabled) {
+        if (inputChannelToken == null) {
+            return;
         }
+
+        nativeRequestPointerCapture(mPtr, inputChannelToken, enabled);
     }
 
     public void setInputDispatchMode(boolean enabled, boolean frozen) {
@@ -1801,43 +1845,57 @@
         return result;
     }
 
-    // Binder call
-    @Override
-    public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
-        long[] pattern;
-        int[] amplitudes;
-        int repeat;
-        if (effect instanceof VibrationEffect.OneShot) {
-            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
-            pattern = new long[] { 0, oneShot.getDuration() };
-            int amplitude = oneShot.getAmplitude();
-            // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
-            // should use some built-in default value, denoted here as DEFAULT_VIBRATION_MAGNITUDE
-            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
-                amplitude = DEFAULT_VIBRATION_MAGNITUDE;
-            }
-            amplitudes = new int[] { 0, amplitude };
-            repeat = -1;
-        } else if (effect instanceof VibrationEffect.Waveform) {
-            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
-            pattern = waveform.getTimings();
-            amplitudes = waveform.getAmplitudes();
-            for (int i = 0; i < amplitudes.length; i++) {
-                if (amplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) {
-                    amplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE;
+    private static class VibrationInfo {
+        private long[] mPattern = new long[0];
+        private int[] mAmplitudes = new int[0];
+        private int mRepeat = -1;
+
+        public long[] getPattern() {
+            return mPattern;
+        }
+
+        public int[] getAmplitudes() {
+            return mAmplitudes;
+        }
+
+        public int getRepeatIndex() {
+            return mRepeat;
+        }
+
+        VibrationInfo(VibrationEffect effect) {
+            if (effect instanceof VibrationEffect.OneShot) {
+                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect;
+                mPattern = new long[] { 0, oneShot.getDuration() };
+                int amplitude = oneShot.getAmplitude();
+                // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
+                // should use some built-in default value, denoted here as
+                // DEFAULT_VIBRATION_MAGNITUDE
+                if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
+                    amplitude = DEFAULT_VIBRATION_MAGNITUDE;
                 }
+                mAmplitudes = new int[] { 0, amplitude };
+                mRepeat = -1;
+            } else if (effect instanceof VibrationEffect.Waveform) {
+                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
+                mPattern = waveform.getTimings();
+                mAmplitudes = waveform.getAmplitudes();
+                for (int i = 0; i < mAmplitudes.length; i++) {
+                    if (mAmplitudes[i] == VibrationEffect.DEFAULT_AMPLITUDE) {
+                        mAmplitudes[i] = DEFAULT_VIBRATION_MAGNITUDE;
+                    }
+                }
+                mRepeat = waveform.getRepeatIndex();
+                if (mRepeat >= mPattern.length) {
+                    throw new ArrayIndexOutOfBoundsException();
+                }
+            } else {
+                // TODO: Add support for prebaked effects
+                Slog.w(TAG, "Pre-baked effects aren't supported on input devices");
             }
-            repeat = waveform.getRepeatIndex();
-        } else {
-            // TODO: Add support for prebaked effects
-            Log.w(TAG, "Pre-baked effects aren't supported on input devices");
-            return;
         }
+    }
 
-        if (repeat >= pattern.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
+    private VibratorToken getVibratorToken(int deviceId, IBinder token) {
         VibratorToken v;
         synchronized (mVibratorLock) {
             v = mVibratorTokens.get(token);
@@ -1852,9 +1910,70 @@
                 mVibratorTokens.put(token, v);
             }
         }
+        return v;
+    }
+
+    // Binder call
+    @Override
+    public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
+        VibrationInfo info = new VibrationInfo(effect);
+        VibratorToken v = getVibratorToken(deviceId, token);
         synchronized (v) {
             v.mVibrating = true;
-            nativeVibrate(mPtr, deviceId, pattern, amplitudes, repeat, v.mTokenValue);
+            nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(),
+                    info.getRepeatIndex(), v.mTokenValue);
+        }
+    }
+
+    // Binder call
+    @Override
+    public int[] getVibratorIds(int deviceId) {
+        return nativeGetVibratorIds(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
+    public boolean isVibrating(int deviceId) {
+        return nativeIsVibrating(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
+    public void vibrateCombined(int deviceId, CombinedVibrationEffect effect, IBinder token) {
+        VibratorToken v = getVibratorToken(deviceId, token);
+        synchronized (v) {
+            if (!(effect instanceof CombinedVibrationEffect.Mono)
+                    && !(effect instanceof CombinedVibrationEffect.Stereo)) {
+                Slog.e(TAG, "Only Mono and Stereo effects are supported");
+                return;
+            }
+
+            v.mVibrating = true;
+            if (effect instanceof CombinedVibrationEffect.Mono) {
+                CombinedVibrationEffect.Mono mono = (CombinedVibrationEffect.Mono) effect;
+                VibrationInfo info = new VibrationInfo(mono.getEffect());
+                nativeVibrate(mPtr, deviceId, info.getPattern(), info.getAmplitudes(),
+                        info.getRepeatIndex(), v.mTokenValue);
+            } else if (effect instanceof CombinedVibrationEffect.Stereo) {
+                CombinedVibrationEffect.Stereo stereo = (CombinedVibrationEffect.Stereo) effect;
+                SparseArray<VibrationEffect> effects = stereo.getEffects();
+                long[] pattern = new long[0];
+                int repeat = Integer.MIN_VALUE;
+                SparseArray<int[]> amplitudes = new SparseArray<int[]>(effects.size());
+                for (int i = 0; i < effects.size(); i++) {
+                    VibrationInfo info = new VibrationInfo(effects.valueAt(i));
+                    // Pattern of all effects should be same
+                    if (pattern.length == 0) {
+                        pattern = info.getPattern();
+                    }
+                    if (repeat == Integer.MIN_VALUE) {
+                        repeat = info.getRepeatIndex();
+                    }
+                    amplitudes.put(effects.keyAt(i), info.getAmplitudes());
+                }
+                nativeVibrateCombined(mPtr, deviceId, pattern, amplitudes, repeat,
+                        v.mTokenValue);
+            }
         }
     }
 
@@ -1945,6 +2064,97 @@
         nativeNotifyPortAssociationsChanged(mPtr);
     }
 
+    @Override // Binder call
+    public InputSensorInfo[] getSensorList(int deviceId) {
+        InputSensorInfo[] sensors = nativeGetSensorList(mPtr, deviceId);
+        return sensors;
+    }
+
+    @Override // Binder call
+    public boolean registerSensorListener(IInputSensorEventListener listener) {
+        if (DEBUG) {
+            Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid="
+                    + Binder.getCallingPid());
+        }
+        if (listener == null) {
+            Slog.e(TAG, "listener must not be null");
+            return false;
+        }
+
+        synchronized (mInputDevicesLock) {
+            int callingPid = Binder.getCallingPid();
+            if (mSensorEventListeners.get(callingPid) != null) {
+                Slog.e(TAG, "The calling process " + callingPid + " has already "
+                        + "registered an InputSensorEventListener.");
+                return false;
+            }
+
+            SensorEventListenerRecord record =
+                    new SensorEventListenerRecord(callingPid, listener);
+            try {
+                IBinder binder = listener.asBinder();
+                binder.linkToDeath(record, 0);
+            } catch (RemoteException ex) {
+                // give up
+                throw new RuntimeException(ex);
+            }
+
+            mSensorEventListeners.put(callingPid, record);
+        }
+        return true;
+    }
+
+    @Override // Binder call
+    public void unregisterSensorListener(IInputSensorEventListener listener) {
+        if (DEBUG) {
+            Slog.d(TAG, "unregisterSensorListener: listener=" + listener + " callingPid="
+                    + Binder.getCallingPid());
+        }
+
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mInputDevicesLock) {
+            int callingPid = Binder.getCallingPid();
+            if (mSensorEventListeners.get(callingPid) != null) {
+                SensorEventListenerRecord record = mSensorEventListeners.get(callingPid);
+                if (record.getListener().asBinder() != listener.asBinder()) {
+                    throw new IllegalArgumentException("listener is not registered");
+                }
+                mSensorEventListeners.remove(callingPid);
+            }
+        }
+    }
+
+    @Override // Binder call
+    public boolean flushSensor(int deviceId, int sensorType) {
+        synchronized (mInputDevicesLock) {
+            int callingPid = Binder.getCallingPid();
+            SensorEventListenerRecord listener = mSensorEventListeners.get(callingPid);
+            if (listener != null) {
+                return nativeFlushSensor(mPtr, deviceId, sensorType);
+            }
+            return false;
+        }
+    }
+
+    @Override // Binder call
+    public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+            int maxBatchReportLatencyUs) {
+        synchronized (mInputDevicesLock) {
+            return nativeEnableSensor(mPtr, deviceId, sensorType, samplingPeriodUs,
+                    maxBatchReportLatencyUs);
+        }
+    }
+
+    @Override // Binder call
+    public void disableSensor(int deviceId, int sensorType) {
+        synchronized (mInputDevicesLock) {
+            nativeDisableSensor(mPtr, deviceId, sensorType);
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -2045,14 +2255,13 @@
 
         if ((switchMask & SW_LID_BIT) != 0) {
             final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
-
-            ArrayList<LidSwitchCallback> callbacksCopy;
             synchronized (mLidSwitchLock) {
-                callbacksCopy = new ArrayList<>(mLidSwitchCallbacks);
-            }
-            for (int i = 0; i < callbacksCopy.size(); i++) {
-                LidSwitchCallback callbacks = callbacksCopy.get(i);
-                callbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+                if (mSystemReady) {
+                    for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
+                        LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i);
+                        callbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+                    }
+                }
             }
         }
 
@@ -2092,11 +2301,7 @@
 
     // Native callback
     private void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
-        final boolean requestConfigurationRefresh =
-                mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
-        if (requestConfigurationRefresh) {
-            nativeSetPointerCapture(mPtr, false);
-        }
+        mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
     }
 
     // Native callback
@@ -2147,6 +2352,46 @@
     }
 
     // Native callback.
+    private void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
+            float[] values) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifySensorEvent: deviceId=" + deviceId + " sensorType="
+                    + sensorType + " values=" + Arrays.toString(values));
+        }
+        mSensorEventListenersToNotify.clear();
+        final int numListeners;
+        synchronized (mSensorEventLock) {
+            numListeners = mSensorEventListeners.size();
+            for (int i = 0; i < numListeners; i++) {
+                mSensorEventListenersToNotify.add(
+                        mSensorEventListeners.valueAt(i));
+            }
+        }
+        for (int i = 0; i < numListeners; i++) {
+            mSensorEventListenersToNotify.get(i).notifySensorEvent(deviceId, sensorType,
+                    accuracy, timestamp, values);
+        }
+        mSensorEventListenersToNotify.clear();
+    }
+
+    // Native callback.
+    private void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
+        mSensorAccuracyListenersToNotify.clear();
+        final int numListeners;
+        synchronized (mSensorEventLock) {
+            numListeners = mSensorEventListeners.size();
+            for (int i = 0; i < numListeners; i++) {
+                mSensorAccuracyListenersToNotify.add(mSensorEventListeners.valueAt(i));
+            }
+        }
+        for (int i = 0; i < numListeners; i++) {
+            mSensorAccuracyListenersToNotify.get(i).notifySensorAccuracy(
+                    deviceId, sensorType, accuracy);
+        }
+        mSensorAccuracyListenersToNotify.clear();
+    }
+
+    // Native callback.
     final boolean filterInputEvent(InputEvent event, int policyFlags) {
         synchronized (mInputFilterLock) {
             if (mInputFilter != null) {
@@ -2494,17 +2739,8 @@
 
         /**
          * Called when the focused window has changed.
-         *
-         * @return true if we want to request a configuration refresh.
          */
-        boolean notifyFocusChanged(IBinder oldToken, IBinder newToken);
-
-        /**
-         * Called by the client to request pointer capture.
-         *
-         * @return true if we want to request a configuration refresh.
-         */
-        boolean requestPointerCapture(IBinder windowToken, boolean enabled);
+        void notifyFocusChanged(IBinder oldToken, IBinder newToken);
     }
 
     /**
@@ -2687,6 +2923,56 @@
         }
     }
 
+    private void onSensorEventListenerDied(int pid) {
+        synchronized (mSensorEventLock) {
+            mSensorEventListeners.remove(pid);
+        }
+    }
+
+    private final class SensorEventListenerRecord implements DeathRecipient {
+        private final int mPid;
+        private final IInputSensorEventListener mListener;
+
+        SensorEventListenerRecord(int pid, IInputSensorEventListener listener) {
+            mPid = pid;
+            mListener = listener;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DEBUG) {
+                Slog.d(TAG, "Sensor event listener for pid " + mPid + " died.");
+            }
+            onSensorEventListenerDied(mPid);
+        }
+
+        public IInputSensorEventListener getListener() {
+            return mListener;
+        }
+
+        public void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
+                float[] values) {
+            try {
+                mListener.onInputSensorChanged(deviceId, sensorType, accuracy, timestamp,
+                        values);
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify process " + mPid
+                        + " that sensor event notified, assuming it died.", ex);
+                binderDied();
+            }
+        }
+
+        public void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
+            try {
+                mListener.onInputSensorAccuracyChanged(deviceId, sensorType, accuracy);
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify process " + mPid
+                        + " that sensor accuracy notified, assuming it died.", ex);
+                binderDied();
+            }
+        }
+    }
+
     private final class VibratorToken implements DeathRecipient {
         public final int mDeviceId;
         public final IBinder mToken;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6395094..90edd77 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -159,6 +159,7 @@
 import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.CallbackUtils;
+import com.android.internal.inputmethod.IBooleanResultCallback;
 import com.android.internal.inputmethod.IInputBindResultResultCallback;
 import com.android.internal.inputmethod.IInputContentUriToken;
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
@@ -3150,41 +3151,44 @@
     }
 
     @Override
-    public boolean showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
-            ResultReceiver resultReceiver) {
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
-        int uid = Binder.getCallingUid();
-        ImeTracing.getInstance().triggerManagerServiceDump(
-                "InputMethodManagerService#showSoftInput");
-        synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked()) {
-                return false;
-            }
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                if (mCurClient == null || client == null
-                        || mCurClient.client.asBinder() != client.asBinder()) {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    final ClientState cs = mClients.get(client.asBinder());
-                    if (cs == null) {
-                        throw new IllegalArgumentException("unknown client " + client.asBinder());
-                    }
-                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                            cs.selfReportedDisplayId)) {
-                        Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
-                        return false;
-                    }
+    public void showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
+            ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
+            int uid = Binder.getCallingUid();
+            ImeTracing.getInstance().triggerManagerServiceDump(
+                    "InputMethodManagerService#showSoftInput");
+            synchronized (mMethodMap) {
+                if (!calledFromValidUserLocked()) {
+                    return false;
                 }
-                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
-                return showCurrentInputLocked(windowToken, flags, resultReceiver,
-                        SoftInputShowHideReason.SHOW_SOFT_INPUT);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    if (mCurClient == null || client == null
+                            || mCurClient.client.asBinder() != client.asBinder()) {
+                        // We need to check if this is the current client with
+                        // focus in the window manager, to allow this call to
+                        // be made before input is started in it.
+                        final ClientState cs = mClients.get(client.asBinder());
+                        if (cs == null) {
+                            throw new IllegalArgumentException(
+                                    "unknown client " + client.asBinder());
+                        }
+                        if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+                                cs.selfReportedDisplayId)) {
+                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
+                            return false;
+                        }
+                    }
+                    if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
+                    return showCurrentInputLocked(windowToken, flags, resultReceiver,
+                                    SoftInputShowHideReason.SHOW_SOFT_INPUT);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                }
             }
-        }
+        });
     }
 
     @BinderThread
@@ -3266,44 +3270,49 @@
     }
 
     @Override
-    public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
-            ResultReceiver resultReceiver) {
-        int uid = Binder.getCallingUid();
-        ImeTracing.getInstance().triggerManagerServiceDump(
-                "InputMethodManagerService#hideSoftInput");
-        synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked()) {
-                return false;
-            }
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
-                if (mCurClient == null || client == null
-                        || mCurClient.client.asBinder() != client.asBinder()) {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    final ClientState cs = mClients.get(client.asBinder());
-                    if (cs == null) {
-                        throw new IllegalArgumentException("unknown client " + client.asBinder());
-                    }
-                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                            cs.selfReportedDisplayId)) {
-                        if (DEBUG) {
-                            Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
-                        }
-                        return false;
-                    }
+    public void hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
+            ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> {
+            int uid = Binder.getCallingUid();
+            ImeTracing.getInstance().triggerManagerServiceDump(
+                    "InputMethodManagerService#hideSoftInput");
+            synchronized (mMethodMap) {
+                if (!InputMethodManagerService.this.calledFromValidUserLocked()) {
+                    return false;
                 }
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
+                    if (mCurClient == null || client == null
+                            || mCurClient.client.asBinder() != client.asBinder()) {
+                        // We need to check if this is the current client with
+                        // focus in the window manager, to allow this call to
+                        // be made before input is started in it.
+                        final ClientState cs = mClients.get(client.asBinder());
+                        if (cs == null) {
+                            throw new IllegalArgumentException(
+                                    "unknown client " + client.asBinder());
+                        }
+                        if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+                                cs.selfReportedDisplayId)) {
+                            if (DEBUG) {
+                                Slog.w(TAG,
+                                        "Ignoring hideSoftInput of uid " + uid + ": " + client);
+                            }
+                            return false;
+                        }
+                    }
 
-                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
-                return hideCurrentInputLocked(windowToken, flags, resultReceiver,
-                        SoftInputShowHideReason.HIDE_SOFT_INPUT);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                    if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
+                    return InputMethodManagerService.this.hideCurrentInputLocked(windowToken,
+                            flags, resultReceiver,
+                            SoftInputShowHideReason.HIDE_SOFT_INPUT);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                }
             }
-        }
+        });
     }
 
     boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@@ -3726,9 +3735,15 @@
                 MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId));
     }
 
-    public boolean isInputMethodPickerShownForTest() {
+    /**
+     * A test API for CTS to make sure that the input method menu is showing.
+     *
+     * @param resultCallback {@code true} while the input method menu is showing UI.
+     */
+    public void isInputMethodPickerShownForTest(IBooleanResultCallback resultCallback) {
         synchronized(mMethodMap) {
-            return mMenuController.isisInputMethodPickerShownForTestLocked();
+            CallbackUtils.onResult(
+                    resultCallback, mMenuController::isisInputMethodPickerShownForTestLocked);
         }
     }
 
@@ -4120,8 +4135,8 @@
 
     @BinderThread
     @Override
-    public boolean isImeTraceEnabled() {
-        return ImeTracing.getInstance().isEnabled();
+    public void isImeTraceEnabled(IBooleanResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> ImeTracing.getInstance().isEnabled());
     }
 
     @BinderThread
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 6bdae63..ccb78a4 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -73,6 +73,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.inputmethod.CallbackUtils;
+import com.android.internal.inputmethod.IBooleanResultCallback;
 import com.android.internal.inputmethod.IInputBindResultResultCallback;
 import com.android.internal.inputmethod.IMultiClientInputMethod;
 import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
@@ -1501,7 +1502,15 @@
 
         @BinderThread
         @Override
-        public boolean showSoftInput(
+        public void showSoftInput(
+                IInputMethodClient client, IBinder token, int flags,
+                ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback,
+                    () -> showSoftInputInternal(client, token, flags, resultReceiver));
+        }
+
+        @BinderThread
+        private boolean showSoftInputInternal(
                 IInputMethodClient client, IBinder token, int flags,
                 ResultReceiver resultReceiver) {
             final int callingUid = Binder.getCallingUid();
@@ -1548,7 +1557,16 @@
 
         @BinderThread
         @Override
-        public boolean hideSoftInput(
+        public void hideSoftInput(
+                IInputMethodClient client, IBinder windowToken, int flags,
+                ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback,
+                    () -> hideSoftInputInternal(client, windowToken, flags, resultReceiver));
+
+        }
+
+        @BinderThread
+        private boolean hideSoftInputInternal(
                 IInputMethodClient client, IBinder windowToken, int flags,
                 ResultReceiver resultReceiver) {
             final int callingUid = Binder.getCallingUid();
@@ -1768,9 +1786,9 @@
 
         @BinderThread
         @Override
-        public boolean isInputMethodPickerShownForTest() {
+        public void isInputMethodPickerShownForTest(IBooleanResultCallback resultCallback) {
             reportNotSupported();
-            return false;
+            CallbackUtils.onResult(resultCallback, () -> false);
         }
 
         @BinderThread
@@ -1834,8 +1852,8 @@
 
         @BinderThread
         @Override
-        public boolean isImeTraceEnabled() {
-            return false;
+        public void isImeTraceEnabled(IBooleanResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback, () -> false);
         }
 
         @BinderThread
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index d624019..43c965d 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -29,14 +29,12 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
 import android.provider.Settings;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.SurfaceControl;
 
 import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.GuardedBy;
@@ -262,25 +260,9 @@
     }
 
     private final class LightImpl extends LogicalLight {
-        private final IBinder mDisplayToken;
-        private final int mSurfaceControlMaximumBrightness;
 
         private LightImpl(Context context, HwLight hwLight) {
             mHwLight = hwLight;
-            mDisplayToken = SurfaceControl.getInternalDisplayToken();
-            final boolean brightnessSupport = SurfaceControl.getDisplayBrightnessSupport(
-                    mDisplayToken);
-            if (DEBUG) {
-                Slog.d(TAG, "Display brightness support: " + brightnessSupport);
-            }
-            int maximumBrightness = 0;
-            if (brightnessSupport) {
-                PowerManager pm = context.getSystemService(PowerManager.class);
-                if (pm != null) {
-                    maximumBrightness = pm.getMaximumScreenBrightnessSetting();
-                }
-            }
-            mSurfaceControlMaximumBrightness = maximumBrightness;
         }
 
         @Override
@@ -301,28 +283,10 @@
                             + ": brightness=" + brightness);
                     return;
                 }
-                // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
-                // right now we just fall back to the old path through Lights brightessMode is
-                // anything but USER or the device shouldBeInLowPersistenceMode().
-                if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
-                        && mSurfaceControlMaximumBrightness == 255) {
-                    // New system
-                    // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
-                    // reason we enforce 255 right now is to stay consistent with the old path. In
-                    // the future, the framework should be refactored so that brightness is a float
-                    // between 0.0f and 1.0f, and the actual number of supported brightness levels
-                    // is determined in the device-specific implementation.
-                    if (DEBUG) {
-                        Slog.d(TAG, "Using new setBrightness path!");
-                    }
-                    SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
-                } else {
-                    // Old system
-                    int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
-                    int color = brightnessInt & 0x000000ff;
-                    color = 0xff000000 | (color << 16) | (color << 8) | color;
-                    setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
-                }
+                int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
+                int color = brightnessInt & 0x000000ff;
+                color = 0xff000000 | (color << 16) | (color << 8) | color;
+                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
             }
         }
 
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 3854f8c..9068287 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -47,7 +47,7 @@
 import android.location.Geofence;
 import android.location.GnssCapabilities;
 import android.location.GnssMeasurementCorrections;
-import android.location.GnssRequest;
+import android.location.GnssMeasurementRequest;
 import android.location.IGeocodeListener;
 import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
@@ -519,9 +519,6 @@
     public List<String> getAllProviders() {
         ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
         for (LocationProviderManager manager : mProviderManagers) {
-            if (FUSED_PROVIDER.equals(manager.getName())) {
-                continue;
-            }
             providers.add(manager.getName());
         }
         return providers;
@@ -538,9 +535,6 @@
             ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
             for (LocationProviderManager manager : mProviderManagers) {
                 String name = manager.getName();
-                if (FUSED_PROVIDER.equals(name)) {
-                    continue;
-                }
                 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
                     continue;
                 }
@@ -565,7 +559,9 @@
         }
 
         if (!providers.isEmpty()) {
-            if (providers.contains(GPS_PROVIDER)) {
+            if (providers.contains(FUSED_PROVIDER)) {
+                return FUSED_PROVIDER;
+            } else if (providers.contains(GPS_PROVIDER)) {
                 return GPS_PROVIDER;
             } else if (providers.contains(NETWORK_PROVIDER)) {
                 return NETWORK_PROVIDER;
@@ -863,7 +859,7 @@
     }
 
     @Override
-    public void addGnssMeasurementsListener(@Nullable GnssRequest request,
+    public void addGnssMeasurementsListener(@Nullable GnssMeasurementRequest request,
             IGnssMeasurementsListener listener, String packageName, String attributionTag) {
         if (mGnssManagerService != null) {
             mGnssManagerService.addGnssMeasurementsListener(request, listener, packageName,
@@ -1046,10 +1042,6 @@
 
     @Override
     public boolean isProviderEnabledForUser(String provider, int userId) {
-        // fused provider is accessed indirectly via criteria rather than the provider-based APIs,
-        // so we discourage its use
-        if (FUSED_PROVIDER.equals(provider)) return false;
-
         return mLocalService.isProviderEnabledForUser(provider, userId);
     }
 
diff --git a/services/core/java/com/android/server/location/OWNERS b/services/core/java/com/android/server/location/OWNERS
index c2c95e6..696a0c2 100644
--- a/services/core/java/com/android/server/location/OWNERS
+++ b/services/core/java/com/android/server/location/OWNERS
@@ -1,8 +1 @@
-aadmal@google.com
-arthuri@google.com
-bduddie@google.com
-gomo@google.com
-sooniln@google.com
-weiwa@google.com
-wyattriley@google.com
-yuhany@google.com
+file:/location/java/android/location/OWNERS
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index 20458b4..cc510fb 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -39,6 +39,10 @@
 
 import com.android.server.location.ClientBrokerProto;
 
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
 
@@ -119,6 +123,13 @@
     private final boolean mHasAccessContextHubPermission;
 
     /*
+     * The set of nanoapp IDs that represent the group of nanoapps this client has a messaging
+     * channel with, i.e. has sent or received messages from this particular nanoapp.
+     */
+    private final Set<Long> mMessageChannelNanoappIdSet =
+            Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>());
+
+    /*
      * Helper class to manage registered PendingIntent requests from the client.
      */
     private class PendingIntentRequest {
@@ -134,7 +145,8 @@
 
         private boolean mValid = false;
 
-        PendingIntentRequest() {}
+        PendingIntentRequest() {
+        }
 
         PendingIntentRequest(PendingIntent pendingIntent, long nanoAppId) {
             mPendingIntent = pendingIntent;
@@ -177,7 +189,7 @@
         mPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
 
         mHasAccessContextHubPermission = context.checkCallingPermission(
-            Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
+                Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
     }
 
     /* package */ ContextHubClientBroker(
@@ -193,7 +205,7 @@
         mPackage = pendingIntent.getCreatorPackage();
 
         mHasAccessContextHubPermission = context.checkCallingPermission(
-            Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
+                Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
     }
 
     /**
@@ -209,6 +221,7 @@
 
         int result;
         if (isRegistered()) {
+            mMessageChannelNanoappIdSet.add(message.getNanoAppId());
             ContextHubMsg messageToNanoApp =
                     ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);
 
@@ -269,6 +282,7 @@
      * @param message the message that came from a nanoapp
      */
     /* package */ void sendMessageToClient(NanoAppMessage message) {
+        mMessageChannelNanoappIdSet.add(message.getNanoAppId());
         invokeCallback(callback -> callback.onMessageFromNanoApp(message));
 
         Supplier<Intent> supplier =
@@ -413,7 +427,7 @@
     /**
      * Sends an intent to any existing PendingIntent
      *
-     * @param supplier method to create the extra Intent
+     * @param supplier  method to create the extra Intent
      * @param nanoAppId the ID of the nanoapp which this event is for
      */
     private synchronized void sendPendingIntent(Supplier<Intent> supplier, long nanoAppId) {
@@ -427,7 +441,7 @@
      * Sends a PendingIntent with extra Intent data
      *
      * @param pendingIntent the PendingIntent
-     * @param intent the extra Intent data
+     * @param intent        the extra Intent data
      */
     private void doSendPendingIntent(PendingIntent pendingIntent, Intent intent) {
         try {
@@ -500,6 +514,17 @@
         } else {
             out += "package: " + mPackage;
         }
+        if (mMessageChannelNanoappIdSet.size() > 0) {
+            out += " messageChannelNanoappSet: (";
+            Iterator<Long> it = mMessageChannelNanoappIdSet.iterator();
+            while (it.hasNext()) {
+                out += "0x" + Long.toHexString(it.next());
+                if (it.hasNext()) {
+                    out += ",";
+                }
+            }
+            out += ")";
+        }
         out += "]";
 
         return out;
diff --git a/services/core/java/com/android/server/location/contexthub/OWNERS b/services/core/java/com/android/server/location/contexthub/OWNERS
new file mode 100644
index 0000000..d4393d6
--- /dev/null
+++ b/services/core/java/com/android/server/location/contexthub/OWNERS
@@ -0,0 +1,2 @@
+arthuri@google.com
+bduddie@google.com
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 326265f..fa137aa 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -21,9 +21,9 @@
 import android.content.Context;
 import android.location.GnssAntennaInfo;
 import android.location.GnssMeasurementCorrections;
+import android.location.GnssMeasurementRequest;
 import android.location.GnssMeasurementsEvent;
 import android.location.GnssNavigationMessage;
-import android.location.GnssRequest;
 import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
 import android.location.IGnssNavigationMessageListener;
@@ -176,12 +176,10 @@
     /**
      * Adds a GNSS measurements listener.
      */
-    public void addGnssMeasurementsListener(GnssRequest request, IGnssMeasurementsListener listener,
-            String packageName, @Nullable String attributionTag) {
+    public void addGnssMeasurementsListener(GnssMeasurementRequest request,
+            IGnssMeasurementsListener listener, String packageName,
+            @Nullable String attributionTag) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-        if (request.isFullTracking()) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
-        }
 
         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
         mGnssMeasurementsProvider.addListener(request, identity, listener);
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 59a533c..fa8e2a6 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -21,8 +21,8 @@
 
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.location.GnssMeasurementRequest;
 import android.location.GnssMeasurementsEvent;
-import android.location.GnssRequest;
 import android.location.IGnssMeasurementsListener;
 import android.location.util.identity.CallerIdentity;
 import android.os.IBinder;
@@ -47,18 +47,18 @@
  * @hide
  */
 public final class GnssMeasurementsProvider extends
-        GnssListenerMultiplexer<GnssRequest, IGnssMeasurementsListener, Boolean> implements
-        SettingsHelper.GlobalSettingChangedListener {
+        GnssListenerMultiplexer<GnssMeasurementRequest, IGnssMeasurementsListener, Boolean>
+        implements SettingsHelper.GlobalSettingChangedListener {
 
     private class GnssMeasurementListenerRegistration extends GnssListenerRegistration {
 
         private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement";
 
         protected GnssMeasurementListenerRegistration(
-                @Nullable GnssRequest gnssRequest,
+                @Nullable GnssMeasurementRequest request,
                 CallerIdentity callerIdentity,
                 IGnssMeasurementsListener iGnssMeasurementsListener) {
-            super(gnssRequest, callerIdentity, iGnssMeasurementsListener);
+            super(request, callerIdentity, iGnssMeasurementsListener);
         }
 
         @Nullable
@@ -100,13 +100,13 @@
     }
 
     @Override
-    public void addListener(GnssRequest request, CallerIdentity identity,
+    public void addListener(GnssMeasurementRequest request, CallerIdentity identity,
             IGnssMeasurementsListener listener) {
         super.addListener(request, identity, listener);
     }
 
     @Override
-    protected GnssListenerRegistration createRegistration(GnssRequest request,
+    protected GnssListenerRegistration createRegistration(GnssMeasurementRequest request,
             CallerIdentity callerIdentity, IGnssMeasurementsListener listener) {
         return new GnssMeasurementListenerRegistration(request, callerIdentity, listener);
     }
diff --git a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
index 70ab3c6..b924d1f 100644
--- a/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
+++ b/services/core/java/com/android/server/location/gnss/GnssPowerStats.java
@@ -16,8 +16,8 @@
 
 package com.android.server.location.gnss;
 
-import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIMESTAMP_NS;
-import static android.hardware.gnss.IGnss.ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS;
+import static android.hardware.gnss.ElapsedRealtime.HAS_TIMESTAMP_NS;
+import static android.hardware.gnss.ElapsedRealtime.HAS_TIME_UNCERTAINTY_NS;
 
 import com.android.internal.util.Preconditions;
 
@@ -57,12 +57,12 @@
 
     /** Returns true if {@link #getElapsedRealtimeNanos()} is available. */
     public boolean hasElapsedRealtimeNanos() {
-        return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIMESTAMP_NS) != 0;
+        return (mElapsedRealtimeFlags & HAS_TIMESTAMP_NS) != 0;
     }
 
     /** Returns true if {@link #getElapsedRealtimeUncertaintyNanos()} is available. */
     public boolean hasElapsedRealtimeUncertaintyNanos() {
-        return (mElapsedRealtimeFlags & ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS) != 0;
+        return (mElapsedRealtimeFlags & HAS_TIME_UNCERTAINTY_NS) != 0;
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
index fd8cf70..b9c23b7 100644
--- a/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
@@ -17,20 +17,17 @@
 package com.android.server.location.timezone;
 
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
-
 import java.time.Duration;
 import java.util.Objects;
 
@@ -57,9 +54,9 @@
     void onInitialize() {
         mProxy.initialize(new LocationTimeZoneProviderProxy.Listener() {
             @Override
-            public void onReportLocationTimeZoneEvent(
-                    @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
-                handleLocationTimeZoneEvent(locationTimeZoneEvent);
+            public void onReportTimeZoneProviderEvent(
+                    @NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
+                handleTimeZoneProviderEvent(timeZoneProviderEvent);
             }
 
             @Override
@@ -80,27 +77,27 @@
         synchronized (mSharedLock) {
             ProviderState currentState = mCurrentState.get();
             switch (currentState.stateEnum) {
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN:
-                case PROVIDER_STATE_ENABLED_CERTAIN: {
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_UNCERTAIN:
+                case PROVIDER_STATE_STARTED_CERTAIN: {
                     // Losing a remote provider is treated as becoming uncertain.
                     String msg = "handleProviderLost reason=" + reason
                             + ", mProviderName=" + mProviderName
                             + ", currentState=" + currentState;
                     debugLog(msg);
-                    // This is an unusual PROVIDER_STATE_ENABLED_UNCERTAIN state because
+                    // This is an unusual PROVIDER_STATE_STARTED_UNCERTAIN state because
                     // event == null
                     ProviderState newState = currentState.newState(
-                            PROVIDER_STATE_ENABLED_UNCERTAIN, null,
+                            PROVIDER_STATE_STARTED_UNCERTAIN, null,
                             currentState.currentUserConfiguration, msg);
                     setCurrentState(newState, true);
                     break;
                 }
-                case PROVIDER_STATE_DISABLED: {
+                case PROVIDER_STATE_STOPPED: {
                     debugLog("handleProviderLost reason=" + reason
                             + ", mProviderName=" + mProviderName
                             + ", currentState=" + currentState
-                            + ": No state change required, provider is disabled.");
+                            + ": No state change required, provider is stopped.");
                     break;
                 }
                 case PROVIDER_STATE_PERM_FAILED: {
@@ -123,16 +120,16 @@
         synchronized (mSharedLock) {
             ProviderState currentState = mCurrentState.get();
             switch (currentState.stateEnum) {
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
                     debugLog("handleOnProviderBound mProviderName=" + mProviderName
-                            + ", currentState=" + currentState + ": Provider is enabled.");
+                            + ", currentState=" + currentState + ": Provider is started.");
                     break;
                 }
-                case PROVIDER_STATE_DISABLED: {
+                case PROVIDER_STATE_STOPPED: {
                     debugLog("handleOnProviderBound mProviderName=" + mProviderName
-                            + ", currentState=" + currentState + ": Provider is disabled.");
+                            + ", currentState=" + currentState + ": Provider is stopped.");
                     break;
                 }
                 case PROVIDER_STATE_PERM_FAILED: {
@@ -150,23 +147,17 @@
     }
 
     @Override
-    void onEnable(@NonNull Duration initializationTimeout) {
+    void onStartUpdates(@NonNull Duration initializationTimeout) {
         // Set a request on the proxy - it will be sent immediately if the service is bound,
         // or will be sent as soon as the service becomes bound.
-        LocationTimeZoneProviderRequest request =
-                new LocationTimeZoneProviderRequest.Builder()
-                        .setReportLocationTimeZone(true)
-                        .setInitializationTimeoutMillis(initializationTimeout.toMillis())
-                        .build();
+        TimeZoneProviderRequest request =
+                TimeZoneProviderRequest.createStartUpdatesRequest(initializationTimeout);
         mProxy.setRequest(request);
     }
 
     @Override
-    void onDisable() {
-        LocationTimeZoneProviderRequest request =
-                new LocationTimeZoneProviderRequest.Builder()
-                        .setReportLocationTimeZone(false)
-                        .build();
+    void onStopUpdates() {
+        TimeZoneProviderRequest request = TimeZoneProviderRequest.createStopUpdatesRequest();
         mProxy.setRequest(request);
     }
 
diff --git a/services/core/java/com/android/server/location/timezone/ControllerImpl.java b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
index 07615ff5..7496168 100644
--- a/services/core/java/com/android/server/location/timezone/ControllerImpl.java
+++ b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
@@ -16,24 +16,24 @@
 
 package com.android.server.location.timezone;
 
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.warnLog;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
 
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
 import com.android.server.location.timezone.ThreadingDomain.SingleRunnableQueue;
 import com.android.server.timezonedetector.ConfigurationInternal;
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
@@ -46,9 +46,9 @@
  * A real implementation of {@link LocationTimeZoneProviderController} that supports a primary and a
  * secondary {@link LocationTimeZoneProvider}.
  *
- * <p>The primary is used until it fails or becomes uncertain. The secondary will then be enabled.
+ * <p>The primary is used until it fails or becomes uncertain. The secondary will then be started.
  * The controller will immediately make suggestions based on "certain" {@link
- * LocationTimeZoneEvent}s, i.e. events that demonstrate the provider is certain what the time zone
+ * TimeZoneProviderEvent}s, i.e. events that demonstrate the provider is certain what the time zone
  * is. The controller will not make immediate suggestions based on "uncertain" events, giving
  * providers time to change their mind. This also gives the secondary provider time to initialize
  * when the primary becomes uncertain.
@@ -107,7 +107,7 @@
             mPrimaryProvider.initialize(providerListener);
             mSecondaryProvider.initialize(providerListener);
 
-            alterProvidersEnabledStateIfRequired(
+            alterProvidersStartedStateIfRequired(
                     null /* oldConfiguration */, mCurrentUserConfiguration);
         }
     }
@@ -125,15 +125,15 @@
 
             if (!newConfig.equals(oldConfig)) {
                 if (newConfig.getUserId() != oldConfig.getUserId()) {
-                    // If the user changed, disable the providers if needed. They may be re-enabled
+                    // If the user changed, stop the providers if needed. They may be re-started
                     // for the new user immediately afterwards if their settings allow.
                     debugLog("User changed. old=" + oldConfig.getUserId()
-                            + ", new=" + newConfig.getUserId() + ": Disabling providers");
-                    disableProviders();
+                            + ", new=" + newConfig.getUserId() + ": Stopping providers");
+                    stopProviders();
 
-                    alterProvidersEnabledStateIfRequired(null /* oldConfiguration */, newConfig);
+                    alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
                 } else {
-                    alterProvidersEnabledStateIfRequired(oldConfig, newConfig);
+                    alterProvidersStartedStateIfRequired(oldConfig, newConfig);
                 }
             }
         }
@@ -145,43 +145,44 @@
     }
 
     @Override
+    @DurationMillisLong
     long getUncertaintyTimeoutDelayMillis() {
         return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
     }
 
     @GuardedBy("mSharedLock")
-    private void disableProviders() {
-        disableProviderIfEnabled(mPrimaryProvider);
-        disableProviderIfEnabled(mSecondaryProvider);
+    private void stopProviders() {
+        stopProviderIfStarted(mPrimaryProvider);
+        stopProviderIfStarted(mSecondaryProvider);
 
-        // By definition, if both providers are disabled, the controller is uncertain.
+        // By definition, if both providers are stopped, the controller is uncertain.
         cancelUncertaintyTimeout();
     }
 
     @GuardedBy("mSharedLock")
-    private void disableProviderIfEnabled(@NonNull LocationTimeZoneProvider provider) {
-        if (provider.getCurrentState().isEnabled()) {
-            disableProvider(provider);
+    private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
+        if (provider.getCurrentState().isStarted()) {
+            stopProvider(provider);
         }
     }
 
     @GuardedBy("mSharedLock")
-    private void disableProvider(@NonNull LocationTimeZoneProvider provider) {
+    private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
         ProviderState providerState = provider.getCurrentState();
         switch (providerState.stateEnum) {
-            case PROVIDER_STATE_DISABLED: {
-                debugLog("No need to disable " + provider + ": already disabled");
+            case PROVIDER_STATE_STOPPED: {
+                debugLog("No need to stop " + provider + ": already stopped");
                 break;
             }
-            case PROVIDER_STATE_ENABLED_INITIALIZING:
-            case PROVIDER_STATE_ENABLED_CERTAIN:
-            case PROVIDER_STATE_ENABLED_UNCERTAIN: {
-                debugLog("Disabling " + provider);
-                provider.disable();
+            case PROVIDER_STATE_STARTED_INITIALIZING:
+            case PROVIDER_STATE_STARTED_CERTAIN:
+            case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                debugLog("Stopping " + provider);
+                provider.stopUpdates();
                 break;
             }
             case PROVIDER_STATE_PERM_FAILED: {
-                debugLog("Unable to disable " + provider + ": it is perm failed");
+                debugLog("Unable to stop " + provider + ": it is perm failed");
                 break;
             }
             default: {
@@ -192,20 +193,20 @@
     }
 
     /**
-     * Sets the providers into the correct enabled/disabled state for the {@code newConfiguration}
+     * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
      * and, if there is a provider state change, makes any suggestions required to inform the
      * downstream time zone detection code.
      *
      * <p>This is a utility method that exists to avoid duplicated logic for the various cases when
-     * provider enabled / disabled state may need to be set or changed, e.g. during initialization
+     * provider started / stopped state may need to be set or changed, e.g. during initialization
      * or when a new configuration has been received.
      */
     @GuardedBy("mSharedLock")
-    private void alterProvidersEnabledStateIfRequired(
+    private void alterProvidersStartedStateIfRequired(
             @Nullable ConfigurationInternal oldConfiguration,
             @NonNull ConfigurationInternal newConfiguration) {
 
-        // Provider enabled / disabled states only need to be changed if geoDetectionEnabled has
+        // Provider started / stopped states only need to be changed if geoDetectionEnabled has
         // changed.
         boolean oldGeoDetectionEnabled = oldConfiguration != null
                 && oldConfiguration.getGeoDetectionEnabledBehavior();
@@ -215,28 +216,28 @@
         }
 
         // The check above ensures that the logic below only executes if providers are going from
-        // {enabled *} -> {disabled}, or {disabled} -> {enabled initializing}. If this changes in
-        // future and there could be {enabled *} -> {enabled *} cases, or cases where the provider
-        // can't be assumed to go straight to the {enabled initializing} state, then the logic below
+        // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
+        // future and there could be {started *} -> {started *} cases, or cases where the provider
+        // can't be assumed to go straight to the {started initializing} state, then the logic below
         // would need to cover extra conditions, for example:
-        // 1) If the primary is in {enabled uncertain}, the secondary should be enabled.
+        // 1) If the primary is in {started uncertain}, the secondary should be started.
         // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
-        //    timeout started when the primary entered {enabled uncertain} should be cancelled.
+        //    timeout started when the primary entered {started uncertain} should be cancelled.
 
         if (newGeoDetectionEnabled) {
-            // Try to enable the primary provider.
-            tryEnableProvider(mPrimaryProvider, newConfiguration);
+            // Try to start the primary provider.
+            tryStartProvider(mPrimaryProvider, newConfiguration);
 
-            // The secondary should only ever be enabled if the primary now isn't enabled (i.e. it
-            // couldn't become {enabled initializing} because it is {perm failed}).
+            // The secondary should only ever be started if the primary now isn't started (i.e. it
+            // couldn't become {started initializing} because it is {perm failed}).
             ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
-            if (!newPrimaryState.isEnabled()) {
-                // If the primary provider is {perm failed} then the controller must try to enable
+            if (!newPrimaryState.isStarted()) {
+                // If the primary provider is {perm failed} then the controller must try to start
                 // the secondary.
-                tryEnableProvider(mSecondaryProvider, newConfiguration);
+                tryStartProvider(mSecondaryProvider, newConfiguration);
 
                 ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
-                if (!newSecondaryState.isEnabled()) {
+                if (!newSecondaryState.isStarted()) {
                     // If both providers are {perm failed} then the controller immediately
                     // becomes uncertain.
                     GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
@@ -247,7 +248,7 @@
                 }
             }
         } else {
-            disableProviders();
+            stopProviders();
 
             // There can be an uncertainty timeout set if the controller most recently received
             // an uncertain event. This is a no-op if there isn't a timeout set.
@@ -256,34 +257,35 @@
             // If a previous "certain" suggestion has been made, then a new "uncertain"
             // suggestion must now be made to indicate the controller {does not / no longer has}
             // an opinion and will not be sending further updates (until at least the config
-            // changes again and providers are re-enabled).
+            // changes again and providers are re-started).
             if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
                 GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
-                        "Provider is disabled:"
+                        "Provider is stopped:"
                                 + " primary=" + mPrimaryProvider.getCurrentState());
                 makeSuggestion(suggestion);
             }
         }
     }
 
-    private void tryEnableProvider(@NonNull LocationTimeZoneProvider provider,
+    private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
             @NonNull ConfigurationInternal configuration) {
         ProviderState providerState = provider.getCurrentState();
         switch (providerState.stateEnum) {
-            case PROVIDER_STATE_DISABLED: {
+            case PROVIDER_STATE_STOPPED: {
                 debugLog("Enabling " + provider);
-                provider.enable(configuration, mEnvironment.getProviderInitializationTimeout(),
+                provider.startUpdates(configuration,
+                        mEnvironment.getProviderInitializationTimeout(),
                         mEnvironment.getProviderInitializationTimeoutFuzz());
                 break;
             }
-            case PROVIDER_STATE_ENABLED_INITIALIZING:
-            case PROVIDER_STATE_ENABLED_CERTAIN:
-            case PROVIDER_STATE_ENABLED_UNCERTAIN: {
-                debugLog("No need to enable " + provider + ": already enabled");
+            case PROVIDER_STATE_STARTED_INITIALIZING:
+            case PROVIDER_STATE_STARTED_CERTAIN:
+            case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                debugLog("No need to start " + provider + ": already started");
                 break;
             }
             case PROVIDER_STATE_PERM_FAILED: {
-                debugLog("Unable to enable " + provider + ": it is perm failed");
+                debugLog("Unable to start " + provider + ": it is perm failed");
                 break;
             }
             default: {
@@ -300,20 +302,20 @@
 
         synchronized (mSharedLock) {
             switch (providerState.stateEnum) {
-                case PROVIDER_STATE_DISABLED: {
-                    // This should never happen: entering disabled does not trigger a state change.
-                    warnLog("onProviderStateChange: Unexpected state change for disabled provider,"
+                case PROVIDER_STATE_STOPPED: {
+                    // This should never happen: entering stopped does not trigger a state change.
+                    warnLog("onProviderStateChange: Unexpected state change for stopped provider,"
                             + " provider=" + provider);
                     break;
                 }
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN: {
-                    // Entering enabled does not trigger a state change, so this only happens if an
-                    // event is received while the provider is enabled.
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                    // Entering started does not trigger a state change, so this only happens if an
+                    // event is received while the provider is started.
                     debugLog("onProviderStateChange: Received notification of a state change while"
-                            + " enabled, provider=" + provider);
-                    handleProviderEnabledStateChange(providerState);
+                            + " started, provider=" + provider);
+                    handleProviderStartedStateChange(providerState);
                     break;
                 }
                 case PROVIDER_STATE_PERM_FAILED: {
@@ -344,18 +346,18 @@
         ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
         ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
 
-        // If a provider has failed, the other may need to be enabled.
+        // If a provider has failed, the other may need to be started.
         if (failedProvider == mPrimaryProvider) {
             if (secondaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
-                // The primary must have failed. Try to enable the secondary. This does nothing if
-                // the provider is already enabled, and will leave the provider in
-                // {enabled initializing} if the provider is disabled.
-                tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
+                // The primary must have failed. Try to start the secondary. This does nothing if
+                // the provider is already started, and will leave the provider in
+                // {started initializing} if the provider is stopped.
+                tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
             }
         } else if (failedProvider == mSecondaryProvider) {
             // No-op: The secondary will only be active if the primary is uncertain or is failed.
-            // So, there the primary should not need to be enabled when the secondary fails.
-            if (primaryCurrentState.stateEnum != PROVIDER_STATE_ENABLED_UNCERTAIN
+            // So, there the primary should not need to be started when the secondary fails.
+            if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
                     && primaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
                 warnLog("Secondary provider unexpected reported a failure:"
                         + " failed provider=" + failedProvider.getName()
@@ -384,16 +386,16 @@
     }
 
     /**
-     * Called when a provider has changed state but just moved from one enabled state to another
-     * enabled state, usually as a result of a new {@link LocationTimeZoneEvent} being received.
+     * Called when a provider has changed state but just moved from one started state to another
+     * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
      * However, there are rare cases where the event can also be null.
      */
     @GuardedBy("mSharedLock")
-    private void handleProviderEnabledStateChange(@NonNull ProviderState providerState) {
+    private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
         LocationTimeZoneProvider provider = providerState.provider;
-        LocationTimeZoneEvent event = providerState.event;
+        TimeZoneProviderEvent event = providerState.event;
         if (event == null) {
-            // Implicit uncertainty, i.e. where the provider is enabled, but a problem has been
+            // Implicit uncertainty, i.e. where the provider is started, but a problem has been
             // detected without having received an event. For example, if the process has detected
             // the loss of a binder-based provider, or initialization took too long. This is treated
             // the same as explicit uncertainty, i.e. where the provider has explicitly told this
@@ -404,18 +406,18 @@
         }
 
         if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
-            // This should not happen: the provider should not be in an enabled state if the user
+            // This should not happen: the provider should not be in an started state if the user
             // does not have geodetection enabled.
-            warnLog("Provider=" + provider + " is enabled, but"
+            warnLog("Provider=" + provider + " is started, but"
                     + " currentUserConfiguration=" + mCurrentUserConfiguration
                     + " suggests it shouldn't be.");
         }
 
-        switch (event.getEventType()) {
+        switch (event.getType()) {
             case EVENT_TYPE_PERMANENT_FAILURE: {
-                // This shouldn't happen. A provider cannot be enabled and have this event type.
+                // This shouldn't happen. A provider cannot be started and have this event type.
                 warnLog("Provider=" + provider
-                        + " is enabled, but event suggests it shouldn't be");
+                        + " is started, but event suggests it shouldn't be");
                 break;
             }
             case EVENT_TYPE_UNCERTAIN: {
@@ -423,13 +425,13 @@
                         + ", explicit uncertainty. event=" + event);
                 break;
             }
-            case EVENT_TYPE_SUCCESS: {
-                handleProviderCertainty(provider, event.getTimeZoneIds(),
+            case EVENT_TYPE_SUGGESTION: {
+                handleProviderSuggestion(provider, event.getSuggestion().getTimeZoneIds(),
                         "Event received provider=" + provider + ", event=" + event);
                 break;
             }
             default: {
-                warnLog("Unknown eventType=" + event.getEventType());
+                warnLog("Unknown eventType=" + event.getType());
                 break;
             }
         }
@@ -439,7 +441,7 @@
      * Called when a provider has become "certain" about the time zone(s).
      */
     @GuardedBy("mSharedLock")
-    private void handleProviderCertainty(
+    private void handleProviderSuggestion(
             @NonNull LocationTimeZoneProvider provider,
             @Nullable List<String> timeZoneIds,
             @NonNull String reason) {
@@ -447,11 +449,10 @@
         cancelUncertaintyTimeout();
 
         if (provider == mPrimaryProvider) {
-            disableProviderIfEnabled(mSecondaryProvider);
+            stopProviderIfStarted(mSecondaryProvider);
         }
 
-        GeolocationTimeZoneSuggestion suggestion =
-                new GeolocationTimeZoneSuggestion(timeZoneIds);
+        GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(timeZoneIds);
         suggestion.addDebugInfo(reason);
         // Rely on the receiver to dedupe suggestions. It is better to over-communicate.
         makeSuggestion(suggestion);
@@ -503,7 +504,7 @@
      * Called when a provider has become "uncertain" about the time zone.
      *
      * <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
-     * this enables the most flexibility for the controller to enable other providers when there are
+     * this enables the most flexibility for the controller to start other providers when there are
      * multiple ones available. The controller is therefore responsible for deciding when to make a
      * "uncertain" suggestion to the downstream time zone detector.
      *
@@ -532,11 +533,11 @@
         }
 
         if (provider == mPrimaryProvider) {
-            // (Try to) enable the secondary. It could already be enabled, or enabling might not
+            // (Try to) start the secondary. It could already be started, or enabling might not
             // succeed if the provider has previously reported it is perm failed. The uncertainty
             // timeout (set above) is used to ensure that an uncertain suggestion will be made if
             // the secondary cannot generate a success event in time.
-            tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
+            tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
         }
     }
 
diff --git a/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java b/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
index 17e719e..b59898a 100644
--- a/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
+++ b/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location.timezone;
 
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.os.Handler;
 
@@ -57,12 +58,12 @@
     }
 
     @Override
-    void postDelayed(@NonNull Runnable r, long delayMillis) {
+    void postDelayed(@NonNull Runnable r, @DurationMillisLong long delayMillis) {
         getHandler().postDelayed(r, delayMillis);
     }
 
     @Override
-    void postDelayed(Runnable r, Object token, long delayMillis) {
+    void postDelayed(Runnable r, Object token, @DurationMillisLong long delayMillis) {
         getHandler().postDelayed(r, token, delayMillis);
     }
 
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
index c8a1db6..98ebec2 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
@@ -24,6 +24,7 @@
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.SystemProperties;
+import android.service.timezone.TimeZoneProviderService;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Slog;
@@ -44,7 +45,7 @@
  * A service class that acts as a container for the {@link LocationTimeZoneProviderController},
  * which determines what {@link com.android.server.timezonedetector.GeolocationTimeZoneSuggestion}
  * are made to the {@link TimeZoneDetectorInternal}, and the {@link LocationTimeZoneProvider}s that
- * (indirectly) generate {@link com.android.internal.location.timezone.LocationTimeZoneEvent}s.
+ * (indirectly) generate {@link TimeZoneProviderEvent}s.
  *
  * <p>For details of the time zone suggestion behavior, see {@link
  * LocationTimeZoneProviderController}.
@@ -120,9 +121,9 @@
     private static final String ATTRIBUTION_TAG = "LocationTimeZoneService";
 
     private static final String PRIMARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
-            "com.android.location.timezone.service.v1.PrimaryLocationTimeZoneProvider";
+            TimeZoneProviderService.PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE;
     private static final String SECONDARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
-            "com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider";
+            TimeZoneProviderService.SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE;
 
 
     @NonNull private final Context mContext;
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
index dc56238..8b51ab4 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
@@ -16,16 +16,17 @@
 
 package com.android.server.location.timezone;
 
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,7 +35,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
 import com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
 import com.android.server.location.timezone.ThreadingDomain.SingleRunnableQueue;
 import com.android.server.timezonedetector.ConfigurationInternal;
@@ -50,7 +50,7 @@
  * process, or could be a stubbed instance when no real provider is registered.
  *
  * <p>The provider is supplied with a {@link ProviderListener} via {@link
- * #initialize(ProviderListener)}. This enables it to communicates asynchronous detection / error
+ * #initialize(ProviderListener)}. This starts communication of asynchronous detection / error
  * events back to the {@link LocationTimeZoneProviderController} via the {@link
  * ProviderListener#onProviderStateChange} method. This call must be made on the
  * {@link Handler} thread from the {@link ThreadingDomain} passed to the constructor.
@@ -77,9 +77,10 @@
      */
     static class ProviderState {
 
-        @IntDef({ PROVIDER_STATE_UNKNOWN, PROVIDER_STATE_ENABLED_INITIALIZING,
-                PROVIDER_STATE_ENABLED_CERTAIN, PROVIDER_STATE_ENABLED_UNCERTAIN,
-                PROVIDER_STATE_DISABLED, PROVIDER_STATE_PERM_FAILED })
+        @IntDef(prefix = "PROVIDER_STATE_",
+                value = { PROVIDER_STATE_UNKNOWN, PROVIDER_STATE_STARTED_INITIALIZING,
+                PROVIDER_STATE_STARTED_CERTAIN, PROVIDER_STATE_STARTED_UNCERTAIN,
+                PROVIDER_STATE_STOPPED, PROVIDER_STATE_PERM_FAILED })
         @interface ProviderStateEnum {}
 
         /**
@@ -88,31 +89,31 @@
         static final int PROVIDER_STATE_UNKNOWN = 0;
 
         /**
-         * The provider is enabled and has not reported its first event.
+         * The provider is started and has not reported its first event.
          */
-        static final int PROVIDER_STATE_ENABLED_INITIALIZING = 1;
+        static final int PROVIDER_STATE_STARTED_INITIALIZING = 1;
 
         /**
-         * The provider is enabled and most recently reported a "success" event.
+         * The provider is started and most recently reported a "suggestion" event.
          */
-        static final int PROVIDER_STATE_ENABLED_CERTAIN = 2;
+        static final int PROVIDER_STATE_STARTED_CERTAIN = 2;
 
         /**
-         * The provider is enabled and most recently reported an "uncertain" event.
+         * The provider is started and most recently reported an "uncertain" event.
          */
-        static final int PROVIDER_STATE_ENABLED_UNCERTAIN = 3;
+        static final int PROVIDER_STATE_STARTED_UNCERTAIN = 3;
 
         /**
-         * The provider is disabled.
+         * The provider is stopped.
          *
          * This is the state after {@link #initialize} is called.
          */
-        static final int PROVIDER_STATE_DISABLED = 4;
+        static final int PROVIDER_STATE_STOPPED = 4;
 
         /**
-         * The provider has failed and cannot be re-enabled.
+         * The provider has failed and cannot be re-started.
          *
-         * Providers may enter this state after a provider is enabled.
+         * Providers may enter this state after a provider is started.
          */
         static final int PROVIDER_STATE_PERM_FAILED = 5;
 
@@ -123,16 +124,16 @@
         public final @ProviderStateEnum int stateEnum;
 
         /**
-         * The last {@link LocationTimeZoneEvent} received. Only populated when {@link #stateEnum}
-         * is either {@link #PROVIDER_STATE_ENABLED_CERTAIN} or {@link
-         * #PROVIDER_STATE_ENABLED_UNCERTAIN}, but it can be {@code null} then too if no event has
+         * The last {@link TimeZoneProviderEvent} received. Only populated when {@link #stateEnum}
+         * is either {@link #PROVIDER_STATE_STARTED_CERTAIN} or {@link
+         * #PROVIDER_STATE_STARTED_UNCERTAIN}, but it can be {@code null} then too if no event has
          * yet been received.
          */
-        @Nullable public final LocationTimeZoneEvent event;
+        @Nullable public final TimeZoneProviderEvent event;
 
         /**
          * The user configuration associated with the current state. Only and always present when
-         * {@link #stateEnum} is one of the enabled states.
+         * {@link #stateEnum} is one of the started states.
          */
         @Nullable public final ConfigurationInternal currentUserConfiguration;
 
@@ -140,6 +141,7 @@
          * The time according to the elapsed realtime clock when the provider entered the current
          * state. Included for debugging, not used for equality.
          */
+        @ElapsedRealtimeLong
         private final long mStateEntryTimeMillis;
 
         /**
@@ -151,7 +153,7 @@
 
         private ProviderState(@NonNull LocationTimeZoneProvider provider,
                 @ProviderStateEnum int stateEnum,
-                @Nullable LocationTimeZoneEvent event,
+                @Nullable TimeZoneProviderEvent event,
                 @Nullable ConfigurationInternal currentUserConfiguration,
                 @Nullable String debugInfo) {
             this.provider = Objects.requireNonNull(provider);
@@ -174,25 +176,25 @@
          * and that the required parameters for the new state are present / absent.
          */
         ProviderState newState(@ProviderStateEnum int newStateEnum,
-                @Nullable LocationTimeZoneEvent event,
+                @Nullable TimeZoneProviderEvent event,
                 @Nullable ConfigurationInternal currentUserConfig,
                 @Nullable String debugInfo) {
 
             // Check valid "from" transitions.
             switch (this.stateEnum) {
                 case PROVIDER_STATE_UNKNOWN: {
-                    if (newStateEnum != PROVIDER_STATE_DISABLED) {
+                    if (newStateEnum != PROVIDER_STATE_STOPPED) {
                         throw new IllegalArgumentException(
                                 "Must transition from " + prettyPrintStateEnum(
                                         PROVIDER_STATE_UNKNOWN)
-                                        + " to " + prettyPrintStateEnum(PROVIDER_STATE_DISABLED));
+                                        + " to " + prettyPrintStateEnum(PROVIDER_STATE_STOPPED));
                     }
                     break;
                 }
-                case PROVIDER_STATE_DISABLED:
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+                case PROVIDER_STATE_STOPPED:
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
                     // These can go to each other or PROVIDER_STATE_PERM_FAILED.
                     break;
                 }
@@ -211,21 +213,21 @@
                     throw new IllegalArgumentException("Cannot transition to "
                             + prettyPrintStateEnum(PROVIDER_STATE_UNKNOWN));
                 }
-                case PROVIDER_STATE_DISABLED: {
+                case PROVIDER_STATE_STOPPED: {
                     if (event != null || currentUserConfig != null) {
                         throw new IllegalArgumentException(
-                                "Disabled state: event and currentUserConfig must be null"
+                                "Stopped state: event and currentUserConfig must be null"
                                         + ", event=" + event
                                         + ", currentUserConfig=" + currentUserConfig);
                     }
                     break;
                 }
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
                     if (currentUserConfig == null) {
                         throw new IllegalArgumentException(
-                                "Enabled state: currentUserConfig must not be null");
+                                "Started state: currentUserConfig must not be null");
                     }
                     break;
                 }
@@ -245,11 +247,11 @@
             return new ProviderState(provider, newStateEnum, event, currentUserConfig, debugInfo);
         }
 
-        /** Returns {@code true} if {@link #stateEnum} is one of the enabled states. */
-        boolean isEnabled() {
-            return stateEnum == PROVIDER_STATE_ENABLED_INITIALIZING
-                    || stateEnum == PROVIDER_STATE_ENABLED_CERTAIN
-                    || stateEnum == PROVIDER_STATE_ENABLED_UNCERTAIN;
+        /** Returns {@code true} if {@link #stateEnum} is one of the started states. */
+        boolean isStarted() {
+            return stateEnum == PROVIDER_STATE_STARTED_INITIALIZING
+                    || stateEnum == PROVIDER_STATE_STARTED_CERTAIN
+                    || stateEnum == PROVIDER_STATE_STARTED_UNCERTAIN;
         }
 
         @Override
@@ -286,14 +288,14 @@
 
         private static String prettyPrintStateEnum(@ProviderStateEnum int state) {
             switch (state) {
-                case PROVIDER_STATE_DISABLED:
-                    return "Disabled (" + PROVIDER_STATE_DISABLED + ")";
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                    return "Enabled initializing (" + PROVIDER_STATE_ENABLED_INITIALIZING + ")";
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                    return "Enabled certain (" + PROVIDER_STATE_ENABLED_CERTAIN + ")";
-                case PROVIDER_STATE_ENABLED_UNCERTAIN:
-                    return "Enabled uncertain (" + PROVIDER_STATE_ENABLED_UNCERTAIN + ")";
+                case PROVIDER_STATE_STOPPED:
+                    return "Stopped (" + PROVIDER_STATE_STOPPED + ")";
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                    return "Started initializing (" + PROVIDER_STATE_STARTED_INITIALIZING + ")";
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                    return "Started certain (" + PROVIDER_STATE_STARTED_CERTAIN + ")";
+                case PROVIDER_STATE_STARTED_UNCERTAIN:
+                    return "Started uncertain (" + PROVIDER_STATE_STARTED_UNCERTAIN + ")";
                 case PROVIDER_STATE_PERM_FAILED:
                     return "Perm failure (" + PROVIDER_STATE_PERM_FAILED + ")";
                 case PROVIDER_STATE_UNKNOWN:
@@ -315,7 +317,7 @@
             new ReferenceWithHistory<>(10);
 
     /**
-     * Used for scheduling initialization timeouts, i.e. for providers that have just been enabled.
+     * Used for scheduling initialization timeouts, i.e. for providers that have just been started.
      */
     @NonNull private final SingleRunnableQueue mInitializationTimeoutQueue;
 
@@ -344,7 +346,7 @@
             mProviderListener = Objects.requireNonNull(providerListener);
             ProviderState currentState = ProviderState.createStartingState(this);
             ProviderState newState = currentState.newState(
-                    PROVIDER_STATE_DISABLED, null, null,
+                    PROVIDER_STATE_STOPPED, null, null,
                     "initialize() called");
             setCurrentState(newState, false);
 
@@ -407,28 +409,28 @@
     }
 
     /**
-     * Enables the provider. It is an error to call this method except when the {@link
-     * #getCurrentState()} is at {@link ProviderState#PROVIDER_STATE_DISABLED}. This method must be
+     * Starts the provider. It is an error to call this method except when the {@link
+     * #getCurrentState()} is at {@link ProviderState#PROVIDER_STATE_STOPPED}. This method must be
      * called using the handler thread from the {@link ThreadingDomain}.
      */
-    final void enable(@NonNull ConfigurationInternal currentUserConfiguration,
+    final void startUpdates(@NonNull ConfigurationInternal currentUserConfiguration,
             @NonNull Duration initializationTimeout, @NonNull Duration initializationTimeoutFuzz) {
         mThreadingDomain.assertCurrentThread();
 
         synchronized (mSharedLock) {
-            assertCurrentState(PROVIDER_STATE_DISABLED);
+            assertCurrentState(PROVIDER_STATE_STOPPED);
 
             ProviderState currentState = mCurrentState.get();
             ProviderState newState = currentState.newState(
-                    PROVIDER_STATE_ENABLED_INITIALIZING, null /* event */,
-                    currentUserConfiguration, "enable() called");
+                    PROVIDER_STATE_STARTED_INITIALIZING, null /* event */,
+                    currentUserConfiguration, "startUpdates() called");
             setCurrentState(newState, false);
 
             Duration delay = initializationTimeout.plus(initializationTimeoutFuzz);
             mInitializationTimeoutQueue.runDelayed(
                     this::handleInitializationTimeout, delay.toMillis());
 
-            onEnable(initializationTimeout);
+            onStartUpdates(initializationTimeout);
         }
     }
 
@@ -437,10 +439,10 @@
 
         synchronized (mSharedLock) {
             ProviderState currentState = mCurrentState.get();
-            if (currentState.stateEnum == PROVIDER_STATE_ENABLED_INITIALIZING) {
+            if (currentState.stateEnum == PROVIDER_STATE_STARTED_INITIALIZING) {
                 // On initialization timeout the provider becomes uncertain.
                 ProviderState newState = currentState.newState(
-                        PROVIDER_STATE_ENABLED_UNCERTAIN, null /* event */,
+                        PROVIDER_STATE_STARTED_UNCERTAIN, null /* event */,
                         currentState.currentUserConfiguration, "initialization timeout");
                 setCurrentState(newState, true);
             }
@@ -448,65 +450,64 @@
     }
 
     /**
-     * Implemented by subclasses to do work during {@link #enable}.
+     * Implemented by subclasses to do work during {@link #startUpdates}.
      */
-    abstract void onEnable(@NonNull Duration initializationTimeout);
+    abstract void onStartUpdates(@NonNull Duration initializationTimeout);
 
     /**
-     * Disables the provider. It is an error* to call this method except when the {@link
-     * #getCurrentState()} is one of the enabled states. This method must be
+     * Stops the provider. It is an error* to call this method except when the {@link
+     * #getCurrentState()} is one of the started states. This method must be
      * called using the handler thread from the {@link ThreadingDomain}.
      */
-    final void disable() {
+    final void stopUpdates() {
         mThreadingDomain.assertCurrentThread();
 
         synchronized (mSharedLock) {
-            assertIsEnabled();
+            assertIsStarted();
 
             ProviderState currentState = mCurrentState.get();
             ProviderState newState = currentState.newState(
-                    PROVIDER_STATE_DISABLED, null, null, "disable() called");
+                    PROVIDER_STATE_STOPPED, null, null, "stopUpdates() called");
             setCurrentState(newState, false);
 
             if (mInitializationTimeoutQueue.hasQueued()) {
                 mInitializationTimeoutQueue.cancel();
             }
 
-            onDisable();
+            onStopUpdates();
         }
     }
 
     /**
-     * Implemented by subclasses to do work during {@link #disable}.
+     * Implemented by subclasses to do work during {@link #stopUpdates}.
      */
-    abstract void onDisable();
+    abstract void onStopUpdates();
 
-    /** For subclasses to invoke when a {@link LocationTimeZoneEvent} has been received. */
-    final void handleLocationTimeZoneEvent(
-            @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
+    /** For subclasses to invoke when a {@link TimeZoneProviderEvent} has been received. */
+    final void handleTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
         mThreadingDomain.assertCurrentThread();
-        Objects.requireNonNull(locationTimeZoneEvent);
+        Objects.requireNonNull(timeZoneProviderEvent);
 
         synchronized (mSharedLock) {
-            debugLog("handleLocationTimeZoneEvent: mProviderName=" + mProviderName
-                    + ", locationTimeZoneEvent=" + locationTimeZoneEvent);
+            debugLog("handleTimeZoneProviderEvent: mProviderName=" + mProviderName
+                    + ", timeZoneProviderEvent=" + timeZoneProviderEvent);
 
             ProviderState currentState = mCurrentState.get();
-            int eventType = locationTimeZoneEvent.getEventType();
+            int eventType = timeZoneProviderEvent.getType();
             switch (currentState.stateEnum) {
                 case PROVIDER_STATE_PERM_FAILED: {
                     // After entering perm failed, there is nothing to do. The remote peer is
                     // supposed to stop sending events after it has reported perm failure.
-                    logWarn("handleLocationTimeZoneEvent: Event=" + locationTimeZoneEvent
+                    logWarn("handleTimeZoneProviderEvent: Event=" + timeZoneProviderEvent
                             + " received for provider=" + this + " when in failed state");
                     return;
                 }
-                case PROVIDER_STATE_DISABLED: {
+                case PROVIDER_STATE_STOPPED: {
                     switch (eventType) {
                         case EVENT_TYPE_PERMANENT_FAILURE: {
-                            String msg = "handleLocationTimeZoneEvent:"
-                                    + " Failure event=" + locationTimeZoneEvent
-                                    + " received for disabled provider=" + this
+                            String msg = "handleTimeZoneProviderEvent:"
+                                    + " Failure event=" + timeZoneProviderEvent
+                                    + " received for stopped provider=" + this
                                     + ", entering permanently failed state";
                             logWarn(msg);
                             ProviderState newState = currentState.newState(
@@ -517,30 +518,30 @@
                             }
                             return;
                         }
-                        case EVENT_TYPE_SUCCESS:
+                        case EVENT_TYPE_SUGGESTION:
                         case EVENT_TYPE_UNCERTAIN: {
-                            // Any geolocation-related events received for a disabled provider are
+                            // Any geolocation-related events received for a stopped provider are
                             // ignored: they should not happen.
-                            logWarn("handleLocationTimeZoneEvent:"
-                                    + " event=" + locationTimeZoneEvent
-                                    + " received for disabled provider=" + this
+                            logWarn("handleTimeZoneProviderEvent:"
+                                    + " event=" + timeZoneProviderEvent
+                                    + " received for stopped provider=" + this
                                     + ", ignoring");
 
                             return;
                         }
                         default: {
                             throw new IllegalStateException(
-                                    "Unknown eventType=" + locationTimeZoneEvent);
+                                    "Unknown eventType=" + timeZoneProviderEvent);
                         }
                     }
                 }
-                case PROVIDER_STATE_ENABLED_INITIALIZING:
-                case PROVIDER_STATE_ENABLED_CERTAIN:
-                case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
                     switch (eventType) {
                         case EVENT_TYPE_PERMANENT_FAILURE: {
-                            String msg = "handleLocationTimeZoneEvent:"
-                                    + " Failure event=" + locationTimeZoneEvent
+                            String msg = "handleTimeZoneProviderEvent:"
+                                    + " Failure event=" + timeZoneProviderEvent
                                     + " received for provider=" + this
                                     + ", entering permanently failed state";
                             logWarn(msg);
@@ -554,16 +555,16 @@
                             return;
                         }
                         case EVENT_TYPE_UNCERTAIN:
-                        case EVENT_TYPE_SUCCESS: {
+                        case EVENT_TYPE_SUGGESTION: {
                             @ProviderStateEnum int providerStateEnum;
                             if (eventType == EVENT_TYPE_UNCERTAIN) {
-                                providerStateEnum = PROVIDER_STATE_ENABLED_UNCERTAIN;
+                                providerStateEnum = PROVIDER_STATE_STARTED_UNCERTAIN;
                             } else {
-                                providerStateEnum = PROVIDER_STATE_ENABLED_CERTAIN;
+                                providerStateEnum = PROVIDER_STATE_STARTED_CERTAIN;
                             }
                             ProviderState newState = currentState.newState(providerStateEnum,
-                                    locationTimeZoneEvent, currentState.currentUserConfiguration,
-                                    "handleLocationTimeZoneEvent() when enabled");
+                                    timeZoneProviderEvent, currentState.currentUserConfiguration,
+                                    "handleTimeZoneProviderEvent() when started");
                             setCurrentState(newState, true);
                             if (mInitializationTimeoutQueue.hasQueued()) {
                                 mInitializationTimeoutQueue.cancel();
@@ -572,7 +573,7 @@
                         }
                         default: {
                             throw new IllegalStateException(
-                                    "Unknown eventType=" + locationTimeZoneEvent);
+                                    "Unknown eventType=" + timeZoneProviderEvent);
                         }
                     }
                 }
@@ -589,10 +590,10 @@
     abstract void logWarn(String msg);
 
     @GuardedBy("mSharedLock")
-    private void assertIsEnabled() {
+    private void assertIsStarted() {
         ProviderState currentState = mCurrentState.get();
-        if (!currentState.isEnabled()) {
-            throw new IllegalStateException("Required an enabled state, but was " + currentState);
+        if (!currentState.isStarted()) {
+            throw new IllegalStateException("Required a started state, but was " + currentState);
         }
     }
 
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
index ace066e..45ec400 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location.timezone;
 
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.os.Handler;
 
@@ -59,7 +60,7 @@
  * disputed areas and oceans. Distinguishing uncertainty allows the controller to try other
  * providers (or give up), where as certainty means it should not.
  *
- * <p>A provider can fail permanently. A permanent failure will disable the provider until next
+ * <p>A provider can fail permanently. A permanent failure will stop the provider until next
  * boot.
  */
 abstract class LocationTimeZoneProviderController implements Dumpable {
@@ -90,6 +91,7 @@
     abstract boolean isUncertaintyTimeoutSet();
 
     @VisibleForTesting
+    @DurationMillisLong
     abstract long getUncertaintyTimeoutDelayMillis();
 
     /**
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
index 8a0259d..91b52f1 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
@@ -23,17 +23,15 @@
 import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
 import com.android.server.timezonedetector.Dumpable;
 
 import java.util.Objects;
 
 /**
- * System server-side proxy for ILocationTimeZoneProvider implementations, i.e. this provides the
- * system server object used to communicate with a remote LocationTimeZoneProvider over Binder,
- * which could be running in a different process. As LocationTimeZoneProviders are bound / unbound
- * this proxy will rebind to the "best" available remote process.
+ * System server-side proxy for ITimeZoneProvider implementations, i.e. this provides the system
+ * server object used to communicate with a remote TimeZoneProvider over Binder, which could be
+ * running in a different process. As TimeZoneProviders are bound / unbound this proxy will rebind
+ * to the "best" available remote process.
  *
  * <p>Threading guarantees provided / required by this interface:
  * <ul>
@@ -41,8 +39,8 @@
  *     from the {@link ThreadingDomain} passed to the constructor, excluding
  *     {@link #dump(IndentingPrintWriter, String[])}</li>
  *     <li>Non-static public methods that make binder calls to remote processes (e.g.
- *     {@link #setRequest(LocationTimeZoneProviderRequest)}) are executed asynchronously and will
- *     return immediately.</li>
+ *     {@link #setRequest(TimeZoneProviderRequest)}) are executed asynchronously and will return
+ *     immediately.</li>
  *     <li>Callbacks received via binder are delivered via {@link Listener} are delivered on the
  *     {@link Handler} thread from the {@link ThreadingDomain} passed to the constructor.
  * </ul>
@@ -93,16 +91,15 @@
     /**
      * Sets a new request for the provider.
      */
-    abstract void setRequest(@NonNull LocationTimeZoneProviderRequest request);
+    abstract void setRequest(@NonNull TimeZoneProviderRequest request);
 
     /**
-     * Handles a {@link LocationTimeZoneEvent} from a remote process.
+     * Handles a {@link TimeZoneProviderEvent} from a remote process.
      */
-    final void handleLocationTimeZoneEvent(
-            @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
+    final void handleTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
         // These calls are invoked on a binder thread. Move to the mThreadingDomain thread as
         // required by the guarantees for this class.
-        mThreadingDomain.post(() -> mListener.onReportLocationTimeZoneEvent(locationTimeZoneEvent));
+        mThreadingDomain.post(() -> mListener.onReportTimeZoneProviderEvent(timeZoneProviderEvent));
     }
 
     /**
@@ -112,9 +109,9 @@
     interface Listener {
 
         /**
-         * Called when a provider receives a {@link LocationTimeZoneEvent}.
+         * Called when a provider receives a {@link TimeZoneProviderEvent}.
          */
-        void onReportLocationTimeZoneEvent(@NonNull LocationTimeZoneEvent locationTimeZoneEvent);
+        void onReportTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent);
 
         /**
          * Called when a provider is (re)bound.
diff --git a/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
index fbcc71f..e11a7ce 100644
--- a/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
@@ -35,11 +35,11 @@
  * and a secondary {@link LocationTimeZoneProvider}, but only a primary is configured, the secondary
  * config will be left null and the {@link LocationTimeZoneProvider} implementation will be
  * defaulted to a {@link NullLocationTimeZoneProvider}. The {@link NullLocationTimeZoneProvider}
- * enters a {@link ProviderState#PROVIDER_STATE_PERM_FAILED} state immediately after being enabled
+ * enters a {@link ProviderState#PROVIDER_STATE_PERM_FAILED} state immediately after being started
  * for the first time and sends the appropriate event, which ensures the {@link
  * LocationTimeZoneProviderController} won't expect any further {@link
- * com.android.internal.location.timezone.LocationTimeZoneEvent}s to come from it, and won't attempt
- * to use it again.
+ * TimeZoneProviderEvent}s to come from it, and won't attempt to use it
+ * again.
  */
 class NullLocationTimeZoneProvider extends LocationTimeZoneProvider {
 
@@ -57,7 +57,7 @@
     }
 
     @Override
-    void onEnable(@NonNull Duration initializationTimeout) {
+    void onStartUpdates(@NonNull Duration initializationTimeout) {
         // Report a failure (asynchronously using the mThreadingDomain thread to avoid recursion).
         mThreadingDomain.post(()-> {
             // Enter the perm-failed state.
@@ -69,8 +69,8 @@
     }
 
     @Override
-    void onDisable() {
-        // Ignored - NullLocationTimeZoneProvider is always permanently failed.
+    void onStopUpdates() {
+        // Ignored - this implementation is always permanently failed.
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
index 1a01288..1bb5cec 100644
--- a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
@@ -22,22 +22,22 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.service.timezone.ITimeZoneProvider;
+import android.service.timezone.ITimeZoneProviderManager;
+import android.service.timezone.TimeZoneProviderSuggestion;
 import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.ILocationTimeZoneProvider;
-import com.android.internal.location.timezone.ILocationTimeZoneProviderManager;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
 import com.android.server.ServiceWatcher;
 
 import java.util.Objects;
 
 /**
- * System server-side proxy for ILocationTimeZoneProvider implementations, i.e. this provides the
- * system server object used to communicate with a remote LocationTimeZoneProvider over Binder,
- * which could be running in a different process. As "remote" LocationTimeZoneProviders are bound /
- * unbound this proxy will rebind to the "best" available remote process.
+ * System server-side proxy for ITimeZoneProvider implementations, i.e. this provides the
+ * system server object used to communicate with a remote {@link
+ * android.service.timezone.TimeZoneProviderService} over Binder, which could be running in a
+ * different process. As "remote" providers are bound / unbound this proxy will rebind to the "best"
+ * available remote process.
  */
 class RealLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
 
@@ -47,7 +47,7 @@
     @Nullable private ManagerProxy mManagerProxy;
 
     @GuardedBy("mProxyLock")
-    @NonNull private LocationTimeZoneProviderRequest mRequest;
+    @NonNull private TimeZoneProviderRequest mRequest;
 
     RealLocationTimeZoneProviderProxy(
             @NonNull Context context, @NonNull ThreadingDomain threadingDomain,
@@ -55,7 +55,7 @@
             int nonOverlayPackageResId) {
         super(context, threadingDomain);
         mManagerProxy = null;
-        mRequest = LocationTimeZoneProviderRequest.EMPTY_REQUEST;
+        mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
         mServiceWatcher = new ServiceWatcher(context, action, this::onBind, this::onUnbind,
                 enableOverlayResId, nonOverlayPackageResId);
     }
@@ -93,12 +93,12 @@
     private void onBindOnHandlerThread(@NonNull IBinder binder) {
         mThreadingDomain.assertCurrentThread();
 
-        ILocationTimeZoneProvider provider = ILocationTimeZoneProvider.Stub.asInterface(binder);
+        ITimeZoneProvider provider = ITimeZoneProvider.Stub.asInterface(binder);
 
         synchronized (mSharedLock) {
             try {
                 mManagerProxy = new ManagerProxy();
-                provider.setLocationTimeZoneProviderManager(mManagerProxy);
+                provider.setTimeZoneProviderManager(mManagerProxy);
                 trySendCurrentRequest();
                 mListener.onProviderBound();
             } catch (RemoteException e) {
@@ -118,7 +118,7 @@
     }
 
     @Override
-    final void setRequest(@NonNull LocationTimeZoneProviderRequest request) {
+    final void setRequest(@NonNull TimeZoneProviderRequest request) {
         mThreadingDomain.assertCurrentThread();
 
         Objects.requireNonNull(request);
@@ -131,11 +131,14 @@
 
     @GuardedBy("mProxyLock")
     private void trySendCurrentRequest() {
-        LocationTimeZoneProviderRequest request = mRequest;
+        TimeZoneProviderRequest request = mRequest;
         mServiceWatcher.runOnBinder(binder -> {
-            ILocationTimeZoneProvider service =
-                    ILocationTimeZoneProvider.Stub.asInterface(binder);
-            service.setRequest(request);
+            ITimeZoneProvider service = ITimeZoneProvider.Stub.asInterface(binder);
+            if (request.sendUpdates()) {
+                service.startUpdates(request.getInitializationTimeout().toMillis());
+            } else {
+                service.stopUpdates();
+            }
         });
     }
 
@@ -148,21 +151,39 @@
     }
 
     /**
-     * A system Server-side proxy for the ILocationTimeZoneProviderManager, i.e. this is a local
-     * binder stub. Each "remote" LocationTimeZoneProvider is passed a binder instance that it
-     * then uses to communicate back with the system server, invoking the logic here.
+     * A system Server-side proxy for the ITimeZoneProviderManager, i.e. this is a local binder stub
+     * Each "remote" TimeZoneProvider is passed a binder instance that it then uses to communicate
+     * back with the system server, invoking the logic here.
      */
-    private class ManagerProxy extends ILocationTimeZoneProviderManager.Stub {
+    private class ManagerProxy extends ITimeZoneProviderManager.Stub {
 
         // executed on binder thread
         @Override
-        public void onLocationTimeZoneEvent(LocationTimeZoneEvent locationTimeZoneEvent) {
+        public void onTimeZoneProviderSuggestion(TimeZoneProviderSuggestion suggestion) {
+            onTimeZoneProviderEvent(TimeZoneProviderEvent.createSuggestionEvent(suggestion));
+        }
+
+        // executed on binder thread
+        @Override
+        public void onTimeZoneProviderUncertain() {
+            onTimeZoneProviderEvent(TimeZoneProviderEvent.createUncertainEvent());
+
+        }
+
+        // executed on binder thread
+        @Override
+        public void onTimeZoneProviderPermanentFailure(String failureReason) {
+            onTimeZoneProviderEvent(
+                    TimeZoneProviderEvent.createPermanentFailureEvent(failureReason));
+        }
+
+        private void onTimeZoneProviderEvent(TimeZoneProviderEvent event) {
             synchronized (mSharedLock) {
                 if (mManagerProxy != this) {
                     return;
                 }
             }
-            handleLocationTimeZoneEvent(locationTimeZoneEvent);
+            handleTimeZoneProviderEvent(event);
         }
     }
 }
diff --git a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
index 7725309..0987ee5 100644
--- a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
+++ b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
@@ -16,9 +16,6 @@
 
 package com.android.server.location.timezone;
 
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.PRIMARY_PROVIDER_NAME;
 import static com.android.server.location.timezone.LocationTimeZoneManagerService.SECONDARY_PROVIDER_NAME;
 
@@ -26,8 +23,7 @@
 import android.annotation.Nullable;
 import android.os.ShellCommand;
 import android.os.SystemClock;
-
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
+import android.service.timezone.TimeZoneProviderSuggestion;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -50,14 +46,14 @@
 
 
     @NonNull private final String mProviderName;
-    private final int mEventType;
-    @Nullable private final LocationTimeZoneEvent mLocationTimeZoneEvent;
+    private final int mType;
+    @Nullable private final TimeZoneProviderEvent mTimeZoneProviderEvent;
 
     private SimulatedBinderProviderEvent(@NonNull String providerName, int eventType,
-            @Nullable LocationTimeZoneEvent locationTimeZoneEvent) {
+            @Nullable TimeZoneProviderEvent timeZoneProviderEvent) {
         this.mProviderName = Objects.requireNonNull(providerName);
-        this.mEventType = eventType;
-        this.mLocationTimeZoneEvent = locationTimeZoneEvent;
+        this.mType = eventType;
+        this.mTimeZoneProviderEvent = timeZoneProviderEvent;
     }
 
     @NonNull
@@ -66,24 +62,24 @@
     }
 
     @Nullable
-    LocationTimeZoneEvent getLocationTimeZoneEvent() {
-        return mLocationTimeZoneEvent;
+    TimeZoneProviderEvent getTimeZoneProviderEvent() {
+        return mTimeZoneProviderEvent;
     }
 
-    int getEventType() {
-        return mEventType;
+    int getType() {
+        return mType;
     }
 
     /** Prints the command line options that {@link #createFromArgs(ShellCommand)} understands. */
     static void printCommandLineOpts(PrintWriter pw) {
         pw.println("Simulated provider binder event:");
         pw.println();
-        pw.println("<provider name> [onBind|onUnbind|locationTimeZoneEvent"
+        pw.println("<provider name> [onBind|onUnbind|timeZoneProviderEvent"
                 + " <location time zone event args>]");
         pw.println();
         pw.println("<provider name> = " + VALID_PROVIDER_NAMES);
-        pw.println("<location time zone event args> ="
-                + " [PERMANENT_FAILURE|UNCERTAIN|SUCCESS <time zone ids>*]");
+        pw.println("<time zone provider event args> ="
+                + " [PERMANENT_FAILURE|UNCERTAIN|SUGGESTION <time zone ids>*]");
     }
 
     /**
@@ -104,8 +100,8 @@
                 return new SimulatedBinderProviderEvent(
                         providerName, INJECTED_EVENT_TYPE_ON_UNBIND, null);
             }
-            case "locationTimeZoneEvent": {
-                LocationTimeZoneEvent event = parseLocationTimeZoneEventArgs(shellCommand);
+            case "timeZoneProviderEvent": {
+                TimeZoneProviderEvent event = parseTimeZoneProviderEventArgs(shellCommand);
                 return new SimulatedBinderProviderEvent(providerName,
                         INJECTED_EVENT_TYPE_LOCATION_TIME_ZONE_EVENT, event);
             }
@@ -115,30 +111,31 @@
         }
     }
 
-    private static LocationTimeZoneEvent parseLocationTimeZoneEventArgs(ShellCommand shellCommand) {
-        LocationTimeZoneEvent.Builder eventBuilder = new LocationTimeZoneEvent.Builder()
-                .setElapsedRealtimeMillis(SystemClock.elapsedRealtime());
-
+    private static TimeZoneProviderEvent parseTimeZoneProviderEventArgs(ShellCommand shellCommand) {
+        TimeZoneProviderEvent event;
         String eventTypeString = shellCommand.getNextArgRequired();
         switch (eventTypeString.toUpperCase()) {
             case "PERMANENT_FAILURE": {
-                eventBuilder.setEventType(EVENT_TYPE_PERMANENT_FAILURE);
+                event = TimeZoneProviderEvent.createPermanentFailureEvent("Simulated");
                 break;
             }
             case "UNCERTAIN": {
-                eventBuilder.setEventType(EVENT_TYPE_UNCERTAIN);
+                event = TimeZoneProviderEvent.createUncertainEvent();
                 break;
             }
-            case "SUCCESS": {
-                eventBuilder.setEventType(EVENT_TYPE_SUCCESS)
-                        .setTimeZoneIds(parseTimeZoneArgs(shellCommand));
+            case "SUGGESTION": {
+                TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
+                        .setElapsedRealtimeMillis(SystemClock.elapsedRealtime())
+                        .setTimeZoneIds(parseTimeZoneArgs(shellCommand))
+                        .build();
+                event = TimeZoneProviderEvent.createSuggestionEvent(suggestion);
                 break;
             }
             default: {
                 throw new IllegalArgumentException("Error: Unknown eventType: " + eventTypeString);
             }
         }
-        return eventBuilder.build();
+        return event;
     }
 
     private static List<String> parseTimeZoneArgs(ShellCommand shellCommand) {
@@ -154,8 +151,8 @@
     public String toString() {
         return "SimulatedBinderProviderEvent{"
                 + "mProviderName=" + mProviderName
-                + ", mEventType=" + mEventType
-                + ", mLocationTimeZoneEvent=" + mLocationTimeZoneEvent
+                + ", mType=" + mType
+                + ", mTimeZoneProviderEvent=" + mTimeZoneProviderEvent
                 + '}';
     }
 }
diff --git a/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
index 5e66a99..cac5621 100644
--- a/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
@@ -26,7 +26,6 @@
 import android.util.IndentingPrintWriter;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
 import com.android.server.timezonedetector.ReferenceWithHistory;
 
 import java.util.Objects;
@@ -38,7 +37,7 @@
 class SimulatedLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
 
     @GuardedBy("mSharedLock")
-    @NonNull private LocationTimeZoneProviderRequest mRequest;
+    @NonNull private TimeZoneProviderRequest mRequest;
 
     @GuardedBy("mSharedLock")
     @NonNull private final ReferenceWithHistory<String> mLastEvent = new ReferenceWithHistory<>(50);
@@ -46,7 +45,7 @@
     SimulatedLocationTimeZoneProviderProxy(
             @NonNull Context context, @NonNull ThreadingDomain threadingDomain) {
         super(context, threadingDomain);
-        mRequest = LocationTimeZoneProviderRequest.EMPTY_REQUEST;
+        mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
     }
 
     @Override
@@ -60,7 +59,7 @@
         Objects.requireNonNull(event);
 
         synchronized (mSharedLock) {
-            switch (event.getEventType()) {
+            switch (event.getType()) {
                 case INJECTED_EVENT_TYPE_ON_BIND: {
                     mLastEvent.set("Simulating onProviderBound(), event=" + event);
                     mThreadingDomain.post(this::onBindOnHandlerThread);
@@ -72,12 +71,12 @@
                     break;
                 }
                 case INJECTED_EVENT_TYPE_LOCATION_TIME_ZONE_EVENT: {
-                    if (!mRequest.getReportLocationTimeZone()) {
+                    if (!mRequest.sendUpdates()) {
                         mLastEvent.set("Test event=" + event + " is testing an invalid case:"
                                 + " reporting is off. mRequest=" + mRequest);
                     }
-                    mLastEvent.set("Simulating LocationTimeZoneEvent, event=" + event);
-                    handleLocationTimeZoneEvent(event.getLocationTimeZoneEvent());
+                    mLastEvent.set("Simulating TimeZoneProviderResult, event=" + event);
+                    handleTimeZoneProviderEvent(event.getTimeZoneProviderEvent());
                     break;
                 }
                 default: {
@@ -106,7 +105,7 @@
     }
 
     @Override
-    final void setRequest(@NonNull LocationTimeZoneProviderRequest request) {
+    final void setRequest(@NonNull TimeZoneProviderRequest request) {
         mThreadingDomain.assertCurrentThread();
 
         Objects.requireNonNull(request);
diff --git a/services/core/java/com/android/server/location/timezone/ThreadingDomain.java b/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
index d55d3ed..a50f8ad 100644
--- a/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
+++ b/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location.timezone;
 
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 
 import com.android.internal.util.Preconditions;
@@ -68,9 +69,9 @@
     /**
      * Execute the supplied runnable on the threading domain's thread with a delay.
      */
-    abstract void postDelayed(@NonNull Runnable runnable, long delayMillis);
+    abstract void postDelayed(@NonNull Runnable runnable, @DurationMillisLong long delayMillis);
 
-    abstract void postDelayed(Runnable r, Object token, long delayMillis);
+    abstract void postDelayed(Runnable r, Object token, @DurationMillisLong long delayMillis);
 
     abstract void removeQueuedRunnables(Object token);
 
@@ -90,6 +91,7 @@
     final class SingleRunnableQueue {
 
         private boolean mIsQueued;
+        @DurationMillisLong
         private long mDelayMillis;
 
         /**
@@ -97,7 +99,7 @@
          * handler thread, cancelling any queued but not-yet-executed {@link Runnable} previously
          * added by this. This method must be called from the threading domain's thread.
          */
-        void runDelayed(Runnable r, long delayMillis) {
+        void runDelayed(Runnable r, @DurationMillisLong long delayMillis) {
             cancel();
             mIsQueued = true;
             mDelayMillis = delayMillis;
@@ -122,6 +124,7 @@
          * IllegalStateException} if nothing is currently queued, see {@link #hasQueued()}.
          * This method must be called from the threading domain's thread.
          */
+        @DurationMillisLong
         long getQueuedDelayMillis() {
             assertCurrentThread();
             if (!mIsQueued) {
diff --git a/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.java b/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.java
new file mode 100644
index 0000000..2d6f8ad
--- /dev/null
+++ b/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.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.location.timezone;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.service.timezone.TimeZoneProviderService;
+import android.service.timezone.TimeZoneProviderSuggestion;
+
+import java.util.Objects;
+
+/**
+ * An event from a {@link TimeZoneProviderService}.
+ */
+final class TimeZoneProviderEvent {
+
+    @IntDef(prefix = "EVENT_TYPE_",
+            value = { EVENT_TYPE_PERMANENT_FAILURE, EVENT_TYPE_SUGGESTION, EVENT_TYPE_UNCERTAIN })
+    public @interface EventType {}
+
+    /**
+     * The provider failed permanently. See {@link
+     * TimeZoneProviderService#reportPermanentFailure(Throwable)}
+     */
+    public static final int EVENT_TYPE_PERMANENT_FAILURE = 1;
+
+    /**
+     * The provider made a suggestion. See {@link
+     * TimeZoneProviderService#reportSuggestion(TimeZoneProviderSuggestion)}
+     */
+    public static final int EVENT_TYPE_SUGGESTION = 2;
+
+    /**
+     * The provider was uncertain about the time zone. See {@link
+     * TimeZoneProviderService#reportUncertain()}
+     */
+    public static final int EVENT_TYPE_UNCERTAIN = 3;
+
+    private static final TimeZoneProviderEvent UNCERTAIN_EVENT =
+            new TimeZoneProviderEvent(EVENT_TYPE_UNCERTAIN, null, null);
+
+    @EventType
+    private final int mType;
+
+    @Nullable
+    private final TimeZoneProviderSuggestion mSuggestion;
+
+    @Nullable
+    private final String mFailureCause;
+
+    private TimeZoneProviderEvent(@EventType int type,
+            @Nullable TimeZoneProviderSuggestion suggestion,
+            @Nullable String failureCause) {
+        mType = type;
+        mSuggestion = suggestion;
+        mFailureCause = failureCause;
+    }
+
+    /** Returns a event of type {@link #EVENT_TYPE_SUGGESTION}. */
+    public static TimeZoneProviderEvent createSuggestionEvent(
+            @NonNull TimeZoneProviderSuggestion suggestion) {
+        return new TimeZoneProviderEvent(EVENT_TYPE_SUGGESTION,
+                Objects.requireNonNull(suggestion), null);
+    }
+
+    /** Returns a event of type {@link #EVENT_TYPE_UNCERTAIN}. */
+    public static TimeZoneProviderEvent createUncertainEvent() {
+        return UNCERTAIN_EVENT;
+    }
+
+    /** Returns a event of type {@link #EVENT_TYPE_PERMANENT_FAILURE}. */
+    public static TimeZoneProviderEvent createPermanentFailureEvent(@NonNull String cause) {
+        return new TimeZoneProviderEvent(EVENT_TYPE_PERMANENT_FAILURE, null,
+                Objects.requireNonNull(cause));
+    }
+
+    /**
+     * Returns the event type.
+     */
+    public @EventType int getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the suggestion. Populated when {@link #getType()} is {@link #EVENT_TYPE_SUGGESTION}.
+     */
+    @Nullable
+    public TimeZoneProviderSuggestion getSuggestion() {
+        return mSuggestion;
+    }
+
+    /**
+     * Returns the failure cauese. Populated when {@link #getType()} is {@link
+     * #EVENT_TYPE_PERMANENT_FAILURE}.
+     */
+    @Nullable
+    public String getFailureCause() {
+        return mFailureCause;
+    }
+
+    @Override
+    public String toString() {
+        return "TimeZoneProviderEvent{"
+                + "mType=" + mType
+                + ", mSuggestion=" + mSuggestion
+                + ", mFailureCause=" + mFailureCause
+                + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TimeZoneProviderEvent that = (TimeZoneProviderEvent) o;
+        return mType == that.mType
+                && Objects.equals(mSuggestion, that.mSuggestion)
+                && Objects.equals(mFailureCause, that.mFailureCause);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mType, mSuggestion, mFailureCause);
+    }
+}
diff --git a/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java b/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java
new file mode 100644
index 0000000..649a74b
--- /dev/null
+++ b/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * This class encapsulates a request to a provider.
+ */
+final class TimeZoneProviderRequest {
+
+    @NonNull
+    private static final TimeZoneProviderRequest STOP_UPDATES =
+            new TimeZoneProviderRequest(
+                    false /* sendUpdates */,
+                    null /* initializationTimeout */);
+
+    private final boolean mSendUpdates;
+
+    @Nullable
+    private final Duration mInitializationTimeout;
+
+    private TimeZoneProviderRequest(
+            boolean sendUpdates, @Nullable Duration initializationTimeout) {
+        mSendUpdates = sendUpdates;
+        mInitializationTimeout = initializationTimeout;
+    }
+
+    /** Creates a request to start updates with the specified timeout. */
+    public static TimeZoneProviderRequest createStartUpdatesRequest(
+            @NonNull Duration initializationTimeout) {
+        return new TimeZoneProviderRequest(true, Objects.requireNonNull(initializationTimeout));
+    }
+
+    /** Creates a request to stop updates. */
+    public static TimeZoneProviderRequest createStopUpdatesRequest() {
+        return STOP_UPDATES;
+    }
+
+    /**
+     * Returns {@code true} if the provider should send updates related to the device's current
+     * time zone, {@code false} otherwise.
+     */
+    public boolean sendUpdates() {
+        return mSendUpdates;
+    }
+
+    // TODO(b/152744911) - once there are a couple of implementations, decide whether this needs to
+    //  be passed to the TimeZoneProviderService and remove if it is not useful.
+    /**
+     * Returns the maximum time that the provider is allowed to initialize before it is expected to
+     * send an event of any sort. Only valid when {@link #sendUpdates()} is {@code true}. Failure to
+     * send an event in this time (with some fuzz) may be interpreted as if the provider is
+     * uncertain of the time zone, and/or it could lead to the provider being stopped.
+     */
+    @Nullable
+    public Duration getInitializationTimeout() {
+        return mInitializationTimeout;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TimeZoneProviderRequest
+                that = (TimeZoneProviderRequest) o;
+        return mSendUpdates == that.mSendUpdates
+                && mInitializationTimeout == that.mInitializationTimeout;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mSendUpdates, mInitializationTimeout);
+    }
+
+    @Override
+    public String toString() {
+        return "TimeZoneProviderRequest{"
+                + "mSendUpdates=" + mSendUpdates
+                + ", mInitializationTimeout=" + mInitializationTimeout
+                + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index c4581c8..834cf05 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -16,8 +16,6 @@
 
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
-
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
 
@@ -271,15 +269,17 @@
     private boolean isNewCredentialSufficient(LockscreenCredential credential) {
         final PasswordMetrics requiredMetrics =
                 mLockPatternUtils.getRequestedPasswordMetrics(mCurrentUserId);
+        final int requiredComplexity =
+                mLockPatternUtils.getRequestedPasswordComplexity(mCurrentUserId);
         final List<PasswordValidationError> errors;
         if (credential.isPassword() || credential.isPin()) {
-            errors = PasswordMetrics.validatePassword(requiredMetrics, PASSWORD_COMPLEXITY_NONE,
+            errors = PasswordMetrics.validatePassword(requiredMetrics, requiredComplexity,
                     credential.isPin(), credential.getCredential());
         } else {
             PasswordMetrics metrics = new PasswordMetrics(
                     credential.isPattern() ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_NONE);
             errors = PasswordMetrics.validatePasswordMetrics(
-                    requiredMetrics, PASSWORD_COMPLEXITY_NONE, false /* isPin */, metrics);
+                    requiredMetrics, requiredComplexity, false /* isPin */, metrics);
         }
         if (!errors.isEmpty()) {
             getOutPrintWriter().println(
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
new file mode 100644
index 0000000..08b8a8c
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -0,0 +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/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 0b3cdae..7afa81a 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -165,11 +165,13 @@
 
     private void buildBluetoothRoutes() {
         mBluetoothRoutes.clear();
-        for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) {
-            if (device.isConnected()) {
-                BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
-                if (newBtRoute.connectedProfiles.size() > 0) {
-                    mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+        if (mBluetoothAdapter.getBondedDevices() != null) {
+            for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) {
+                if (device.isConnected()) {
+                    BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
+                    if (newBtRoute.connectedProfiles.size() > 0) {
+                        mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index f882c57..edc9d7c 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -77,7 +77,7 @@
     @NonNull
     public List<RoutingSessionInfo> getSessionInfos() {
         synchronized (mLock) {
-            return mSessionInfos;
+            return new ArrayList<>(mSessionInfos);
         }
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 85af346..ab38dca 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -108,8 +108,8 @@
         mLastDiscoveryPreference = discoveryPreference;
         if (mConnectionReady) {
             mActiveConnection.updateDiscoveryPreference(discoveryPreference);
-            updateBinding();
         }
+        updateBinding();
     }
 
     @Override
@@ -205,9 +205,11 @@
     }
 
     private boolean shouldBind() {
-        //TODO: Binding could be delayed until it's necessary.
         if (mRunning) {
-            return true;
+            // Bind when there is a discovery preference or an active route session.
+            return (mLastDiscoveryPreference != null
+                    && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
+                    || !getSessionInfos().isEmpty();
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1114fe0..31edf43 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
 import static android.media.MediaRouter2Utils.getOriginalId;
 import static android.media.MediaRouter2Utils.getProviderId;
@@ -73,10 +74,12 @@
     // TODO: (In Android S or later) if we add callback methods for generic failures
     //       in MediaRouter2, remove this constant and replace the usages with the real request IDs.
     private static final long DUMMY_REQUEST_ID = -1;
+    private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND;
 
     private final Context mContext;
     private final Object mLock = new Object();
     final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
+    final ActivityManager mActivityManager;
 
     @GuardedBy("mLock")
     private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
@@ -87,8 +90,21 @@
     @GuardedBy("mLock")
     private int mCurrentUserId = -1;
 
+    private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener =
+            (uid, importance) -> {
+                synchronized (mLock) {
+                    final int count = mUserRecords.size();
+                    for (int i = 0; i < count; i++) {
+                        mUserRecords.valueAt(i).mHandler.maybeUpdateDiscoveryPreferenceForUid(uid);
+                    }
+                }
+            };
+
     MediaRouter2ServiceImpl(Context context) {
         mContext = context;
+        mActivityManager = mContext.getSystemService(ActivityManager.class);
+        mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener,
+                PACKAGE_IMPORTANCE_FOR_DISCOVERY);
     }
 
     ////////////////////////////////////////////////////////////////
@@ -388,6 +404,30 @@
         }
     }
 
+    public void startScan(IMediaRouter2Manager manager) {
+        Objects.requireNonNull(manager, "manager must not be null");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                startScanLocked(manager);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void stopScan(IMediaRouter2Manager manager) {
+        Objects.requireNonNull(manager, "manager must not be null");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                stopScanLocked(manager);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
             MediaRoute2Info route, int volume) {
         Objects.requireNonNull(manager, "manager must not be null");
@@ -839,6 +879,24 @@
         disposeUserIfNeededLocked(userRecord); // since manager removed from user
     }
 
+    private void startScanLocked(@NonNull IMediaRouter2Manager manager) {
+        final IBinder binder = manager.asBinder();
+        ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+        if (managerRecord == null) {
+            return;
+        }
+        managerRecord.startScan();
+    }
+
+    private void stopScanLocked(@NonNull IMediaRouter2Manager manager) {
+        final IBinder binder = manager.asBinder();
+        ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+        if (managerRecord == null) {
+            return;
+        }
+        managerRecord.stopScan();
+    }
+
     private void setRouteVolumeWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager,
             @NonNull MediaRoute2Info route, int volume) {
@@ -1122,6 +1180,7 @@
         public final String mPackageName;
         public final int mManagerId;
         public SessionCreationRequest mLastSessionCreationRequest;
+        public boolean mIsScanning;
 
         ManagerRecord(UserRecord userRecord, IMediaRouter2Manager manager,
                 int uid, int pid, String packageName) {
@@ -1146,6 +1205,24 @@
             pw.println(prefix + this);
         }
 
+        public void startScan() {
+            if (mIsScanning) {
+                return;
+            }
+            mIsScanning = true;
+            mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage(
+                    UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler));
+        }
+
+        public void stopScan() {
+            if (!mIsScanning) {
+                return;
+            }
+            mIsScanning = false;
+            mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage(
+                    UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler));
+        }
+
         @Override
         public String toString() {
             return "Manager " + mPackageName + " (pid " + mPid + ")";
@@ -1262,6 +1339,24 @@
             return null;
         }
 
+        public void maybeUpdateDiscoveryPreferenceForUid(int uid) {
+            MediaRouter2ServiceImpl service = mServiceRef.get();
+            if (service == null) {
+                return;
+            }
+            boolean isUidRelevant;
+            synchronized (service.mLock) {
+                isUidRelevant = mUserRecord.mRouterRecords.stream().anyMatch(
+                        router -> router.mUid == uid)
+                        | mUserRecord.mManagerRecords.stream().anyMatch(
+                            manager -> manager.mUid == uid);
+            }
+            if (isUidRelevant) {
+                sendMessage(PooledLambda.obtainMessage(
+                        UserHandler::updateDiscoveryPreferenceOnHandler, this));
+            }
+        }
+
         private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
             int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
             MediaRoute2ProviderInfo currentInfo = provider.getProviderInfo();
@@ -1767,6 +1862,16 @@
             return managers;
         }
 
+        private List<RouterRecord> getRouterRecords() {
+            MediaRouter2ServiceImpl service = mServiceRef.get();
+            if (service == null) {
+                return Collections.emptyList();
+            }
+            synchronized (service.mLock) {
+                return new ArrayList<>(mUserRecord.mRouterRecords);
+            }
+        }
+
         private List<ManagerRecord> getManagerRecords() {
             MediaRouter2ServiceImpl service = mServiceRef.get();
             if (service == null) {
@@ -2001,13 +2106,28 @@
                 return;
             }
             List<RouteDiscoveryPreference> discoveryPreferences = new ArrayList<>();
-            synchronized (service.mLock) {
-                for (RouterRecord routerRecord : mUserRecord.mRouterRecords) {
+            List<RouterRecord> routerRecords = getRouterRecords();
+            List<ManagerRecord> managerRecords = getManagerRecords();
+            boolean isAnyManagerScanning =
+                    managerRecords.stream().anyMatch(manager -> manager.mIsScanning
+                    && service.mActivityManager.getPackageImportance(manager.mPackageName)
+                    <= PACKAGE_IMPORTANCE_FOR_DISCOVERY);
+
+            for (RouterRecord routerRecord : routerRecords) {
+                if (isAnyManagerScanning
+                        || service.mActivityManager.getPackageImportance(routerRecord.mPackageName)
+                        <= PACKAGE_IMPORTANCE_FOR_DISCOVERY) {
                     discoveryPreferences.add(routerRecord.mDiscoveryPreference);
                 }
-                mUserRecord.mCompositeDiscoveryPreference =
-                        new RouteDiscoveryPreference.Builder(discoveryPreferences)
-                                .build();
+            }
+
+            synchronized (service.mLock) {
+                RouteDiscoveryPreference newPreference =
+                        new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
+                if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)) {
+                    return;
+                }
+                mUserRecord.mCompositeDiscoveryPreference = newPreference;
             }
             for (MediaRoute2Provider provider : mRouteProviders) {
                 provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 0e52a67..b6d6cc4 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -544,6 +544,18 @@
 
     // Binder call
     @Override
+    public void startScan(IMediaRouter2Manager manager) {
+        mService2.startScan(manager);
+    }
+
+    // Binder call
+    @Override
+    public void stopScan(IMediaRouter2Manager manager) {
+        mService2.stopScan(manager);
+    }
+
+    // Binder call
+    @Override
     public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
             MediaRoute2Info route, int volume) {
         mService2.setRouteVolumeWithManager(manager, requestId, route, volume);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 11dbef2..17ceb15 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.os.UserHandle.ALL;
 import static android.os.UserHandle.CURRENT;
 
@@ -40,7 +41,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.UserInfo;
 import android.media.AudioManager;
 import android.media.AudioPlaybackConfiguration;
 import android.media.IRemoteVolumeControllerCallback;
@@ -393,15 +393,17 @@
         synchronized (mLock) {
             UserManager manager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
             mFullUserIds.clear();
-            List<UserInfo> allUsers = manager.getUsers();
+            List<UserHandle> allUsers = manager.getUserHandles(/*excludeDying=*/false);
             if (allUsers != null) {
-                for (UserInfo userInfo : allUsers) {
-                    if (userInfo.isManagedProfile()) {
-                        mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
+                for (UserHandle user : allUsers) {
+                    UserHandle parent = manager.getProfileParent(user);
+                    if (parent != null) {
+                        mFullUserIds.put(user.getIdentifier(), parent.getIdentifier());
                     } else {
-                        mFullUserIds.put(userInfo.id, userInfo.id);
-                        if (mUserRecords.get(userInfo.id) == null) {
-                            mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
+                        mFullUserIds.put(user.getIdentifier(), user.getIdentifier());
+                        if (mUserRecords.get(user.getIdentifier()) == null) {
+                            mUserRecords.put(user.getIdentifier(),
+                                    new FullUserRecord(user.getIdentifier()));
                         }
                     }
                 }
@@ -1114,8 +1116,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 enforcePackageName(packageName, uid);
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        false /* allowAll */, true /* requireFull */, "createSession", packageName);
+                int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
                 if (cb == null) {
                     throw new IllegalArgumentException("Controller callback cannot be null");
                 }
@@ -1190,11 +1191,8 @@
             final long token = Binder.clearCallingIdentity();
 
             try {
-                // Check that they can make calls on behalf of the user and
-                // get the final user id
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        true /* allowAll */, true /* requireFull */, "getSession2Tokens",
-                        null /* optional packageName */);
+                // Check that they can make calls on behalf of the user and get the final user id
+                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
                 List<Session2Token> result;
                 synchronized (mLock) {
                     FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1261,9 +1259,7 @@
 
             try {
                 // Check that they can make calls on behalf of the user and get the final user id.
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
-                        null /* optional packageName */);
+                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
                 synchronized (mLock) {
                     int index = findIndexOfSession2TokensListenerLocked(listener);
                     if (index >= 0) {
@@ -1980,16 +1976,40 @@
                 packageName = componentName.getPackageName();
                 enforcePackageName(packageName, uid);
             }
-            // Check that they can make calls on behalf of the user and
-            // get the final user id
-            int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                    true /* allowAll */, true /* requireFull */, "getSessions", packageName);
-            // Check if they have the permissions or their component is
-            // enabled for the user they're calling from.
+            // Check that they can make calls on behalf of the user and get the final user id
+            int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
+            // Check if they have the permissions or their component is enabled for the user
+            // they're calling from.
             enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
             return resolvedUserId;
         }
 
+        // Handles incoming user by checking whether the caller has permission to access the
+        // given user id's information or not. Permission is not necessary if the given user id is
+        // equal to the caller's user id, but if not, the caller needs to have the
+        // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
+        // The return value will be the given user id, unless the given user id is
+        // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
+        private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
+            int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+            if (userId == callingUserId) {
+                return userId;
+            }
+
+            boolean canInteractAcrossUsersFull = mContext.checkPermission(
+                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
+            if (canInteractAcrossUsersFull) {
+                if (userId == CURRENT.getIdentifier()) {
+                    return ActivityManager.getCurrentUser();
+                }
+                return userId;
+            }
+
+            throw new SecurityException("Permission denied while calling from " + packageName
+                    + " with user id: " + userId + "; Need to run as either the calling user id ("
+                    + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
+        }
+
         private boolean hasEnabledNotificationListener(int callingUserId,
                 String controllerPackageName, int controllerUid) {
             int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index f0bf5c0..9c5abd4 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -16,11 +16,11 @@
 
 package com.android.server.net;
 
+import android.net.InetAddresses;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
 import android.net.StaticIpConfiguration;
@@ -284,8 +284,10 @@
                         } else if (key.equals(IP_ASSIGNMENT_KEY)) {
                             ipAssignment = IpAssignment.valueOf(in.readUTF());
                         } else if (key.equals(LINK_ADDRESS_KEY)) {
-                            LinkAddress linkAddr = new LinkAddress(
-                                    NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
+                            LinkAddress linkAddr =
+                                    new LinkAddress(
+                                            InetAddresses.parseNumericAddress(in.readUTF()),
+                                            in.readInt());
                             if (linkAddr.getAddress() instanceof Inet4Address &&
                                     staticIpConfiguration.ipAddress == null) {
                                 staticIpConfiguration.ipAddress = linkAddr;
@@ -297,7 +299,7 @@
                             InetAddress gateway = null;
                             if (version == 1) {
                                 // only supported default gateways - leave the dest/prefix empty
-                                gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                gateway = InetAddresses.parseNumericAddress(in.readUTF());
                                 if (staticIpConfiguration.gateway == null) {
                                     staticIpConfiguration.gateway = gateway;
                                 } else {
@@ -305,12 +307,13 @@
                                 }
                             } else {
                                 if (in.readInt() == 1) {
-                                    dest = new LinkAddress(
-                                            NetworkUtils.numericToInetAddress(in.readUTF()),
-                                            in.readInt());
+                                    dest =
+                                            new LinkAddress(
+                                                    InetAddresses.parseNumericAddress(in.readUTF()),
+                                                    in.readInt());
                                 }
                                 if (in.readInt() == 1) {
-                                    gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                    gateway = InetAddresses.parseNumericAddress(in.readUTF());
                                 }
                                 RouteInfo route = new RouteInfo(dest, gateway);
                                 if (route.isIPv4Default() &&
@@ -322,7 +325,7 @@
                             }
                         } else if (key.equals(DNS_KEY)) {
                             staticIpConfiguration.dnsServers.add(
-                                    NetworkUtils.numericToInetAddress(in.readUTF()));
+                                    InetAddresses.parseNumericAddress(in.readUTF()));
                         } else if (key.equals(PROXY_SETTINGS_KEY)) {
                             proxySettings = ProxySettings.valueOf(in.readUTF());
                         } else if (key.equals(PROXY_HOST_KEY)) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a44ddcb..5f8b31a 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -230,7 +230,6 @@
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.StatLogger;
 import com.android.internal.util.XmlUtils;
@@ -243,9 +242,7 @@
 
 import libcore.io.IoUtils;
 
-import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -256,7 +253,6 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.nio.charset.StandardCharsets;
 import java.time.Clock;
 import java.time.Instant;
 import java.time.ZoneId;
@@ -271,6 +267,7 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.function.IntConsumer;
 
 /**
  * Service that maintains low-level network policy rules, using
@@ -4034,7 +4031,8 @@
         try {
             updateRulesForDeviceIdleUL();
             updateRulesForPowerSaveUL();
-            updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
+            forEachUid("updateRulesForRestrictPower",
+                    uid -> updateRulesForPowerRestrictionsUL(uid));
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
@@ -4044,31 +4042,19 @@
     private void updateRulesForRestrictBackgroundUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictBackgroundUL");
         try {
-            updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND);
+            forEachUid("updateRulesForRestrictBackground",
+                    uid -> updateRulesForDataUsageRestrictionsUL(uid));
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
     }
 
-    private static final int TYPE_RESTRICT_BACKGROUND = 1;
-    private static final int TYPE_RESTRICT_POWER = 2;
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = false, value = {
-            TYPE_RESTRICT_BACKGROUND,
-            TYPE_RESTRICT_POWER,
-    })
-    public @interface RestrictType {
-    }
-
-    // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them...
-    @GuardedBy("mUidRulesFirstLock")
-    private void updateRulesForAllAppsUL(@RestrictType int type) {
+    private void forEachUid(String tag, IntConsumer consumer) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
-            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL-" + type);
+            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "forEachUid-" + tag);
         }
         try {
             // update rules for all installed applications
-
             final PackageManager pm = mContext.getPackageManager();
             final List<UserInfo> users;
             final List<ApplicationInfo> apps;
@@ -4096,16 +4082,7 @@
                 for (int j = 0; j < appsSize; j++) {
                     final ApplicationInfo app = apps.get(j);
                     final int uid = UserHandle.getUid(user.id, app.uid);
-                    switch (type) {
-                        case TYPE_RESTRICT_BACKGROUND:
-                            updateRulesForDataUsageRestrictionsUL(uid);
-                            break;
-                        case TYPE_RESTRICT_POWER:
-                            updateRulesForPowerRestrictionsUL(uid);
-                            break;
-                        default:
-                            Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type);
-                    }
+                    consumer.accept(uid);
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index c1deb96..b9984a5 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -293,9 +293,7 @@
                                 .appendPath(file.getAbsolutePath()).build())
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                         .putExtra(EXTRA_KEY, file.getAbsolutePath()),
-                // TODO(b/174161800) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
         mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, deletionTime, pi);
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 692e97a..c9ed518 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -242,7 +242,6 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.logging.InstanceIdSequence;
@@ -468,7 +467,6 @@
     private UriGrantsManagerInternal mUgmInternal;
     private RoleObserver mRoleObserver;
     private UserManager mUm;
-    private IPlatformCompat mPlatformCompat;
     private ShortcutHelper mShortcutHelper;
 
     final IBinder mForegroundToken = new Binder();
@@ -1987,8 +1985,6 @@
         mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class);
         mDpm = dpm;
         mUm = userManager;
-        mPlatformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
 
         mUiHandler = new Handler(UiThread.get().getLooper());
         String[] extractorNames;
@@ -2278,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(
@@ -2886,16 +2896,16 @@
         return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
     }
 
-    private ToastRecord getToastRecord(int uid, int pid, String packageName, IBinder token,
-            @Nullable CharSequence text, @Nullable ITransientNotification callback, int duration,
-            Binder windowToken, int displayId,
+    private ToastRecord getToastRecord(int uid, int pid, String packageName, boolean isSystemToast,
+            IBinder token, @Nullable CharSequence text, @Nullable ITransientNotification callback,
+            int duration, Binder windowToken, int displayId,
             @Nullable ITransientNotificationCallback textCallback) {
         if (callback == null) {
-            return new TextToastRecord(this, mStatusBar, uid, pid, packageName, token, text,
-                    duration, windowToken, displayId, textCallback);
+            return new TextToastRecord(this, mStatusBar, uid, pid, packageName,
+                    isSystemToast, token, text, duration, windowToken, displayId, textCallback);
         } else {
-            return new CustomToastRecord(this, uid, pid, packageName, token, callback, duration,
-                    windowToken, displayId);
+            return new CustomToastRecord(this, uid, pid, packageName,
+                    isSystemToast, token, callback, duration, windowToken, displayId);
         }
     }
 
@@ -2966,31 +2976,10 @@
             }
 
             boolean isAppRenderedToast = (callback != null);
-            if (isAppRenderedToast && !isSystemToast && !isPackageInForegroundForToast(pkg,
-                    callingUid)) {
-                boolean block;
-                final long id = Binder.clearCallingIdentity();
-                try {
-                    // CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so block will be
-                    // false for apps with targetSdk < R. For apps with targetSdk R+, text toasts
-                    // are not app-rendered, so isAppRenderedToast == true means it's a custom
-                    // toast.
-                    block = mPlatformCompat.isChangeEnabledByPackageName(
-                            CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, pkg,
-                            callingUser.getIdentifier());
-                } catch (RemoteException e) {
-                    // Shouldn't happen have since it's a local local
-                    Slog.e(TAG, "Unexpected exception while checking block background custom toasts"
-                            + " change", e);
-                    block = false;
-                } finally {
-                    Binder.restoreCallingIdentity(id);
-                }
-                if (block) {
-                    Slog.w(TAG, "Blocking custom toast from package " + pkg
-                            + " due to package not in the foreground");
-                    return;
-                }
+            if (blockToast(callingUid, isSystemToast, isAppRenderedToast)) {
+                Slog.w(TAG, "Blocking custom toast from package " + pkg
+                        + " due to package not in the foreground at time the toast was posted");
+                return;
             }
 
             synchronized (mToastQueue) {
@@ -3023,8 +3012,8 @@
 
                         Binder windowToken = new Binder();
                         mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId);
-                        record = getToastRecord(callingUid, callingPid, pkg, token, text, callback,
-                                duration, windowToken, displayId, textCallback);
+                        record = getToastRecord(callingUid, callingPid, pkg, isSystemToast, token,
+                                text, callback, duration, windowToken, displayId, textCallback);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
                         keepProcessAliveForToastIfNeededLocked(callingPid);
@@ -3042,28 +3031,6 @@
             }
         }
 
-        /**
-         * Implementation note: Our definition of foreground for toasts is an implementation matter
-         * and should strike a balance between functionality and anti-abuse effectiveness. We
-         * currently worry about the following cases:
-         * <ol>
-         *     <li>App with fullscreen activity: Allow toasts
-         *     <li>App behind translucent activity from other app: Block toasts
-         *     <li>App in multi-window: Allow toasts
-         *     <li>App with expanded bubble: Allow toasts
-         *     <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts
-         *     <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts
-         * </ol>
-         * Checking if the UID has any resumed activities satisfy use-cases above.
-         *
-         * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) ==
-         * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has
-         * any visible activities, failing case 2 in list above.
-         */
-        private boolean isPackageInForegroundForToast(String pkg, int callingUid) {
-            return mAtm.hasResumedActivity(callingUid);
-        }
-
         @Override
         public void cancelToast(String pkg, IBinder token) {
             Slog.i(TAG, "cancelToast pkg=" + pkg + " token=" + token);
@@ -7388,17 +7355,16 @@
                     CompatChanges.isChangeEnabled(RATE_LIMIT_TOASTS, record.uid);
             boolean isWithinQuota =
                     mToastRateLimiter.isWithinQuota(userId, record.pkg, TOAST_QUOTA_TAG);
-            if ((!rateLimitingEnabled || isWithinQuota) && record.show()) {
+
+            if (tryShowToast(record, rateLimitingEnabled, isWithinQuota)) {
                 scheduleDurationReachedLocked(record);
                 mIsCurrentToastShown = true;
                 if (rateLimitingEnabled) {
                     mToastRateLimiter.noteEvent(userId, record.pkg, TOAST_QUOTA_TAG);
                 }
                 return;
-            } else if (rateLimitingEnabled && !isWithinQuota) {
-                Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the "
-                        + "following toast was blocked and discarded: " + record);
             }
+
             int index = mToastQueue.indexOf(record);
             if (index >= 0) {
                 mToastQueue.remove(index);
@@ -7407,6 +7373,22 @@
         }
     }
 
+    /** Returns true if it successfully showed the toast. */
+    private boolean tryShowToast(ToastRecord record, boolean rateLimitingEnabled,
+            boolean isWithinQuota) {
+        if (rateLimitingEnabled && !isWithinQuota) {
+            Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the "
+                    + "following toast was blocked and discarded: " + record);
+            return false;
+        }
+        if (blockToast(record.uid, record.isSystemToast, record.isAppRendered())) {
+            Slog.w(TAG, "Blocking custom toast from package " + record.pkg
+                    + " due to package not in the foreground at the time of showing the toast");
+            return false;
+        }
+        return record.show();
+    }
+
     @GuardedBy("mToastQueue")
     void cancelToastLocked(int index) {
         ToastRecord record = mToastQueue.get(index);
@@ -7526,6 +7508,44 @@
         }
     }
 
+    /**
+     * Implementation note: Our definition of foreground for toasts is an implementation matter
+     * and should strike a balance between functionality and anti-abuse effectiveness. We
+     * currently worry about the following cases:
+     * <ol>
+     *     <li>App with fullscreen activity: Allow toasts
+     *     <li>App behind translucent activity from other app: Block toasts
+     *     <li>App in multi-window: Allow toasts
+     *     <li>App with expanded bubble: Allow toasts
+     *     <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts
+     *     <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts
+     * </ol>
+     * Checking if the UID has any resumed activities satisfy use-cases above.
+     *
+     * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) ==
+     * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has
+     * any visible activities, failing case 2 in list above.
+     */
+    private boolean isPackageInForegroundForToast(int callingUid) {
+        return mAtm.hasResumedActivity(callingUid);
+    }
+
+    /**
+     * True if the toast should be blocked. It will return true if all of the following conditions
+     * apply: it's a custom toast, it's not a system toast, the package that sent the toast is in
+     * the background and CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is enabled.
+     *
+     * CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so it will return false for apps
+     * with targetSdk < R. For apps with targetSdk R+, text toasts are not app-rendered, so
+     * isAppRenderedToast == true means it's a custom toast.
+     */
+    private boolean blockToast(int uid, boolean isSystemToast, boolean isAppRenderedToast) {
+        return isAppRenderedToast
+                && !isSystemToast
+                && !isPackageInForegroundForToast(uid)
+                && CompatChanges.isChangeEnabled(CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, uid);
+    }
+
     private void handleRankingReconsideration(Message message) {
         if (!(message.obj instanceof RankingReconsideration)) return;
         RankingReconsideration recon = (RankingReconsideration) message.obj;
@@ -9180,7 +9200,16 @@
         @Override
         protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId)
                 throws IOException {
-            boolean userSet = parser.getAttributeBoolean(null, ATT_USER_SET, false);
+            // TODO: this logic looks broken, since it's trying to convert a
+            // list into a boolean; for now we preserve the old parsing behavior
+            // to avoid a performance regression, but someone should investigate
+            final String value = parser.getAttributeValue(null, ATT_USER_SET);
+            final boolean userSet;
+            if (TextUtils.isEmpty(value)) {
+                userSet = false;
+            } else {
+                userSet = Boolean.parseBoolean(value);
+            }
             setUserSet(userId, userSet);
         }
 
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 3e197fb..f078242 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -462,8 +462,6 @@
     }
 
     private PendingIntent createPendingIntent(String pkg, String key, int userId) {
-        // TODO(b/174969959) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         return PendingIntent.getBroadcast(mContext,
                 REQUEST_CODE_REPOST,
                 new Intent(REPOST_ACTION)
@@ -471,7 +469,7 @@
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                         .putExtra(EXTRA_KEY, key)
                         .putExtra(EXTRA_USER_ID, userId),
-                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
     }
 
     public void scheduleRepostsForPersistedNotifications(long currentTime) {
diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
index 17e0b39..30378ac 100644
--- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
@@ -37,9 +37,10 @@
     public final ITransientNotification callback;
 
     public CustomToastRecord(NotificationManagerService notificationManager, int uid, int pid,
-            String packageName, IBinder token, ITransientNotification callback, int duration,
-            Binder windowToken, int displayId) {
-        super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
+            String packageName, boolean isSystemToast, IBinder token,
+            ITransientNotification callback, int duration, Binder windowToken, int displayId) {
+        super(notificationManager, uid, pid, packageName, isSystemToast, token, duration,
+                windowToken, displayId);
         this.callback = checkNotNull(callback);
     }
 
@@ -78,10 +79,16 @@
     }
 
     @Override
+    public boolean isAppRendered() {
+        return true;
+    }
+
+    @Override
     public String toString() {
         return "CustomToastRecord{"
                 + Integer.toHexString(System.identityHashCode(this))
                 + " " + pid + ":" +  pkg + "/" + UserHandle.formatUid(uid)
+                + " isSystemToast=" + isSystemToast
                 + " token=" + token
                 + " callback=" + callback
                 + " duration=" + getDuration()
diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
index 544520e..7b36db2 100644
--- a/services/core/java/com/android/server/notification/toast/TextToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
@@ -43,9 +43,11 @@
 
     public TextToastRecord(NotificationManagerService notificationManager,
             @Nullable StatusBarManagerInternal statusBarManager, int uid, int pid,
-            String packageName, IBinder token, CharSequence text, int duration, Binder windowToken,
-            int displayId, @Nullable ITransientNotificationCallback callback) {
-        super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
+            String packageName, boolean isSystemToast, IBinder token, CharSequence text,
+            int duration, Binder windowToken, int displayId,
+            @Nullable ITransientNotificationCallback callback) {
+        super(notificationManager, uid, pid, packageName, isSystemToast, token, duration,
+                windowToken, displayId);
         mStatusBar = statusBarManager;
         mCallback = callback;
         this.text = checkNotNull(text);
@@ -73,10 +75,16 @@
     }
 
     @Override
+    public boolean isAppRendered() {
+        return false;
+    }
+
+    @Override
     public String toString() {
         return "TextToastRecord{"
                 + Integer.toHexString(System.identityHashCode(this))
                 + " " + pid + ":" +  pkg + "/" + UserHandle.formatUid(uid)
+                + " isSystemToast=" + isSystemToast
                 + " token=" + token
                 + " text=" + text
                 + " duration=" + getDuration()
diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java
index 33906cc..1d5fc27 100644
--- a/services/core/java/com/android/server/notification/toast/ToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java
@@ -31,6 +31,7 @@
     public final int uid;
     public final int pid;
     public final String pkg;
+    public final boolean isSystemToast;
     public final IBinder token;
     public final int displayId;
     public final Binder windowToken;
@@ -38,11 +39,13 @@
     private int mDuration;
 
     protected ToastRecord(NotificationManagerService notificationManager, int uid, int pid,
-            String pkg, IBinder token, int duration, Binder windowToken, int displayId) {
+            String pkg, boolean isSystemToast, IBinder token, int duration, Binder windowToken,
+            int displayId) {
         this.mNotificationManager = notificationManager;
         this.uid = uid;
         this.pid = pid;
         this.pkg = pkg;
+        this.isSystemToast = isSystemToast;
         this.token = token;
         this.windowToken = windowToken;
         this.displayId = displayId;
@@ -95,4 +98,10 @@
         // should override this method.
         return false;
     }
+
+    /**
+     * Returns true if the app is responsible for rendering the toast, false otherwise (for example,
+     * if it's rendered by the system).
+     */
+    public abstract boolean isAppRendered();
 }
diff --git a/services/core/java/com/android/server/om/OWNERS b/services/core/java/com/android/server/om/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/services/core/java/com/android/server/om/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/services/core/java/com/android/server/people/OWNERS b/services/core/java/com/android/server/people/OWNERS
new file mode 100644
index 0000000..3198a5e
--- /dev/null
+++ b/services/core/java/com/android/server/people/OWNERS
@@ -0,0 +1 @@
+include /services/people/OWNERS
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dac2e4f..094be06 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -55,6 +55,12 @@
 import com.android.server.compat.CompatChange;
 import com.android.server.om.OverlayReferenceMapper;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Snapshots;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.Watcher;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -69,7 +75,7 @@
  * manifests.
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class AppsFilter {
+public class AppsFilter implements Watchable, Snappable {
 
     private static final String TAG = "AppsFilter";
 
@@ -145,6 +151,55 @@
     @GuardedBy("mCacheLock")
     private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;
 
+    /**
+     * A cached snapshot.
+     */
+    private volatile AppsFilter mSnapshot = null;
+
+    /**
+     * Watchable machinery
+     */
+    private final WatchableImpl mWatchable = new WatchableImpl();
+
+    /**
+     * Ensures an observer is in the list, exactly once. The observer cannot be null.  The
+     * function quietly returns if the observer is already in the list.
+     *
+     * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+     */
+    public void registerObserver(@NonNull Watcher observer) {
+        mWatchable.registerObserver(observer);
+    }
+
+    /**
+     * Ensures an observer is not in the list. The observer must not be null.  The function
+     * quietly returns if the objserver is not in the list.
+     *
+     * @param observer The {@link Watcher} that should not be in the notification list.
+     */
+    public void unregisterObserver(@NonNull Watcher observer) {
+        mWatchable.unregisterObserver(observer);
+    }
+
+    /**
+     * Invokes {@link Watcher#onChange} on each registered observer.  The method can be called
+     * with the {@link Watchable} that generated the event.  In a tree of {@link Watchable}s, this
+     * is generally the first (deepest) {@link Watchable} to detect a change.
+     *
+     * @param what The {@link Watchable} that generated the event.
+     */
+    public void dispatchChange(@Nullable Watchable what) {
+        mSnapshot = null;
+        mWatchable.dispatchChange(what);
+    }
+
+    /**
+     * Report a change to observers.
+     */
+    private void onChanged() {
+        dispatchChange(this);
+    }
+
     @VisibleForTesting(visibility = PRIVATE)
     AppsFilter(StateProvider stateProvider,
             FeatureConfig featureConfig,
@@ -162,6 +217,44 @@
     }
 
     /**
+     * The copy constructor is used by PackageManagerService to construct a snapshot.
+     * Attributes are not deep-copied since these are supposed to be immutable.
+     * TODO: deep-copy the attributes, if necessary.
+     */
+    private AppsFilter(AppsFilter orig) {
+        Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
+        Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
+        Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
+        mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
+        mForceQueryable.addAll(orig.mForceQueryable);
+        mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
+        mSystemAppsQueryable = orig.mSystemAppsQueryable;
+        mFeatureConfig = orig.mFeatureConfig;
+        mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
+        mStateProvider = orig.mStateProvider;
+        mSystemSigningDetails = orig.mSystemSigningDetails;
+        mProtectedBroadcasts = orig.mProtectedBroadcasts;
+        mShouldFilterCache = orig.mShouldFilterCache;
+
+        mBackgroundExecutor = null;
+    }
+
+    /**
+     * Return a snapshot.  If the cached snapshot is null, build a new one.  The logic in
+     * the function ensures that this function returns a valid snapshot even if a race
+     * condition causes the cached snapshot to be cleared asynchronously to this method.
+     */
+    public AppsFilter snapshot() {
+        AppsFilter s = mSnapshot;
+        if (s == null) {
+            s = new AppsFilter(this);
+            s.mWatchable.seal();
+            mSnapshot = s;
+        }
+        return s;
+    }
+
+    /**
      * Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
      * the data with the package lock.
      */
@@ -311,6 +404,9 @@
             } else {
                 mDisabledPackages.add(pkg.getPackageName());
             }
+            if (mAppsFilter != null) {
+                mAppsFilter.onChanged();
+            }
         }
 
         @Override
@@ -347,7 +443,7 @@
         }
         final StateProvider stateProvider = command -> {
             synchronized (injector.getLock()) {
-                command.currentState(injector.getSettings().mPackages,
+                command.currentState(injector.getSettings().getPackagesLocked().untrackedMap(),
                         injector.getUserManagerInternal().getUserInfos());
             }
         };
@@ -482,7 +578,8 @@
      */
     public void grantImplicitAccess(int recipientUid, int visibleUid) {
         if (recipientUid != visibleUid) {
-            if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
+            final boolean changed = mImplicitlyQueryable.add(recipientUid, visibleUid);
+            if (changed && DEBUG_LOGGING) {
                 Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
             }
             synchronized (mCacheLock) {
@@ -497,6 +594,9 @@
                     visibleUids.put(visibleUid, false);
                 }
             }
+            if (changed) {
+                onChanged();
+            }
         }
     }
 
@@ -505,6 +605,7 @@
         mFeatureConfig.onSystemReady();
 
         updateEntireShouldFilterCacheAsync();
+        onChanged();
     }
 
     /**
@@ -530,6 +631,7 @@
                 }
             });
         } finally {
+            onChanged();
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
@@ -712,6 +814,7 @@
         synchronized (mCacheLock) {
             if (mShouldFilterCache != null) {
                 updateEntireShouldFilterCache();
+                onChanged();
             }
         }
     }
@@ -870,6 +973,16 @@
     }
 
     /**
+     * This api does type conversion on the <existingSettings> parameter.
+     */
+    @VisibleForTesting(visibility = PRIVATE)
+    @Nullable
+    SparseArray<int[]> getVisibilityAllowList(PackageSetting setting, int[] users,
+            WatchedArrayMap<String, PackageSetting> existingSettings) {
+        return getVisibilityAllowList(setting, users, existingSettings.untrackedMap());
+    }
+
+    /**
      * Equivalent to calling {@link #addPackage(PackageSetting, boolean)} with {@code isReplace}
      * equal to {@code false}.
      * @see AppsFilter#addPackage(PackageSetting, boolean)
@@ -946,6 +1059,7 @@
                                 siblingSetting, settings, users, settings.size());
                     }
                 }
+                onChanged();
             }
         });
     }
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index a234f5a..1d73abc 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 package com.android.server.pm;
-
+import static android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES;
+import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.MANAGE_APP_OPS_MODES;
 import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
 import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
 import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
-import android.Manifest;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -31,7 +34,6 @@
 import android.app.AppOpsManager.Mode;
 import android.app.IApplicationThread;
 import android.app.admin.DevicePolicyEventLogger;
-import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
@@ -154,15 +156,15 @@
             if (callerUserId != userId) {
                 final int permissionFlag =  PermissionChecker.checkPermissionForPreflight(
                         mContext,
-                        android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+                        INTERACT_ACROSS_PROFILES,
                         callingPid,
                         callingUid,
                         callingPackage);
                 if (permissionFlag != PermissionChecker.PERMISSION_GRANTED
                         || !isSameProfileGroup(callerUserId, userId)) {
                     throw new SecurityException("Attempt to launch activity without required "
-                            + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
-                            + " or target user is not in the same profile group.");
+                            + INTERACT_ACROSS_PROFILES
+                            + " permission or target user is not in the same profile group.");
                 }
             }
             launchIntent.setComponent(component);
@@ -217,8 +219,8 @@
         if (callerUserId != userId) {
             if (!hasCallerGotInteractAcrossProfilesPermission(callingPackage)) {
                 throw new SecurityException("Attempt to launch activity without required "
-                        + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
-                        + " or target user is not in the same profile group.");
+                        + INTERACT_ACROSS_PROFILES
+                        + " permission or target user is not in the same profile group.");
             }
         }
 
@@ -294,13 +296,13 @@
                 callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid());
     }
 
-    private boolean isCrossProfilePackageWhitelisted(String packageName) {
+    private boolean isCrossProfilePackageAllowlisted(String packageName) {
         return mInjector.withCleanCallingIdentity(() ->
                 mInjector.getDevicePolicyManagerInternal()
                         .getAllCrossProfilePackages().contains(packageName));
     }
 
-    private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
+    private boolean isCrossProfilePackageAllowlistedByDefault(String packageName) {
         return mInjector.withCleanCallingIdentity(() ->
                 mInjector.getDevicePolicyManagerInternal()
                         .getDefaultCrossProfilePackages().contains(packageName));
@@ -388,32 +390,36 @@
     /**
      * See {@link android.content.pm.CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)}.
      *
-     * <p>Logs metrics. Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, boolean)}
-     * to avoid permission checks or to specify not to log metrics.
+     * <p>Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, int)} to avoid permission
+     * checks.
      */
     @Override
     public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
+        setInteractAcrossProfilesAppOp(packageName, newMode, mInjector.getCallingUserId());
+    }
+
+    private void setInteractAcrossProfilesAppOp(
+            String packageName, @Mode int newMode, @UserIdInt int userId) {
         final int callingUid = mInjector.getCallingUid();
-        if (!isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
-                && !isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)) {
+        if (!isPermissionGranted(INTERACT_ACROSS_USERS_FULL, callingUid)
+                && !isPermissionGranted(INTERACT_ACROSS_USERS, callingUid)) {
             throw new SecurityException(
                     "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL is required to set the"
                             + " app-op for interacting across profiles.");
         }
-        if (!isPermissionGranted(Manifest.permission.MANAGE_APP_OPS_MODES, callingUid)
-                && !isPermissionGranted(
-                        Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
+        if (!isPermissionGranted(MANAGE_APP_OPS_MODES, callingUid)
+                && !isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
             throw new SecurityException(
                     "MANAGE_APP_OPS_MODES or CONFIGURE_INTERACT_ACROSS_PROFILES is required to set"
                             + " the app-op for interacting across profiles.");
         }
-        setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, /* logMetrics= */ true);
+        setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, userId);
     }
 
     private void setInteractAcrossProfilesAppOpUnchecked(
-            String packageName, @Mode int newMode, boolean logMetrics) {
+            String packageName, @Mode int newMode, @UserIdInt int userId) {
         if (newMode == AppOpsManager.MODE_ALLOWED
-                && !canConfigureInteractAcrossProfiles(packageName)) {
+                && !canConfigureInteractAcrossProfiles(packageName, userId)) {
             // The user should not be prompted for apps that cannot request to interact across
             // profiles. However, we return early here if required to avoid race conditions.
             Slog.e(TAG, "Tried to turn on the appop for interacting across profiles for invalid"
@@ -421,56 +427,57 @@
             return;
         }
         final int[] profileIds =
-                mInjector.getUserManager()
-                        .getProfileIds(mInjector.getCallingUserId(), /* enabledOnly= */ false);
+                mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
         for (int profileId : profileIds) {
             if (!isPackageInstalled(packageName, profileId)) {
                 continue;
             }
-            setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId, logMetrics);
+            // Only log once per profile group by checking against the user ID.
+            setInteractAcrossProfilesAppOpForProfile(
+                    packageName, newMode, profileId, /* logMetrics= */ profileId == userId);
         }
     }
 
+    /**
+     * Returns whether the given package name is installed in the given user ID. The calling UID is
+     * used as the filter calling UID, as described at {@link PackageManagerInternal#getPackageInfo(
+     * String, int, int, int)}.
+     */
     private boolean isPackageInstalled(String packageName, @UserIdInt int userId) {
-        final int callingUid = mInjector.getCallingUid();
         return mInjector.withCleanCallingIdentity(() -> {
+            final int flags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             final PackageInfo info =
                     mInjector.getPackageManagerInternal()
-                            .getPackageInfo(
-                                    packageName,
-                                    MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                                    callingUid,
-                                    userId);
+                            .getPackageInfo(packageName, flags, mInjector.getCallingUid(), userId);
             return info != null;
         });
     }
 
-    private void setInteractAcrossProfilesAppOpForUser(
-            String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) {
+    private void setInteractAcrossProfilesAppOpForProfile(
+            String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics) {
         try {
-            setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId, logMetrics);
+            setInteractAcrossProfilesAppOpForProfileOrThrow(
+                    packageName, newMode, profileId, logMetrics);
         } catch (PackageManager.NameNotFoundException e) {
-            Slog.e(TAG, "Missing package " + packageName + " on user ID " + userId, e);
+            Slog.e(TAG, "Missing package " + packageName + " on profile user ID " + profileId, e);
         }
     }
 
-    private void setInteractAcrossProfilesAppOpForUserOrThrow(
-            String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics)
+    private void setInteractAcrossProfilesAppOpForProfileOrThrow(
+            String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics)
             throws PackageManager.NameNotFoundException {
         final int uid = mInjector.getPackageManager()
-                .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
+                .getPackageUidAsUser(packageName, /* flags= */ 0, profileId);
         if (currentModeEquals(newMode, packageName, uid)) {
             Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for "
-                    + packageName + " on user ID " + userId);
+                    + packageName + " on profile user ID " + profileId);
             return;
         }
 
         final boolean hadPermission = hasInteractAcrossProfilesPermission(
                 packageName, uid, PermissionChecker.PID_UNKNOWN);
 
-        final int callingUid = mInjector.getCallingUid();
-        if (isPermissionGranted(
-                Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
+        if (isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, mInjector.getCallingUid())) {
             // Clear calling identity since the CONFIGURE_INTERACT_ACROSS_PROFILES permission allows
             // this particular app-op to be modified without the broader app-op permissions.
             mInjector.withCleanCallingIdentity(() ->
@@ -483,16 +490,15 @@
         // Kill the UID before sending the broadcast to ensure that apps can be informed when
         // their app-op has been revoked.
         maybeKillUid(packageName, uid, hadPermission);
-        sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
-        maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
+        sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId));
+        maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid);
     }
 
     /**
      * Kills the process represented by the given UID if it has lost the permission to
      * interact across profiles.
      */
-    private void maybeKillUid(
-            String packageName, int uid, boolean hadPermission) {
+    private void maybeKillUid(String packageName, int uid, boolean hadPermission) {
         if (!hadPermission) {
             return;
         }
@@ -503,18 +509,10 @@
     }
 
     private void maybeLogSetInteractAcrossProfilesAppOp(
-            String packageName,
-            @Mode int newMode,
-            @UserIdInt int userId,
-            boolean logMetrics,
-            int uid) {
+            String packageName, @Mode int newMode, boolean logMetrics, int uid) {
         if (!logMetrics) {
             return;
         }
-        if (userId != mInjector.getCallingUserId()) {
-            // Only log once per profile group by checking for the calling user ID.
-            return;
-        }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP)
                 .setStrings(packageName)
@@ -529,8 +527,7 @@
      * any necessary permission checks.
      */
     private boolean currentModeEquals(@Mode int otherMode, String packageName, int uid) {
-        final String op =
-                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
+        final String op = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
         return mInjector.withCleanCallingIdentity(() -> otherMode
                 == mInjector.getAppOpsManager().unsafeCheckOpNoThrow(op, uid, packageName));
     }
@@ -562,37 +559,49 @@
 
     @Override
     public boolean canConfigureInteractAcrossProfiles(String packageName) {
-        if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
+        return canConfigureInteractAcrossProfiles(packageName, mInjector.getCallingUserId());
+    }
+
+    private boolean canConfigureInteractAcrossProfiles(String packageName, @UserIdInt int userId) {
+        if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName, userId)) {
             return false;
         }
-        if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
+        if (!hasOtherProfileWithPackageInstalled(packageName, userId)) {
             return false;
         }
         if (!hasRequestedAppOpPermission(
                 AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
             return false;
         }
-        return isCrossProfilePackageWhitelisted(packageName);
+        return isCrossProfilePackageAllowlisted(packageName);
     }
 
     @Override
     public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
-        final int[] profileIds = mInjector.getUserManager().getProfileIds(
-                mInjector.getCallingUserId(), /* enabledOnly= */ false);
+        return canUserAttemptToConfigureInteractAcrossProfiles(
+                packageName, mInjector.getCallingUserId());
+    }
+
+    private boolean canUserAttemptToConfigureInteractAcrossProfiles(
+            String packageName, @UserIdInt int userId) {
+        final int[] profileIds =
+                mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
         if (profileIds.length < 2) {
             return false;
         }
         if (isProfileOwner(packageName, profileIds)) {
             return false;
         }
-        return hasRequestedAppOpPermission(
-                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
-                && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
+        if (!hasRequestedAppOpPermission(
+                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
+            return false;
+        }
+        return !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
     }
 
     private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
             String packageName, int[] profileIds) {
-        return !isCrossProfilePackageWhitelistedByDefault(packageName)
+        return !isCrossProfilePackageAllowlistedByDefault(packageName)
                 && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
     }
 
@@ -610,7 +619,7 @@
             if (uid == -1) {
                 continue;
             }
-            if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
+            if (isPermissionGranted(INTERACT_ACROSS_PROFILES, uid)) {
                 return true;
             }
         }
@@ -642,7 +651,7 @@
             return;
         }
         final String op =
-                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
+                AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
         setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
     }
 
@@ -650,7 +659,7 @@
     public void clearInteractAcrossProfilesAppOps() {
         final int defaultMode =
                 AppOpsManager.opToDefaultMode(
-                        AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES));
+                        AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES));
         findAllPackageNames()
                 .forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode));
     }
@@ -695,17 +704,13 @@
     }
 
     private boolean hasInteractAcrossProfilesPermission(String packageName, int uid, int pid) {
-        if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
-                || isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)) {
+        if (isPermissionGranted(INTERACT_ACROSS_USERS_FULL, uid)
+                || isPermissionGranted(INTERACT_ACROSS_USERS, uid)) {
             return true;
         }
         return PermissionChecker.PERMISSION_GRANTED
                 == PermissionChecker.checkPermissionForPreflight(
-                        mContext,
-                        Manifest.permission.INTERACT_ACROSS_PROFILES,
-                        pid,
-                        uid,
-                        packageName);
+                        mContext, INTERACT_ACROSS_PROFILES, pid, uid, packageName);
     }
 
     private boolean isProfileOwner(String packageName, int[] userIds) {
@@ -898,5 +903,12 @@
         public List<UserHandle> getTargetUserProfiles(String packageName, int userId) {
             return getTargetUserProfilesUnchecked(packageName, userId);
         }
+
+        @Override
+        public void setInteractAcrossProfilesAppOp(
+                String packageName, int newMode, @UserIdInt int userId) {
+            CrossProfileAppsServiceImpl.this.setInteractAcrossProfilesAppOpUnchecked(
+                    packageName, newMode, userId);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index 8e6b89a..bf7f466 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -14,21 +14,22 @@
  * limitations under the License.
  */
 
-
 package com.android.server.pm;
 
-
 import android.annotation.NonNull;
 import android.content.IntentFilter;
 
-import com.android.server.IntentResolver;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
+
 import java.util.List;
 
 /**
  * Used to find a list of {@link CrossProfileIntentFilter}s that match an intent.
  */
 class CrossProfileIntentResolver
-        extends IntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter> {
+        extends WatchableIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
+        implements Snappable {
     @Override
     protected CrossProfileIntentFilter[] newArray(int size) {
         return new CrossProfileIntentFilter[size];
@@ -48,4 +49,15 @@
     protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) {
         return input;
     }
+
+    /**
+     * Return a snapshot of the current object.  The snapshot is a read-only copy suitable
+     * for read-only methods.
+     * @return A snapshot of the current object.
+     */
+    public CrossProfileIntentResolver snapshot() {
+        CrossProfileIntentResolver result = new CrossProfileIntentResolver();
+        result.doCopy(this);
+        return result;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index a09640d..69d3e5c 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -24,6 +24,7 @@
 import android.content.pm.InstantAppInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.content.pm.PermissionInfo;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -36,13 +37,13 @@
 import android.os.Message;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.PackageUtils;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 import android.util.TypedXmlPullParser;
 import android.util.TypedXmlSerializer;
 import android.util.Xml;
@@ -55,20 +56,23 @@
 import com.android.server.pm.parsing.PackageInfoUtils;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.WatchedSparseBooleanArray;
+import com.android.server.utils.Watcher;
 
 import libcore.io.IoUtils;
 import libcore.util.HexEncoding;
 
-import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
@@ -82,7 +86,7 @@
  * pruning installed instant apps and meta-data for uninstalled instant apps
  * when free space is needed.
  */
-class InstantAppRegistry {
+class InstantAppRegistry implements Watchable, Snappable {
     private static final boolean DEBUG = false;
 
     private static final String LOG_TAG = "InstantAppRegistry";
@@ -120,7 +124,7 @@
 
     /** State for uninstalled instant apps */
     @GuardedBy("mService.mLock")
-    private SparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;
+    private final WatchedSparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;
 
     /**
      * Automatic grants for access to instant app metadata.
@@ -129,17 +133,90 @@
      * UserID -> TargetAppId -> InstantAppId
      */
     @GuardedBy("mService.mLock")
-    private SparseArray<SparseArray<SparseBooleanArray>> mInstantGrants;
+    private final WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>> mInstantGrants;
 
     /** The set of all installed instant apps. UserID -> AppID */
     @GuardedBy("mService.mLock")
-    private SparseArray<SparseBooleanArray> mInstalledInstantAppUids;
+    private final WatchedSparseArray<WatchedSparseBooleanArray> mInstalledInstantAppUids;
+
+    /**
+     * The cached snapshot
+     */
+    private volatile InstantAppRegistry mSnapshot = null;
+
+    /**
+     * Watchable machinery
+     */
+    private final WatchableImpl mWatchable = new WatchableImpl();
+    public void registerObserver(@NonNull Watcher observer) {
+        mWatchable.registerObserver(observer);
+    }
+    public void unregisterObserver(@NonNull Watcher observer) {
+        mWatchable.unregisterObserver(observer);
+    }
+    public void dispatchChange(@Nullable Watchable what) {
+        mSnapshot = null;
+        mWatchable.dispatchChange(what);
+    }
+    /**
+     * Notify listeners that this object has changed.
+     */
+    private void onChanged() {
+        dispatchChange(this);
+    }
+
+    /** The list of observers */
+    private final Watcher mObserver = new Watcher() {
+            @Override
+            public void onChange(@Nullable Watchable what) {
+                InstantAppRegistry.this.onChanged();
+            }
+        };
 
     public InstantAppRegistry(PackageManagerService service,
             PermissionManagerServiceInternal permissionManager) {
         mService = service;
         mPermissionManager = permissionManager;
         mCookiePersistence = new CookiePersistence(BackgroundThread.getHandler().getLooper());
+
+        mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>();
+        mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>();
+        mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>();
+
+        mUninstalledInstantApps.registerObserver(mObserver);
+        mInstantGrants.registerObserver(mObserver);
+        mInstalledInstantAppUids.registerObserver(mObserver);
+    }
+
+    /**
+     * The copy constructor is used by PackageManagerService to construct a snapshot.
+     */
+    private InstantAppRegistry(InstantAppRegistry r) {
+        mService = r.mService;
+        mPermissionManager = r.mPermissionManager;
+        mCookiePersistence = null;
+
+        mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>(
+            r.mUninstalledInstantApps);
+        mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>(
+            r.mInstantGrants);
+        mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>(
+            r.mInstalledInstantAppUids);
+
+        // Do not register any observers.  This is a clone
+    }
+
+    /**
+     * Return a snapshot: the value is the cached snapshot if available.
+     */
+    public InstantAppRegistry snapshot() {
+        InstantAppRegistry s = mSnapshot;
+        if (s == null) {
+            s = new InstantAppRegistry(this);
+            s.mWatchable.seal();
+            mSnapshot = s;
+        }
+        return s;
     }
 
     @GuardedBy("mService.mLock")
@@ -370,37 +447,20 @@
 
     @GuardedBy("mService.mLock")
     public void onUserRemovedLPw(int userId) {
-        if (mUninstalledInstantApps != null) {
-            mUninstalledInstantApps.remove(userId);
-            if (mUninstalledInstantApps.size() <= 0) {
-                mUninstalledInstantApps = null;
-            }
-        }
-        if (mInstalledInstantAppUids != null) {
-            mInstalledInstantAppUids.remove(userId);
-            if (mInstalledInstantAppUids.size() <= 0) {
-                mInstalledInstantAppUids = null;
-            }
-        }
-        if (mInstantGrants != null) {
-            mInstantGrants.remove(userId);
-            if (mInstantGrants.size() <= 0) {
-                mInstantGrants = null;
-            }
-        }
+        mUninstalledInstantApps.remove(userId);
+        mInstalledInstantAppUids.remove(userId);
+        mInstantGrants.remove(userId);
         deleteDir(getInstantApplicationsDir(userId));
     }
 
     public boolean isInstantAccessGranted(@UserIdInt int userId, int targetAppId,
             int instantAppId) {
-        if (mInstantGrants == null) {
-            return false;
-        }
-        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+        final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+                mInstantGrants.get(userId);
         if (targetAppList == null) {
             return false;
         }
-        final SparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
+        final WatchedSparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
         if (instantGrantList == null) {
             return false;
         }
@@ -413,7 +473,7 @@
         if (mInstalledInstantAppUids == null) {
             return;     // no instant apps installed; no need to grant
         }
-        SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+        WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
         if (instantAppList == null || !instantAppList.get(instantAppId)) {
             return;     // instant app id isn't installed; no need to grant
         }
@@ -426,17 +486,14 @@
                 return;  // launched via VIEW/BROWSABLE intent; no need to grant
             }
         }
-        if (mInstantGrants == null) {
-            mInstantGrants = new SparseArray<>();
-        }
-        SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+        WatchedSparseArray<WatchedSparseBooleanArray> targetAppList = mInstantGrants.get(userId);
         if (targetAppList == null) {
-            targetAppList = new SparseArray<>();
+            targetAppList = new WatchedSparseArray<>();
             mInstantGrants.put(userId, targetAppList);
         }
-        SparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
+        WatchedSparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
         if (instantGrantList == null) {
-            instantGrantList = new SparseBooleanArray();
+            instantGrantList = new WatchedSparseBooleanArray();
             targetAppList.put(recipientUid, instantGrantList);
         }
         instantGrantList.put(instantAppId, true /*granted*/);
@@ -444,15 +501,13 @@
 
     @GuardedBy("mService.mLock")
     public void addInstantAppLPw(@UserIdInt int userId, int instantAppId) {
-        if (mInstalledInstantAppUids == null) {
-            mInstalledInstantAppUids = new SparseArray<>();
-        }
-        SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+        WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
         if (instantAppList == null) {
-            instantAppList = new SparseBooleanArray();
+            instantAppList = new WatchedSparseBooleanArray();
             mInstalledInstantAppUids.put(userId, instantAppList);
         }
         instantAppList.put(instantAppId, true /*installed*/);
+        onChanged();
     }
 
     @GuardedBy("mService.mLock")
@@ -461,23 +516,28 @@
         if (mInstalledInstantAppUids == null) {
             return; // no instant apps on the system
         }
-        final SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+        final WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
         if (instantAppList == null) {
             return;
         }
 
-        instantAppList.delete(instantAppId);
+        try {
+            instantAppList.delete(instantAppId);
 
-        // remove any grants
-        if (mInstantGrants == null) {
-            return; // no grants on the system
-        }
-        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
-        if (targetAppList == null) {
-            return; // no grants for this user
-        }
-        for (int i = targetAppList.size() - 1; i >= 0; --i) {
-            targetAppList.valueAt(i).delete(instantAppId);
+            // remove any grants
+            if (mInstantGrants == null) {
+                return; // no grants on the system
+            }
+            final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+                    mInstantGrants.get(userId);
+            if (targetAppList == null) {
+                return; // no grants for this user
+            }
+            for (int i = targetAppList.size() - 1; i >= 0; --i) {
+                targetAppList.valueAt(i).delete(instantAppId);
+            }
+        } finally {
+            onChanged();
         }
     }
 
@@ -487,11 +547,13 @@
         if (mInstantGrants == null) {
             return; // no grants on the system
         }
-        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+        final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+                mInstantGrants.get(userId);
         if (targetAppList == null) {
             return; // no grants for this user
         }
         targetAppList.delete(targetAppId);
+        onChanged();
     }
 
     @GuardedBy("mService.mLock")
@@ -502,9 +564,6 @@
         if (uninstalledApp == null) {
             return;
         }
-        if (mUninstalledInstantApps == null) {
-            mUninstalledInstantApps = new SparseArray<>();
-        }
         List<UninstalledInstantAppState> uninstalledAppStates =
                 mUninstalledInstantApps.get(userId);
         if (uninstalledAppStates == null) {
@@ -593,9 +652,7 @@
             uninstalledAppStates.remove(i);
             if (uninstalledAppStates.isEmpty()) {
                 mUninstalledInstantApps.remove(userId);
-                if (mUninstalledInstantApps.size() <= 0) {
-                    mUninstalledInstantApps = null;
-                }
+                onChanged();
                 return;
             }
         }
@@ -919,8 +976,7 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             for (String grantedPermission : appInfo.getGrantedPermissions()) {
-                final boolean propagatePermission =
-                        mPermissionManager.canPropagatePermissionToInstantApp(grantedPermission);
+                final boolean propagatePermission = canPropagatePermission(grantedPermission);
                 if (propagatePermission && pkg.getRequestedPermissions().contains(
                         grantedPermission)) {
                     mService.grantRuntimePermission(pkg.getPackageName(), grantedPermission,
@@ -932,6 +988,19 @@
         }
     }
 
+    private boolean canPropagatePermission(@NonNull String permissionName) {
+        final PermissionManager permissionManager = mService.mContext.getSystemService(
+                PermissionManager.class);
+        final PermissionInfo permissionInfo = permissionManager.getPermissionInfo(permissionName,
+                0);
+        return permissionInfo != null
+                && (permissionInfo.getProtection() == PermissionInfo.PROTECTION_DANGEROUS
+                        || (permissionInfo.getProtectionFlags()
+                                & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0)
+                && (permissionInfo.getProtectionFlags() & PermissionInfo.PROTECTION_FLAG_INSTANT)
+                        != 0;
+    }
+
     private @NonNull
     InstantAppInfo peekOrParseUninstalledInstantAppInfo(
             @NonNull String packageName, @UserIdInt int userId) {
@@ -994,12 +1063,7 @@
             }
         }
 
-        if (uninstalledAppStates != null) {
-            if (mUninstalledInstantApps == null) {
-                mUninstalledInstantApps = new SparseArray<>();
-            }
-            mUninstalledInstantApps.put(userId, uninstalledAppStates);
-        }
+        mUninstalledInstantApps.put(userId, uninstalledAppStates);
 
         return uninstalledAppStates;
     }
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index cca2b83..004259b 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -30,9 +30,10 @@
 per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com
 per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com
 per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com
+per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com
+per-file UserManagerInternal.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
 per-file UserManagerService.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
 per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com
-per-file RestrictionsSet.java = bookatz@google.com, omakoto@google.com, yamasani@google.com, rubinxu@google.com, sandness@google.com
 per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
 per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
 per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com
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 34bee95..2d393c0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -291,23 +291,23 @@
     }
 
     void restoreAndApplyStagedSessionIfNeeded() {
-        List<PackageInstallerSession> stagedSessionsToRestore = new ArrayList<>();
+        List<StagingManager.StagedSession> stagedSessionsToRestore = new ArrayList<>();
         synchronized (mSessions) {
             for (int i = 0; i < mSessions.size(); i++) {
                 final PackageInstallerSession session = mSessions.valueAt(i);
                 if (session.isStaged()) {
-                    stagedSessionsToRestore.add(session);
+                    stagedSessionsToRestore.add(session.mStagedSession);
                 }
             }
         }
         // Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
         // atomic install which needs to query sessions, which requires lock on mSessions.
         boolean isDeviceUpgrading = mPm.isDeviceUpgrading();
-        for (PackageInstallerSession session : stagedSessionsToRestore) {
-            if (!session.isStagedAndInTerminalState() && session.hasParentSessionId()
+        for (StagingManager.StagedSession session : stagedSessionsToRestore) {
+            if (!session.isInTerminalState() && session.hasParentSessionId()
                     && getSession(session.getParentSessionId()) == null) {
-                session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
-                        "An orphan staged session " + session.sessionId + " is found, "
+                session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+                        "An orphan staged session " + session.sessionId() + " is found, "
                                 + "parent " + session.getParentSessionId() + " is missing");
             }
             mStagingManager.restoreSession(session, isDeviceUpgrading);
@@ -532,6 +532,20 @@
                     + "to use a data loader");
         }
 
+        // INSTALL_REASON_ROLLBACK allows an app to be rolled back without requiring the ROLLBACK
+        // capability; ensure if this is set as the install reason the app has one of the necessary
+        // signature permissions to perform the rollback.
+        if (params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+            if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)
+                    != PackageManager.PERMISSION_GRANTED &&
+                    mContext.checkCallingOrSelfPermission(Manifest.permission.TEST_MANAGE_ROLLBACKS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException(
+                        "INSTALL_REASON_ROLLBACK requires the MANAGE_ROLLBACKS permission or the "
+                                + "TEST_MANAGE_ROLLBACKS permission");
+            }
+        }
+
         // App package name and label length is restricted so that really long strings aren't
         // written to disk.
         if (params.appPackageName != null
@@ -733,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) {
@@ -1385,7 +1399,7 @@
                 @Override
                 public void run() {
                     if (session.isStaged() && !success) {
-                        mStagingManager.abortSession(session);
+                        mStagingManager.abortSession(session.mStagedSession);
                     }
                     synchronized (mSessions) {
                         if (!session.isStaged() || !success) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4ab1282..f97a5ee 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;
 
@@ -422,30 +429,341 @@
     @GuardedBy("mLock")
     private ArrayMap<String, List<CertifiedChecksum>> mChecksums = new ArrayMap<>();
 
-    @GuardedBy("mLock")
-    private boolean mStagedSessionApplied;
-    @GuardedBy("mLock")
-    private boolean mStagedSessionReady;
-    @GuardedBy("mLock")
-    private boolean mStagedSessionFailed;
-    @GuardedBy("mLock")
-    private int mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
-    @GuardedBy("mLock")
-    private String mStagedSessionErrorMessage;
-
-    /**
-     * The callback to run when pre-reboot verification has ended. Used by {@link #abandonStaged()}
-     * to delay session clean-up until it is safe to do so.
-     */
-    @GuardedBy("mLock")
     @Nullable
-    private Runnable mPendingAbandonCallback;
-    /**
-     * {@code true} if pre-reboot verification is ongoing which means it is not safe for
-     * {@link #abandon()} to clean up staging directories.
-     */
-    @GuardedBy("mLock")
-    private boolean mInPreRebootVerification;
+    final StagedSession mStagedSession;
+
+    @VisibleForTesting
+    public class StagedSession implements StagingManager.StagedSession {
+        @GuardedBy("mLock")
+        private boolean mSessionApplied;
+        @GuardedBy("mLock")
+        private boolean mSessionReady;
+        @GuardedBy("mLock")
+        private boolean mSessionFailed;
+        @GuardedBy("mLock")
+        private int mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+        @GuardedBy("mLock")
+        private String mSessionErrorMessage;
+
+        /**
+         * The callback to run when pre-reboot verification has ended. Used by {@link #abandon()}
+         * to delay session clean-up until it is safe to do so.
+         */
+        @GuardedBy("mLock")
+        @Nullable
+        private Runnable mPendingAbandonCallback;
+        /**
+         * {@code true} if pre-reboot verification is ongoing which means it is not safe for
+         * {@link #abandon()} to clean up staging directories.
+         */
+        @GuardedBy("mLock")
+        private boolean mInPreRebootVerification;
+
+        StagedSession(boolean isReady, boolean isApplied, boolean isFailed, int errorCode,
+                String errorMessage) {
+            mSessionReady = isReady;
+            mSessionApplied = isApplied;
+            mSessionFailed = isFailed;
+            mSessionErrorCode = errorCode;
+            mSessionErrorMessage = errorMessage != null ? errorMessage : "";
+        }
+
+        @Override
+        public List<StagingManager.StagedSession> getChildSessions() {
+            if (!params.isMultiPackage) {
+                return Collections.EMPTY_LIST;
+            }
+            synchronized (mLock) {
+                int size = mChildSessions.size();
+                List<StagingManager.StagedSession> childSessions = new ArrayList<>(size);
+                for (int i = 0; i < size; ++i) {
+                    childSessions.add(mChildSessions.valueAt(i).mStagedSession);
+                }
+                return childSessions;
+            }
+        }
+
+        @Override
+        public SessionParams sessionParams() {
+            return params;
+        }
+
+        @Override
+        public boolean isMultiPackage() {
+            return params.isMultiPackage;
+        }
+
+        @Override
+        public boolean isApexSession() {
+            return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
+        }
+
+        @Override
+        public int sessionId() {
+            return sessionId;
+        }
+
+        @Override
+        public boolean containsApexSession() {
+            return sessionContains((s) -> s.isApexSession());
+        }
+
+        @Override
+        public String getPackageName() {
+            return PackageInstallerSession.this.getPackageName();
+        }
+
+        @Override
+        public void setSessionReady() {
+            synchronized (mLock) {
+                // Do not allow destroyed/failed staged session to change state
+                if (mDestroyed || mSessionFailed) return;
+                mSessionReady = true;
+                mSessionApplied = false;
+                mSessionFailed = false;
+                mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+                mSessionErrorMessage = "";
+            }
+            mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+        }
+
+        @Override
+        public void setSessionFailed(int errorCode, String errorMessage) {
+            List<PackageInstallerSession> childSessions;
+            synchronized (mLock) {
+                // Do not allow destroyed/failed staged session to change state
+                if (mDestroyed || mSessionFailed) return;
+                mSessionReady = false;
+                mSessionApplied = false;
+                mSessionFailed = true;
+                mSessionErrorCode = errorCode;
+                mSessionErrorMessage = errorMessage;
+                Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
+                childSessions = getChildSessionsLocked();
+            }
+            cleanStageDir(childSessions);
+            mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+        }
+
+        @Override
+        public void setSessionApplied() {
+            List<PackageInstallerSession> childSessions;
+            synchronized (mLock) {
+                // Do not allow destroyed/failed staged session to change state
+                if (mDestroyed || mSessionFailed) return;
+                mSessionReady = false;
+                mSessionApplied = true;
+                mSessionFailed = false;
+                mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+                mSessionErrorMessage = "";
+                Slog.d(TAG, "Marking session " + sessionId + " as applied");
+                childSessions = getChildSessionsLocked();
+            }
+            cleanStageDir(childSessions);
+            mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+        }
+
+        @Override
+        public boolean containsApkSession() {
+            return PackageInstallerSession.this.containsApkSession();
+        }
+
+        /**
+         * Installs apks of staged session while skipping the verification process for a committed
+         * and ready session.
+         */
+        @Override
+        public void installSession(IntentSender statusReceiver) {
+            assertCallerIsOwnerOrRootOrSystemLocked();
+            assertNotChildLocked("StagedSession#installSession");
+            Preconditions.checkArgument(isCommitted() && isSessionReady());
+
+            // Since staged sessions are installed during boot, the original reference to status
+            // receiver from the owner has already been lost. We can safely replace it with a
+            // status receiver from the system without effecting the flow.
+            updateRemoteStatusReceiver(statusReceiver);
+            install();
+        }
+
+        private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
+            synchronized (mLock) {
+                mRemoteStatusReceiver = remoteStatusReceiver;
+                if (isMultiPackage()) {
+                    final IntentSender childIntentSender = new ChildStatusIntentReceiver(
+                            mChildSessions.clone(), remoteStatusReceiver).getIntentSender();
+                    for (int i = mChildSessions.size() - 1; i >= 0; --i) {
+                        mChildSessions.valueAt(i).mRemoteStatusReceiver = childIntentSender;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean hasParentSessionId() {
+            return PackageInstallerSession.this.hasParentSessionId();
+        }
+
+        @Override
+        public int getParentSessionId() {
+            return PackageInstallerSession.this.getParentSessionId();
+        }
+
+        @Override
+        public boolean isCommitted() {
+            return PackageInstallerSession.this.isCommitted();
+        }
+
+        @Override
+        public boolean isInTerminalState() {
+            synchronized (mLock) {
+                return mSessionApplied || mSessionFailed;
+            }
+        }
+
+        @Override
+        public boolean isDestroyed() {
+            return PackageInstallerSession.this.isDestroyed();
+        }
+
+        @Override
+        public long getCommittedMillis() {
+            return PackageInstallerSession.this.getCommittedMillis();
+        }
+
+        @Override
+        public boolean sessionContains(Predicate<StagingManager.StagedSession> filter) {
+            return PackageInstallerSession.this.sessionContains(s -> filter.test(s.mStagedSession));
+        }
+
+        @Override
+        public boolean isSessionReady() {
+            synchronized (mLock) {
+                return mSessionReady;
+            }
+        }
+
+        @Override
+        public boolean isSessionApplied() {
+            synchronized (mLock) {
+                return mSessionApplied;
+            }
+        }
+
+        @Override
+        public boolean isSessionFailed() {
+            synchronized (mLock) {
+                return mSessionFailed;
+            }
+        }
+
+        @StagedSessionErrorCode int getSessionErrorCode() {
+            synchronized (mLock) {
+                return mSessionErrorCode;
+            }
+        }
+
+        String getSessionErrorMessage() {
+            synchronized (mLock) {
+                return mSessionErrorMessage;
+            }
+        }
+
+        @Override
+        public void abandon() {
+            final Runnable r;
+            synchronized (mLock) {
+                assertNotChildLocked("StagedSession#abandon");
+                assertCallerIsOwnerOrRootLocked();
+                if (isInTerminalState()) {
+                    // We keep the session in the database if it's in a finalized state. It will be
+                    // removed by PackageInstallerService when the last update time is old enough.
+                    // Also, in such cases cleanStageDir() has already been executed so no need to
+                    // do it now.
+                    return;
+                }
+                mDestroyed = true;
+                boolean isCommitted = mCommitted;
+                List<PackageInstallerSession> childSessions = getChildSessionsLocked();
+                r = () -> {
+                    assertNotLocked("abandonStaged");
+                    if (isCommitted) {
+                        mStagingManager.abortCommittedSession(this);
+                    }
+                    cleanStageDir(childSessions);
+                    destroyInternal();
+                    dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+                    maybeCleanUpChildSessions();
+                };
+                if (mInPreRebootVerification) {
+                    // Pre-reboot verification is ongoing, not safe to clean up the session yet.
+                    mPendingAbandonCallback = r;
+                    mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+                    return;
+                }
+            }
+            r.run();
+        }
+
+        /**
+         * Notified by the staging manager that pre-reboot verification is about to start. The
+         * return value should be checked to decide whether it is OK to start pre-reboot
+         * verification. In the case of a destroyed session, {@code false} is returned and there is
+         * no need to start pre-reboot verification.
+         */
+        @Override
+        public boolean notifyStartPreRebootVerification() {
+            synchronized (mLock) {
+                if (mInPreRebootVerification) {
+                    throw new IllegalStateException("Pre-reboot verification has started");
+                }
+                if (mDestroyed) {
+                    return false;
+                }
+                mInPreRebootVerification = true;
+                return true;
+            }
+        }
+
+        /**
+         * Notified by the staging manager that pre-reboot verification has ended. Now it is safe to
+         * clean up the session if {@link #abandon()} has been called previously.
+         */
+        @Override
+        public void notifyEndPreRebootVerification() {
+            synchronized (mLock) {
+                if (!mInPreRebootVerification) {
+                    throw new IllegalStateException("Pre-reboot verification not started");
+                }
+                mInPreRebootVerification = false;
+            }
+            dispatchPendingAbandonCallback();
+        }
+
+        /**
+         * Resumes verification process for non-final committed staged session.
+         *
+         * Useful if a device gets rebooted before verification is complete and we need to restart
+         * the verification.
+         */
+        @Override
+        public void verifySession() {
+            assertCallerIsOwnerOrRootOrSystemLocked();
+            Preconditions.checkArgument(isCommitted());
+            Preconditions.checkArgument(!mSessionApplied && !mSessionFailed);
+            verify();
+        }
+
+        private void dispatchPendingAbandonCallback() {
+            final Runnable callback;
+            synchronized (mLock) {
+                callback = mPendingAbandonCallback;
+                mPendingAbandonCallback = null;
+            }
+            if (callback != null) {
+                callback.run();
+            }
+        }
+    }
 
     /**
      * Path to the validated base APK for this session, which may point at an
@@ -625,7 +943,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 +966,7 @@
         this.params = params;
         this.createdMillis = createdMillis;
         this.updatedMillis = createdMillis;
+        this.committedMillis = committedMillis;
         this.stageDir = stageDir;
         this.stageCid = stageCid;
         this.mShouldBeSealed = sealed;
@@ -683,12 +1002,8 @@
         mPrepared = prepared;
         mCommitted = committed;
         mDestroyed = destroyed;
-        mStagedSessionReady = isReady;
-        mStagedSessionFailed = isFailed;
-        mStagedSessionApplied = isApplied;
-        mStagedSessionErrorCode = stagedSessionErrorCode;
-        mStagedSessionErrorMessage =
-                stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
+        mStagedSession = params.isStaged ? new StagedSession(isReady, isApplied, isFailed,
+                stagedSessionErrorCode, stagedSessionErrorMessage) : null;
 
         if (isDataLoaderInstallation()) {
             if (isApexSession()) {
@@ -781,10 +1096,11 @@
             info.rollbackDataPolicy = params.rollbackDataPolicy;
             info.parentSessionId = mParentSessionId;
             info.childSessionIds = getChildSessionIdsLocked();
-            info.isStagedSessionApplied = mStagedSessionApplied;
-            info.isStagedSessionReady = mStagedSessionReady;
-            info.isStagedSessionFailed = mStagedSessionFailed;
-            info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
+            info.isStagedSessionApplied = isStagedSessionApplied();
+            info.isStagedSessionReady = isStagedSessionReady();
+            info.isStagedSessionFailed = isStagedSessionFailed();
+            info.setStagedSessionErrorCode(getStagedSessionErrorCode(),
+                    getStagedSessionErrorMessage());
             info.createdMillis = createdMillis;
             info.updatedMillis = updatedMillis;
         }
@@ -819,9 +1135,7 @@
 
     /** Returns true if a staged session has reached a final state and can be forgotten about  */
     public boolean isStagedAndInTerminalState() {
-        synchronized (mLock) {
-            return params.isStaged && (mStagedSessionApplied || mStagedSessionFailed);
-        }
+        return params.isStaged && mStagedSession.isInTerminalState();
     }
 
     private void assertNotLocked(String cookie) {
@@ -1641,6 +1955,7 @@
                 mActiveCount.incrementAndGet();
 
                 mCommitted = true;
+                committedMillis = System.currentTimeMillis();
             }
             return true;
         } catch (PackageManagerException e) {
@@ -1715,11 +2030,11 @@
         // Session is sealed and committed but could not be verified, we need to destroy it.
         destroyInternal();
         if (isStaged()) {
-            setStagedSessionFailed(
+            mStagedSession.setSessionFailed(
                     SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
             // TODO(b/136257624): Remove this once all verification logic has been transferred out
             //  of StagingManager.
-            mStagingManager.notifyVerificationComplete(this);
+            mStagingManager.notifyVerificationComplete(mStagedSession);
         } else {
             // Dispatch message to remove session from PackageInstallerService.
             dispatchSessionFinished(error, msg, null);
@@ -1796,7 +2111,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 +2137,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;
@@ -1838,7 +2153,7 @@
                     .write();
         }
         if (params.isStaged) {
-            mStagingManager.commitSession(this);
+            mStagingManager.commitSession(mStagedSession);
             // TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
             //  though ideally, we just need to send session committed broadcast.
             dispatchSessionFinished(INSTALL_SUCCEEDED, "Session staged", null);
@@ -1854,21 +2169,6 @@
         verify();
     }
 
-    /**
-     * Resumes verification process for non-final committed staged session.
-     *
-     * Useful if a device gets rebooted before verification is complete and we need to restart the
-     * verification.
-     */
-    void verifyStagedSession() {
-        assertCallerIsOwnerOrRootOrSystemLocked();
-        Preconditions.checkArgument(isCommitted());
-        Preconditions.checkArgument(isStaged());
-        Preconditions.checkArgument(!mStagedSessionApplied && !mStagedSessionFailed);
-
-        verify();
-    }
-
     private void verify() {
         try {
             verifyNonStaged();
@@ -1923,36 +2223,6 @@
         }
     }
 
-    /**
-     * Installs apks of staged session while skipping the verification process for a committed and
-     * ready session.
-     */
-    void installStagedSession(IntentSender statusReceiver) {
-        assertCallerIsOwnerOrRootOrSystemLocked();
-        Preconditions.checkArgument(!hasParentSessionId()); // Don't allow installing child sessions
-        Preconditions.checkArgument(isCommitted() && isStagedSessionReady());
-
-        // Since staged sessions are installed during boot, the original reference to status
-        // receiver from the owner has already been lost. We can safely replace it with a
-        // status receiver from the system without effecting the flow.
-        updateRemoteStatusReceiver(statusReceiver);
-        install();
-    }
-
-    private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
-        synchronized (mLock) {
-            mRemoteStatusReceiver = remoteStatusReceiver;
-            if (isMultiPackage()) {
-                final IntentSender childIntentSender =
-                        new ChildStatusIntentReceiver(mChildSessions.clone(), remoteStatusReceiver)
-                                .getIntentSender();
-                for (int i = mChildSessions.size() - 1; i >= 0; --i) {
-                    mChildSessions.valueAt(i).mRemoteStatusReceiver = childIntentSender;
-                }
-            }
-        }
-    }
-
     private void install() {
         try {
             installNonStaged();
@@ -2179,7 +2449,7 @@
         if (isStaged()) {
             // TODO(b/136257624): Remove this once all verification logic has been transferred out
             //  of StagingManager.
-            mStagingManager.notifyPreRebootVerification_Apk_Complete(this);
+            mStagingManager.notifyPreRebootVerification_Apk_Complete(mStagedSession);
             // TODO(b/136257624): We also need to destroy internals for verified staged session,
             //  otherwise file descriptors are never closed for verified staged session until reboot
             return;
@@ -2361,10 +2631,6 @@
         return false;
     }
 
-    boolean containsApexSession() {
-        return sessionContains((s) -> s.isApexSession());
-    }
-
     boolean containsApkSession() {
         return sessionContains((s) -> !s.isApexSession());
     }
@@ -2963,7 +3229,8 @@
     /**
      * @return the package name of this session
      */
-    String getPackageName() {
+    @VisibleForTesting(visibility = PACKAGE)
+    public String getPackageName() {
         synchronized (mLock) {
             return mPackageName;
         }
@@ -2978,6 +3245,12 @@
         }
     }
 
+    long getCommittedMillis() {
+        synchronized (mLock) {
+            return committedMillis;
+        }
+    }
+
     String getInstallerPackageName() {
         return getInstallSource().installerPackageName;
     }
@@ -3179,6 +3452,7 @@
 
     private void abandonNonStaged() {
         synchronized (mLock) {
+            assertNotChildLocked("abandonNonStaged");
             assertCallerIsOwnerOrRootLocked();
             if (mRelinquished) {
                 if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control");
@@ -3190,98 +3464,23 @@
         maybeCleanUpChildSessions();
     }
 
-    private void abandonStaged() {
-        final Runnable r;
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            if (isStagedAndInTerminalState()) {
-                // We keep the session in the database if it's in a finalized state. It will be
-                // removed by PackageInstallerService when the last update time is old enough.
-                // Also, in such cases cleanStageDir() has already been executed so no need to
-                // do it now.
-                return;
-            }
-            mDestroyed = true;
-            boolean isCommitted = mCommitted;
-            List<PackageInstallerSession> childSessions = getChildSessionsLocked();
-            r = () -> {
-                assertNotLocked("abandonStaged");
-                if (isCommitted) {
-                    mStagingManager.abortCommittedSession(this);
-                }
-                cleanStageDir(childSessions);
-                destroyInternal();
-                dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
-                maybeCleanUpChildSessions();
-            };
-            if (mInPreRebootVerification) {
-                // Pre-reboot verification is ongoing. It is not safe to clean up the session yet.
-                mPendingAbandonCallback = r;
-                mCallback.onStagedSessionChanged(this);
-                return;
-            }
+    @GuardedBy("mLock")
+    private void assertNotChildLocked(String cookie) {
+        if (hasParentSessionId()) {
+            throw new IllegalStateException(cookie + " can't be called on a child session, id="
+                    + sessionId + " parentId=" + getParentSessionId());
         }
-        r.run();
     }
 
     @Override
     public void abandon() {
-        if (hasParentSessionId()) {
-            throw new IllegalStateException(
-                    "Session " + sessionId + " is a child of multi-package session "
-                            + getParentSessionId() +  " and may not be abandoned directly.");
-        }
         if (params.isStaged) {
-            abandonStaged();
+            mStagedSession.abandon();
         } else {
             abandonNonStaged();
         }
     }
 
-    /**
-     * Notified by the staging manager that pre-reboot verification is about to start. The return
-     * value should be checked to decide whether it is OK to start pre-reboot verification. In
-     * the case of a destroyed session, {@code false} is returned and there is no need to start
-     * pre-reboot verification.
-     */
-    boolean notifyStagedStartPreRebootVerification() {
-        synchronized (mLock) {
-            if (mInPreRebootVerification) {
-                throw new IllegalStateException("Pre-reboot verification has started");
-            }
-            if (mDestroyed) {
-                return false;
-            }
-            mInPreRebootVerification = true;
-            return true;
-        }
-    }
-
-    private void dispatchPendingAbandonCallback() {
-        final Runnable callback;
-        synchronized (mLock) {
-            callback = mPendingAbandonCallback;
-            mPendingAbandonCallback = null;
-        }
-        if (callback != null) {
-            callback.run();
-        }
-    }
-
-    /**
-     * Notified by the staging manager that pre-reboot verification has ended. Now it is safe to
-     * clean up the session if {@link #abandon()} has been called previously.
-     */
-    void notifyStagedEndPreRebootVerification() {
-        synchronized (mLock) {
-            if (!mInPreRebootVerification) {
-                throw new IllegalStateException("Pre-reboot verification not started");
-            }
-            mInPreRebootVerification = false;
-        }
-        dispatchPendingAbandonCallback();
-    }
-
     @Override
     public boolean isMultiPackage() {
         return params.isMultiPackage;
@@ -3767,88 +3966,29 @@
     }
 
     /** {@hide} */
-    void setStagedSessionReady() {
-        synchronized (mLock) {
-            // Do not allow destroyed/failed staged session to change state
-            if (mDestroyed || mStagedSessionFailed) return;
-            mStagedSessionReady = true;
-            mStagedSessionApplied = false;
-            mStagedSessionFailed = false;
-            mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
-            mStagedSessionErrorMessage = "";
-        }
-        mCallback.onStagedSessionChanged(this);
-    }
-
-    /** {@hide} */
-    void setStagedSessionFailed(@StagedSessionErrorCode int errorCode, String errorMessage) {
-        List<PackageInstallerSession> childSessions;
-        synchronized (mLock) {
-            // Do not allow destroyed/failed staged session to change state
-            if (mDestroyed || mStagedSessionFailed) return;
-            mStagedSessionReady = false;
-            mStagedSessionApplied = false;
-            mStagedSessionFailed = true;
-            mStagedSessionErrorCode = errorCode;
-            mStagedSessionErrorMessage = errorMessage;
-            Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
-            childSessions = getChildSessionsLocked();
-        }
-        cleanStageDir(childSessions);
-        mCallback.onStagedSessionChanged(this);
-    }
-
-    /** {@hide} */
-    void setStagedSessionApplied() {
-        List<PackageInstallerSession> childSessions;
-        synchronized (mLock) {
-            // Do not allow destroyed/failed staged session to change state
-            if (mDestroyed || mStagedSessionFailed) return;
-            mStagedSessionReady = false;
-            mStagedSessionApplied = true;
-            mStagedSessionFailed = false;
-            mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
-            mStagedSessionErrorMessage = "";
-            Slog.d(TAG, "Marking session " + sessionId + " as applied");
-            childSessions = getChildSessionsLocked();
-        }
-        cleanStageDir(childSessions);
-        mCallback.onStagedSessionChanged(this);
-    }
-
-    /** {@hide} */
     boolean isStagedSessionReady() {
-        synchronized (mLock) {
-            return mStagedSessionReady;
-        }
+        return params.isStaged && mStagedSession.isSessionReady();
     }
 
     /** {@hide} */
     boolean isStagedSessionApplied() {
-        synchronized (mLock) {
-            return mStagedSessionApplied;
-        }
+        return params.isStaged && mStagedSession.isSessionApplied();
     }
 
     /** {@hide} */
     boolean isStagedSessionFailed() {
-        synchronized (mLock) {
-            return mStagedSessionFailed;
-        }
+        return params.isStaged && mStagedSession.isSessionFailed();
     }
 
     /** {@hide} */
     @StagedSessionErrorCode int getStagedSessionErrorCode() {
-        synchronized (mLock) {
-            return mStagedSessionErrorCode;
-        }
+        return params.isStaged ? mStagedSession.getSessionErrorCode()
+                : SessionInfo.STAGED_SESSION_NO_ERROR;
     }
 
     /** {@hide} */
     String getStagedSessionErrorMessage() {
-        synchronized (mLock) {
-            return mStagedSessionErrorMessage;
-        }
+        return params.isStaged ? mStagedSession.getSessionErrorMessage() : "";
     }
 
     private void destroyInternal() {
@@ -3923,6 +4063,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();
@@ -3944,11 +4085,11 @@
         pw.printPair("params.isStaged", params.isStaged);
         pw.printPair("mParentSessionId", mParentSessionId);
         pw.printPair("mChildSessionIds", getChildSessionIdsLocked());
-        pw.printPair("mStagedSessionApplied", mStagedSessionApplied);
-        pw.printPair("mStagedSessionFailed", mStagedSessionFailed);
-        pw.printPair("mStagedSessionReady", mStagedSessionReady);
-        pw.printPair("mStagedSessionErrorCode", mStagedSessionErrorCode);
-        pw.printPair("mStagedSessionErrorMessage", mStagedSessionErrorMessage);
+        pw.printPair("mStagedSessionApplied", isStagedSessionApplied());
+        pw.printPair("mStagedSessionFailed", isStagedSessionFailed());
+        pw.printPair("mStagedSessionReady", isStagedSessionReady());
+        pw.printPair("mStagedSessionErrorCode", getStagedSessionErrorCode());
+        pw.printPair("mStagedSessionErrorMessage", getStagedSessionErrorMessage());
         pw.println();
 
         pw.decreaseIndent();
@@ -4099,6 +4240,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());
@@ -4113,12 +4255,12 @@
 
             writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
             writeBooleanAttribute(out, ATTR_STAGED_SESSION, params.isStaged);
-            writeBooleanAttribute(out, ATTR_IS_READY, mStagedSessionReady);
-            writeBooleanAttribute(out, ATTR_IS_FAILED, mStagedSessionFailed);
-            writeBooleanAttribute(out, ATTR_IS_APPLIED, mStagedSessionApplied);
-            out.attributeInt(null, ATTR_STAGED_SESSION_ERROR_CODE, mStagedSessionErrorCode);
+            writeBooleanAttribute(out, ATTR_IS_READY, isStagedSessionReady());
+            writeBooleanAttribute(out, ATTR_IS_FAILED, isStagedSessionFailed());
+            writeBooleanAttribute(out, ATTR_IS_APPLIED, isStagedSessionApplied());
+            out.attributeInt(null, ATTR_STAGED_SESSION_ERROR_CODE, getStagedSessionErrorCode());
             writeStringAttribute(out, ATTR_STAGED_SESSION_ERROR_MESSAGE,
-                    mStagedSessionErrorMessage);
+                    getStagedSessionErrorMessage());
             // TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
             //                       we've read all sessions.
             out.attributeInt(null, ATTR_PARENT_SESSION_ID, mParentSessionId);
@@ -4252,6 +4394,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 +4538,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 72dad61..22f4a92 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,7 @@
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_BROWSABLE;
 import static android.content.Intent.CATEGORY_DEFAULT;
 import static android.content.Intent.CATEGORY_HOME;
 import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
@@ -238,6 +239,7 @@
 import android.content.pm.dex.ArtManager;
 import android.content.pm.dex.DexMetadataHelper;
 import android.content.pm.dex.IArtManager;
+import android.content.pm.parsing.ApkLiteParseUtils;
 import android.content.pm.parsing.ParsingPackageUtils;
 import android.content.pm.parsing.component.ParsedActivity;
 import android.content.pm.parsing.component.ParsedInstrumentation;
@@ -248,6 +250,8 @@
 import android.content.pm.parsing.component.ParsedProcess;
 import android.content.pm.parsing.component.ParsedProvider;
 import android.content.pm.parsing.component.ParsedService;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -256,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;
@@ -391,6 +394,7 @@
 import com.android.server.storage.DeviceStorageMonitorInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.utils.WatchedArrayMap;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
 import dalvik.system.CloseGuard;
@@ -999,7 +1003,7 @@
                 Producer<PackageParser2> scanningPackageParserProducer,
                 Producer<PackageParser2> preparingPackageParserProducer,
                 Producer<PackageInstallerService> packageInstallerServiceProducer,
-                ProducerWithArgument<InstantAppResolverConnection, ComponentName> 
+                ProducerWithArgument<InstantAppResolverConnection, ComponentName>
                         instantAppResolverConnectionProducer,
                 Producer<ModuleInfoProvider> moduleInfoProviderProducer,
                 Producer<LegacyPermissionManagerInternal> legacyPermissionManagerInternalProducer,
@@ -3299,7 +3303,8 @@
 
             // Clean up orphaned packages for which the code path doesn't exist
             // and they are an update to a system app - caused by bug/32321269
-            final ArrayMap<String, PackageSetting> packageSettings = mSettings.getPackagesLocked();
+            final WatchedArrayMap<String, PackageSetting> packageSettings =
+                mSettings.getPackagesLocked();
             final int packageSettingCount = packageSettings.size();
             for (int i = packageSettingCount - 1; i >= 0; i--) {
                 PackageSetting ps = packageSettings.valueAt(i);
@@ -4803,6 +4808,12 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
+        return getPackageInfoInternalBody(packageName, versionCode, flags, filterCallingUid,
+                userId);
+    }
+
+    private PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
+            int flags, int filterCallingUid, int userId) {
         // reader
         synchronized (mLock) {
             // Normalize package name to handle renamed packages and static libs
@@ -5224,6 +5235,11 @@
                     "get application info");
         }
 
+        return getApplicationInfoInternalBody(packageName, flags, filterCallingUid, userId);
+    }
+
+    private ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
+            int filterCallingUid, int userId) {
         // writer
         synchronized (mLock) {
             // Normalize package name to handle renamed packages and static libs
@@ -5414,6 +5430,14 @@
                             InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
                 return;
             }
+
+            // 11. Free storage service cache
+            StorageManagerInternal smInternal =
+                    mInjector.getLocalService(StorageManagerInternal.class);
+            // TODO(b/170481432): Decide what value of bytes needs to be sent instead of
+            // sending the bytes parameter of freeStorage
+            smInternal.freeCache(volumeUuid, bytes);
+            if (file.getUsableSpace() >= bytes) return;
         } else {
             try {
                 mInstaller.freeCache(volumeUuid, bytes, 0, 0);
@@ -5525,8 +5549,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,
@@ -5649,6 +5672,11 @@
                     false /* requireFullPermission */, false /* checkShell */, "get activity info");
         }
 
+        return getActivityInfoInternalBody(component, flags, filterCallingUid, userId);
+    }
+
+    private ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
+            int filterCallingUid, int userId) {
         synchronized (mLock) {
             ParsedActivity a = mComponentResolver.getActivity(component);
 
@@ -5955,6 +5983,11 @@
         flags = updateFlagsForComponent(flags, userId);
         enforceCrossUserOrProfilePermission(callingUid, userId, false /* requireFullPermission */,
                 false /* checkShell */, "get service info");
+        return getServiceInfoBody(component, flags, userId, callingUid);
+    }
+
+    private ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
+                                             int callingUid) {
         synchronized (mLock) {
             ParsedService s = mComponentResolver.getService(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -6527,6 +6560,11 @@
         final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         final int userId = UserHandle.getUserId(uid);
         final int appId = UserHandle.getAppId(uid);
+        return getPackagesForUidInternalBody(callingUid, userId, appId, isCallerInstantApp);
+    }
+
+    private String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
+                                                     boolean isCallerInstantApp) {
         // reader
         synchronized (mLock) {
             final Object obj = mSettings.getSettingLPr(appId);
@@ -6878,6 +6916,15 @@
         }
         // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
         // Or if there's already an ephemeral app installed that handles the action
+        return isInstantAppResolutionAllowedBody(intent, resolvedActivities, userId,
+                                                   skipPackageCheck);
+    }
+
+    // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
+    // Or if there's already an ephemeral app installed that handles the action
+    private boolean isInstantAppResolutionAllowedBody(
+            Intent intent, List<ResolveInfo> resolvedActivities, int userId,
+            boolean skipPackageCheck) {
         synchronized (mLock) {
             final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
             for (int n = 0; n < count; n++) {
@@ -7447,6 +7494,23 @@
                 userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
     }
 
+    // Collect the results of queryIntentActivitiesInternalBody into a single class
+    private static class QueryIntentActivitiesResult {
+        public boolean sortResult = false;
+        public boolean addInstant = false;
+        public List<ResolveInfo> result = null;
+        public List<ResolveInfo> answer = null;
+
+        QueryIntentActivitiesResult(List<ResolveInfo> l) {
+            answer = l;
+        }
+        QueryIntentActivitiesResult(boolean s, boolean a, List<ResolveInfo> l) {
+            sortResult = s;
+            addInstant = a;
+            result = l;
+        }
+    }
+
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
             int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
@@ -7520,11 +7584,37 @@
             return result;
         }
 
+        QueryIntentActivitiesResult lockedResult =
+                queryIntentActivitiesInternalBody(
+                    intent, resolvedType, flags, filterCallingUid, userId, resolveForStart,
+                    allowDynamicSplits, pkgName, instantAppPkgName);
+        if (lockedResult.answer != null) {
+            return lockedResult.answer;
+        }
+
+        if (lockedResult.addInstant) {
+            String callingPkgName = getInstantAppPackageName(filterCallingUid);
+            boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+            lockedResult.result = maybeAddInstantAppInstaller(lockedResult.result, intent,
+                    resolvedType, flags, userId, resolveForStart, isRequesterInstantApp);
+        }
+        if (lockedResult.sortResult) {
+            Collections.sort(lockedResult.result, RESOLVE_PRIORITY_SORTER);
+        }
+        return applyPostResolutionFilter(
+                lockedResult.result, instantAppPkgName, allowDynamicSplits, filterCallingUid,
+                resolveForStart, userId, intent);
+    }
+
+    private @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(
+            Intent intent, String resolvedType, int flags, int filterCallingUid, int userId,
+            boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
+            String instantAppPkgName) {
         // reader
-        boolean sortResult = false;
-        boolean addInstant = false;
-        List<ResolveInfo> result;
         synchronized (mLock) {
+            boolean sortResult = false;
+            boolean addInstant = false;
+            List<ResolveInfo> result = null;
             if (pkgName == null) {
                 List<CrossProfileIntentFilter> matchingFilters =
                         getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
@@ -7534,9 +7624,11 @@
                 if (xpResolveInfo != null) {
                     List<ResolveInfo> xpResult = new ArrayList<>(1);
                     xpResult.add(xpResolveInfo);
-                    return applyPostResolutionFilter(
-                            filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
-                            allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent);
+                    return new QueryIntentActivitiesResult(
+                            applyPostResolutionFilter(
+                                    filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
+                                    allowDynamicSplits, filterCallingUid, resolveForStart, userId,
+                                    intent));
                 }
 
                 // Check for results in the current profile.
@@ -7575,17 +7667,19 @@
                             // And we are not going to add emphemeral app, so we can return the
                             // result straight away.
                             result.add(xpDomainInfo.resolveInfo);
-                            return applyPostResolutionFilter(result, instantAppPkgName,
-                                    allowDynamicSplits, filterCallingUid, resolveForStart, userId,
-                                    intent);
+                            return new QueryIntentActivitiesResult(
+                                    applyPostResolutionFilter(result, instantAppPkgName,
+                                            allowDynamicSplits, filterCallingUid, resolveForStart,
+                                            userId, intent));
                         }
                     } else if (result.size() <= 1 && !addInstant) {
                         // No result in parent user and <= 1 result in current profile, and we
                         // are not going to add emphemeral app, so we can return the result without
                         // further processing.
-                        return applyPostResolutionFilter(result, instantAppPkgName,
+                        return new QueryIntentActivitiesResult(
+                                applyPostResolutionFilter(result, instantAppPkgName,
                                 allowDynamicSplits, filterCallingUid, resolveForStart, userId,
-                                intent);
+                                intent));
                     }
                     // We have more than one candidate (combining results from current and parent
                     // profile), so we need filtering and sorting.
@@ -7613,19 +7707,8 @@
                     }
                 }
             }
+            return new QueryIntentActivitiesResult(sortResult, addInstant, result);
         }
-        if (addInstant) {
-            String callingPkgName = getInstantAppPackageName(filterCallingUid);
-            boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
-            result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId,
-                    resolveForStart, isRequesterInstantApp);
-        }
-        if (sortResult) {
-            Collections.sort(result, RESOLVE_PRIORITY_SORTER);
-        }
-        return applyPostResolutionFilter(
-                result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
-                userId, intent);
     }
 
     private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
@@ -7972,14 +8055,30 @@
                     candidates.size());
         }
 
-        final ArrayList<ResolveInfo> result = new ArrayList<>();
-        final ArrayList<ResolveInfo> alwaysList = new ArrayList<>();
-        final ArrayList<ResolveInfo> undefinedList = new ArrayList<>();
-        final ArrayList<ResolveInfo> alwaysAskList = new ArrayList<>();
-        final ArrayList<ResolveInfo> neverList = new ArrayList<>();
-        final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
+        final ArrayList<ResolveInfo> result =
+                filterCandidatesWithDomainPreferredActivitiesLPrBody(
+                    intent, matchFlags, candidates, xpDomainInfo, userId, debug);
 
+        if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
+            Slog.v(TAG, "Filtered results with preferred activities. New candidates count: "
+                    + result.size());
+            for (ResolveInfo info : result) {
+                Slog.v(TAG, "  + " + info.activityInfo);
+            }
+        }
+        return result;
+    }
+
+    private ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
+            Intent intent, int matchFlags, List<ResolveInfo> candidates,
+            CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
         synchronized (mLock) {
+            final ArrayList<ResolveInfo> result = new ArrayList<>();
+            final ArrayList<ResolveInfo> alwaysList = new ArrayList<>();
+            final ArrayList<ResolveInfo> undefinedList = new ArrayList<>();
+            final ArrayList<ResolveInfo> alwaysAskList = new ArrayList<>();
+            final ArrayList<ResolveInfo> neverList = new ArrayList<>();
+            final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
             final int count = candidates.size();
             // First, try to use linked apps. Partition the candidates into four lists:
             // one for the final results, one for the "do not use ever", one for "undefined status"
@@ -8003,6 +8102,13 @@
                             Slog.i(TAG, "  + always: " + info.activityInfo.packageName
                                     + " : linkgen=" + linkGeneration);
                         }
+
+                        if (!intent.hasCategory(CATEGORY_BROWSABLE)
+                                || !intent.hasCategory(CATEGORY_DEFAULT)) {
+                            undefinedList.add(info);
+                            continue;
+                        }
+
                         // Use link-enabled generation as preferredOrder, i.e.
                         // prefer newly-enabled over earlier-enabled.
                         info.preferredOrder = linkGeneration;
@@ -8108,15 +8214,8 @@
                     result.removeAll(neverList);
                 }
             }
+            return result;
         }
-        if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
-            Slog.v(TAG, "Filtered results with preferred activities. New candidates count: " +
-                    result.size());
-            for (ResolveInfo info : result) {
-                Slog.v(TAG, "  + " + info.activityInfo);
-            }
-        }
-        return result;
     }
 
     // Returns a packed value as a long:
@@ -8615,6 +8714,13 @@
             return list;
         }
 
+        return queryIntentServicesInternalBody(intent, resolvedType, flags,
+                userId, callingUid, instantAppPkgName);
+    }
+
+    private @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
+            String resolvedType, int flags, int userId, int callingUid,
+            String instantAppPkgName) {
         // reader
         synchronized (mLock) {
             String pkgName = intent.getPackage();
@@ -8840,15 +8946,21 @@
         }
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId);
-        final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
-        final boolean listApex = (flags & MATCH_APEX) != 0;
-        final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
 
         enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
                 false /* checkShell */, "get installed packages");
 
+        return getInstalledPackagesBody(flags, userId, callingUid);
+    }
+
+    private ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
+                                                                      int callingUid) {
         // writer
         synchronized (mLock) {
+            final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
+            final boolean listApex = (flags & MATCH_APEX) != 0;
+            final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
+
             ArrayList<PackageInfo> list;
             if (listUninstalled) {
                 list = new ArrayList<>(mSettings.getPackagesLocked().size());
@@ -9098,6 +9210,11 @@
         if (HIDE_EPHEMERAL_APIS) {
             return false;
         }
+        return isInstantAppInternalBody(packageName, userId, callingUid);
+    }
+
+    private boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
+            int callingUid) {
         synchronized (mLock) {
             if (Process.isIsolated(callingUid)) {
                 callingUid = mIsolatedOwners.get(callingUid);
@@ -15322,7 +15439,7 @@
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, InstallSource installSource, String volumeUuid,
-                UserHandle user, String packageAbiOverride) {
+                UserHandle user, String packageAbiOverride, PackageLite packageLite) {
             super(user);
             this.origin = origin;
             this.move = move;
@@ -15341,7 +15458,7 @@
             this.forceQueryableOverride = false;
             this.mDataLoaderType = DataLoaderType.NONE;
             this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
-            this.mPackageLite = null;
+            this.mPackageLite = packageLite;
         }
 
         InstallParams(File stagedDir, IPackageInstallObserver2 observer,
@@ -17681,12 +17798,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();
@@ -17704,12 +17821,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);
@@ -17726,12 +17843,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);
@@ -17757,7 +17874,7 @@
         public void onPackageLoadingProgressChanged(float progress) {
             final PackageSetting ps;
             synchronized (mLock) {
-                ps = mSettings.mPackages.get(mPackageName);
+                ps = mSettings.getPackageLPr(mPackageName);
             }
             if (ps == null) {
                 return;
@@ -17780,7 +17897,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;
@@ -17793,7 +17910,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");
@@ -20719,6 +20836,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())) {
@@ -20791,8 +20913,12 @@
                 mSettings.applyDefaultPreferredAppsLPw(userId);
                 clearIntentFilterVerificationsLPw(userId);
                 primeDomainVerificationsLPw(userId);
+                final int numPackages = mPackages.size();
+                for (int i = 0; i < numPackages; i++) {
+                    final AndroidPackage pkg = mPackages.valueAt(i);
+                    mPermissionManager.resetRuntimePermissions(pkg, userId);
+                }
             }
-            mPermissionManager.resetAllRuntimePermissions(userId);
             updateDefaultHomeNotLocked(userId);
             // TODO: We have to reset the default SMS and Phone. This requires
             // significant refactoring to keep all default apps in the package
@@ -22290,7 +22416,7 @@
         mUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
         reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
 
-        mPermissionManager.systemReady();
+        mPermissionManager.onSystemReady();
 
         int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
         for (int userId : UserManagerService.getInstance().getUserIds()) {
@@ -24182,8 +24308,12 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
+        final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+        final ParseResult<PackageLite> ret = ApkLiteParseUtils.parsePackageLite(input,
+                new File(origin.resolvedPath), /* flags */ 0);
+        final PackageLite lite = ret.isSuccess() ? ret.getResult() : null;
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installSource, volumeUuid, user, packageAbiOverride);
+                installSource, volumeUuid, user, packageAbiOverride, lite);
         params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -24597,7 +24727,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;
                 }
@@ -26044,7 +26174,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/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index c77eda1..d3d7c60 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -822,7 +822,7 @@
     public static PackageInfoLite getMinimalPackageInfo(Context context,
             PackageParser.PackageLite pkg, String packagePath, int flags, String abiOverride) {
         final PackageInfoLite ret = new PackageInfoLite();
-        if (packagePath == null) {
+        if (packagePath == null || pkg == null) {
             Slog.i(TAG, "Invalid package file " + packagePath);
             ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
             return ret;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 318b229..2f6756d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -27,7 +27,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.role.IRoleManager;
 import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -80,7 +79,6 @@
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.PersistableBundle;
 import android.os.Process;
-import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
@@ -106,6 +104,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
@@ -2971,12 +2970,10 @@
         final int translatedUserId =
                 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
         final CompletableFuture<Boolean> future = new CompletableFuture<>();
-        final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
         try {
-            IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
-            roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
-                    0, translatedUserId, callback);
+            RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+            roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, 0,
+                    UserHandle.of(translatedUserId), FgThread.getExecutor(), future::complete);
             boolean success = future.get();
             if (success) {
                 pw.println("Success");
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index ac76cf7..67bd82b4 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -175,22 +175,27 @@
 
     public void setInstallerPackageName(String packageName) {
         installSource = installSource.setInstallerPackage(packageName);
+        onChanged();
     }
 
     public void setInstallSource(InstallSource installSource) {
         this.installSource = Objects.requireNonNull(installSource);
+        onChanged();
     }
 
     void removeInstallerPackage(String packageName) {
         installSource = installSource.removeInstallerPackage(packageName);
+        onChanged();
     }
 
     public void setIsOrphaned(boolean isOrphaned) {
         installSource = installSource.setIsOrphaned(isOrphaned);
+        onChanged();
     }
 
     public void setVolumeUuid(String volumeUuid) {
         this.volumeUuid = volumeUuid;
+        onChanged();
     }
 
     public String getVolumeUuid() {
@@ -199,10 +204,12 @@
 
     public void setTimeStamp(long newStamp) {
         timeStamp = newStamp;
+        onChanged();
     }
 
     public void setUpdateAvailable(boolean updateAvailable) {
         this.updateAvailable = updateAvailable;
+        onChanged();
     }
 
     public boolean isUpdateAvailable() {
@@ -272,6 +279,7 @@
         if (state == null) {
             state = new PackageUserState();
             mUserState.put(userId, state);
+            onChanged();
         }
         return state;
     }
@@ -289,6 +297,7 @@
         PackageUserState st = modifyUserState(userId);
         st.enabled = state;
         st.lastDisableAppCaller = callingPackage;
+        onChanged();
     }
 
     int getEnabled(int userId) {
@@ -434,6 +443,7 @@
         }
         existingUserState.suspendParams.put(suspendingPackage, newSuspendParams);
         existingUserState.suspended = true;
+        onChanged();
     }
 
     void removeSuspension(String suspendingPackage, int userId) {
@@ -445,6 +455,7 @@
             }
         }
         existingUserState.suspended = (existingUserState.suspendParams != null);
+        onChanged();
     }
 
     void removeSuspension(Predicate<String> suspendingPackagePredicate, int userId) {
@@ -461,6 +472,7 @@
             }
         }
         existingUserState.suspended = (existingUserState.suspendParams != null);
+        onChanged();
     }
 
     public boolean getInstantApp(int userId) {
@@ -506,6 +518,7 @@
         state.instantApp = instantApp;
         state.virtualPreload = virtualPreload;
         state.harmfulAppWarning = harmfulAppWarning;
+        onChanged();
     }
 
     void setUserState(int userId, PackageUserState otherState) {
@@ -547,11 +560,17 @@
 
     PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
         PackageUserState state = modifyUserState(userId);
+        boolean changed = false;
         if (disabled && state.disabledComponents == null) {
             state.disabledComponents = new ArraySet<String>(1);
+            changed = true;
         }
         if (enabled && state.enabledComponents == null) {
             state.enabledComponents = new ArraySet<String>(1);
+            changed = true;
+        }
+        if (changed) {
+            onChanged();
         }
         return state;
     }
@@ -603,6 +622,7 @@
 
     void removeUser(int userId) {
         mUserState.delete(userId);
+        onChanged();
     }
 
     public int[] getNotInstalledUserIds() {
@@ -630,6 +650,7 @@
 
     void setIntentFilterVerificationInfo(IntentFilterVerificationInfo info) {
         verificationInfo = info;
+        onChanged();
     }
 
     // Returns a packed value as a long:
@@ -648,6 +669,7 @@
         state.domainVerificationStatus = status;
         if (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
             state.appLinkGeneration = generation;
+            onChanged();
         }
     }
 
@@ -694,6 +716,7 @@
     void setHarmfulAppWarning(int userId, String harmfulAppWarning) {
         PackageUserState userState = modifyUserState(userId);
         userState.harmfulAppWarning = harmfulAppWarning;
+        onChanged();
     }
 
     String getHarmfulAppWarning(int userId) {
@@ -838,6 +861,7 @@
         for (int i = 0; i < other.mUserState.size(); i++) {
             mUserState.put(other.mUserState.keyAt(i), other.mUserState.valueAt(i));
         }
+        onChanged();
         return this;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index 08a87d8..d0f9787 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -19,10 +19,12 @@
 import android.annotation.NonNull;
 import android.content.IntentFilter;
 
-import com.android.server.IntentResolver;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
 
 public class PersistentPreferredIntentResolver
-        extends IntentResolver<PersistentPreferredActivity, PersistentPreferredActivity> {
+        extends WatchableIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
+        implements Snappable {
     @Override
     protected PersistentPreferredActivity[] newArray(int size) {
         return new PersistentPreferredActivity[size];
@@ -37,4 +39,15 @@
     protected boolean isPackageForFilter(String packageName, PersistentPreferredActivity filter) {
         return packageName.equals(filter.mComponent.getPackageName());
     }
+
+    /**
+     * Return a snapshot of the current object.  The snapshot is a read-only copy suitable
+     * for read-only methods.
+     * @return A snapshot of the current object.
+     */
+    public PersistentPreferredIntentResolver snapshot() {
+        PersistentPreferredIntentResolver result = new PersistentPreferredIntentResolver();
+        result.doCopy(this);
+        return result;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index ff3df13..b62421e 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -19,13 +19,15 @@
 import android.annotation.NonNull;
 import android.content.IntentFilter;
 
-import java.io.PrintWriter;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
 
-import com.android.server.IntentResolver;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 public class PreferredIntentResolver
-        extends IntentResolver<PreferredActivity, PreferredActivity> {
+        extends WatchableIntentResolver<PreferredActivity, PreferredActivity>
+        implements Snappable {
     @Override
     protected PreferredActivity[] newArray(int size) {
         return new PreferredActivity[size];
@@ -66,4 +68,15 @@
         }
         return true;
     }
+
+    /**
+     * Return a snapshot of the current object.  The snapshot is a read-only copy suitable
+     * for read-only methods.
+     * @return A snapshot of the current object.
+     */
+    public PreferredIntentResolver snapshot() {
+        PreferredIntentResolver result = new PreferredIntentResolver();
+        result.doCopy(this);
+        return result;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 968c4b5..7924d5d 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -16,17 +16,71 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.Watcher;
 
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public abstract class SettingBase {
+public abstract class SettingBase implements Watchable {
+    // TODO: make this variable protected, or even private with a getter and setter.
+    // Simply making it protected or private requires that the name be changed to conformm
+    // to the Android naming convention, and that touches quite a few files.
     int pkgFlags;
+
+    // TODO: make this variable protected, or even private with a getter and setter.
+    // Simply making it protected or private requires that the name be changed to conformm
+    // to the Android naming convention, and that touches quite a few files.
     int pkgPrivateFlags;
 
     /**
+     * Watchable machinery
+     */
+    private final Watchable mWatchable = new WatchableImpl();
+
+    /**
+     * Ensures an observer is in the list, exactly once. The observer cannot be null.  The
+     * function quietly returns if the observer is already in the list.
+     *
+     * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+     */
+    public void registerObserver(@NonNull Watcher observer) {
+        mWatchable.registerObserver(observer);
+    }
+
+    /**
+     * Ensures an observer is not in the list. The observer must not be null.  The function
+     * quietly returns if the objserver is not in the list.
+     *
+     * @param observer The {@link Watcher} that should not be in the notification list.
+     */
+    public void unregisterObserver(@NonNull Watcher observer) {
+        mWatchable.unregisterObserver(observer);
+    }
+
+    /**
+     * Invokes {@link Watcher#onChange} on each registered observer.  The method can be called
+     * with the {@link Watchable} that generated the event.  In a tree of {@link Watchable}s, this
+     * is generally the first (deepest) {@link Watchable} to detect a change.
+     *
+     * @param what The {@link Watchable} that generated the event.
+     */
+    public void dispatchChange(@Nullable Watchable what) {
+        mWatchable.dispatchChange(what);
+    }
+    /**
+     * Notify listeners that this object has changed.
+     */
+    protected void onChanged() {
+        dispatchChange(this);
+    }
+
+    /**
      * The legacy permission state that is read from package settings persistence for migration.
      * This state here can not reflect the current permission state and should not be used for
      * purposes other than migration.
@@ -53,6 +107,7 @@
         pkgFlags = orig.pkgFlags;
         pkgPrivateFlags = orig.pkgPrivateFlags;
         mLegacyPermissionsState.copyFrom(orig.mLegacyPermissionsState);
+        onChanged();
     }
 
     @Deprecated
@@ -64,6 +119,7 @@
         this.pkgFlags = pkgFlags
                 & (ApplicationInfo.FLAG_SYSTEM
                         | ApplicationInfo.FLAG_EXTERNAL_STORAGE);
+        onChanged();
     }
 
     void setPrivateFlags(int pkgPrivateFlags) {
@@ -75,5 +131,6 @@
                 | ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT
                 | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER
                 | ApplicationInfo.PRIVATE_FLAG_ODM);
+        onChanged();
     }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2d5034e..7c4dade 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -114,7 +114,14 @@
 import com.android.server.pm.permission.LegacyPermissionSettings;
 import com.android.server.pm.permission.LegacyPermissionState;
 import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Snapshots;
 import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.Watcher;
 
 import libcore.io.IoUtils;
 
@@ -148,10 +155,58 @@
 /**
  * Holds information about dynamic settings.
  */
-public final class Settings {
+public final class Settings implements Watchable, Snappable {
     private static final String TAG = "PackageSettings";
 
     /**
+     * Cached snapshot
+     */
+    private volatile Settings mSnapshot = null;
+
+    /**
+     * Watchable machinery
+     */
+    private final WatchableImpl mWatchable = new WatchableImpl();
+
+    /**
+     * Ensures an observer is in the list, exactly once. The observer cannot be null.  The
+     * function quietly returns if the observer is already in the list.
+     *
+     * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+     */
+    public void registerObserver(@NonNull Watcher observer) {
+        mWatchable.registerObserver(observer);
+    }
+
+    /**
+     * Ensures an observer is not in the list. The observer must not be null.  The function
+     * quietly returns if the objserver is not in the list.
+     *
+     * @param observer The {@link Watcher} that should not be in the notification list.
+     */
+    public void unregisterObserver(@NonNull Watcher observer) {
+        mWatchable.unregisterObserver(observer);
+    }
+
+    /**
+     * Invokes {@link Watcher#onChange} on each registered observer.  The method can be called
+     * with the {@link Watchable} that generated the event.  In a tree of {@link Watchable}s, this
+     * is generally the first (deepest) {@link Watchable} to detect a change.
+     *
+     * @param what The {@link Watchable} that generated the event.
+     */
+    public void dispatchChange(@Nullable Watchable what) {
+        mSnapshot = null;
+        mWatchable.dispatchChange(what);
+    }
+    /**
+     * Notify listeners that this object has changed.
+     */
+    protected void onChanged() {
+        dispatchChange(this);
+    }
+
+    /**
      * Current version of the package database. Set it to the latest version in
      * the {@link DatabaseVersion} class below to ensure the database upgrade
      * doesn't happen repeatedly.
@@ -295,7 +350,8 @@
     private final File mKernelMappingFilename;
 
     /** Map from package name to settings */
-    final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    final WatchedArrayMap<String, PackageSetting> mPackages = new WatchedArrayMap<>();
 
     /**
      * List of packages that were involved in installing other packages, i.e. are listed
@@ -367,21 +423,21 @@
 
     // The user's preferred activities associated with particular intent
     // filters.
-    private final SparseArray<PreferredIntentResolver> mPreferredActivities =
-            new SparseArray<PreferredIntentResolver>();
+    private final WatchedSparseArray<PreferredIntentResolver>
+            mPreferredActivities = new WatchedSparseArray<>();
 
     // The persistent preferred activities of the user's profile/device owner
     // associated with particular intent filters.
-    private final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
-            new SparseArray<PersistentPreferredIntentResolver>();
+    private final WatchedSparseArray<PersistentPreferredIntentResolver>
+            mPersistentPreferredActivities = new WatchedSparseArray<>();
 
     // For every user, it is used to find to which other users the intent can be forwarded.
-    private final SparseArray<CrossProfileIntentResolver> mCrossProfileIntentResolvers =
-            new SparseArray<CrossProfileIntentResolver>();
+    private final WatchedSparseArray<CrossProfileIntentResolver>
+            mCrossProfileIntentResolvers = new WatchedSparseArray<>();
 
     final ArrayMap<String, SharedUserSetting> mSharedUsers = new ArrayMap<>();
-    private final ArrayList<SettingBase> mAppIds = new ArrayList<>();
-    private final SparseArray<SettingBase> mOtherAppIds = new SparseArray<>();
+    private final ArrayList<SettingBase> mAppIds;
+    private final SparseArray<SettingBase> mOtherAppIds;
 
     // For reading/writing settings file.
     private final ArrayList<Signature> mPastSignatures =
@@ -414,17 +470,30 @@
 
     private final File mSystemDir;
 
-    public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
+    public final KeySetManagerService mKeySetManagerService =
+            new KeySetManagerService(mPackages.untrackedMap());
 
     /** Settings and other information about permissions */
     final LegacyPermissionSettings mPermissions;
 
     private final LegacyPermissionDataProvider mPermissionDataProvider;
 
+    /**
+     * The observer that watches for changes from array members
+     */
+    private final Watcher mObserver = new Watcher() {
+            @Override
+            public void onChange(@Nullable Watchable what) {
+                Settings.this.dispatchChange(what);
+            }
+        };
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public Settings(Map<String, PackageSetting> pkgSettings) {
         mLock = new Object();
         mPackages.putAll(pkgSettings);
+        mAppIds = new ArrayList<>();
+        mOtherAppIds = new SparseArray<>();
         mSystemDir = null;
         mPermissions = null;
         mRuntimePermissionsPersistence = null;
@@ -435,11 +504,17 @@
         mStoppedPackagesFilename = null;
         mBackupStoppedPackagesFilename = null;
         mKernelMappingFilename = null;
+        mPackages.registerObserver(mObserver);
+        mPreferredActivities.registerObserver(mObserver);
+        mPersistentPreferredActivities.registerObserver(mObserver);
+        mCrossProfileIntentResolvers.registerObserver(mObserver);
     }
 
     Settings(File dataDir, RuntimePermissionsPersistence runtimePermissionsPersistence,
             LegacyPermissionDataProvider permissionDataProvider, Object lock) {
         mLock = lock;
+        mAppIds = new ArrayList<>();
+        mOtherAppIds = new SparseArray<>();
         mPermissions = new LegacyPermissionSettings(lock);
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                 runtimePermissionsPersistence);
@@ -462,18 +537,91 @@
         // Deprecated: Needed for migration
         mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
         mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
+        mPackages.registerObserver(mObserver);
+        mPreferredActivities.registerObserver(mObserver);
+        mPersistentPreferredActivities.registerObserver(mObserver);
+        mCrossProfileIntentResolvers.registerObserver(mObserver);
     }
 
-    private static void invalidatePackageCache() {
+    /**
+     * A copy constructor used in snapshot().  Attributes that are supposed to be
+     * immutable in the PackageManagerService application are referenced.  Attributes that
+     * are changed by PackageManagerService APIs are deep-copied
+     */
+    private Settings(Settings r) {
+        final int mPackagesSize = r.mPackages.size();
+        mPackages.putAll(r.mPackages);
+
+        // The following assignments satisfy Java requirements but are not
+        // needed by the read-only methods.  Note especially that the lock
+        // is not required because this clone is meant to support lock-free
+        // read-only methods.
+        mLock = null;
+        mRuntimePermissionsPersistence = r.mRuntimePermissionsPersistence;
+        mSettingsFilename = null;
+        mBackupSettingsFilename = null;
+        mPackageListFilename = null;
+        mStoppedPackagesFilename = null;
+        mBackupStoppedPackagesFilename = null;
+        mKernelMappingFilename = null;
+
+        mInstallerPackages.addAll(r.mInstallerPackages);
+        mKernelMapping.putAll(r.mKernelMapping);
+        mDisabledSysPackages.putAll(r.mDisabledSysPackages);
+        Snapshots.copy(mBlockUninstallPackages, r.mBlockUninstallPackages);
+        mRestoredIntentFilterVerifications.putAll(r.mRestoredIntentFilterVerifications);
+        mVersion.putAll(r.mVersion);
+        mVerifierDeviceIdentity = r.mVerifierDeviceIdentity;
+        WatchedSparseArray.snapshot(
+                mPreferredActivities, r.mPreferredActivities);
+        WatchedSparseArray.snapshot(
+                mPersistentPreferredActivities, r.mPersistentPreferredActivities);
+        WatchedSparseArray.snapshot(
+                mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
+        mSharedUsers.putAll(r.mSharedUsers);
+        mAppIds = new ArrayList<>(r.mAppIds);
+        mOtherAppIds = r.mOtherAppIds.clone();
+        mPastSignatures.addAll(r.mPastSignatures);
+        mKeySetRefs.putAll(r.mKeySetRefs);
+        mRenamedPackages.putAll(r.mRenamedPackages);
+        Snapshots.copy(mDefaultBrowserApp, r.mDefaultBrowserApp);
+        Snapshots.snapshot(mNextAppLinkGeneration, r.mNextAppLinkGeneration);
+        // mReadMessages
+        mPendingPackages.addAll(r.mPendingPackages);
+        mSystemDir = null;
+        // mKeySetManagerService;
+        mPermissions = r.mPermissions;
+        mPermissionDataProvider = r.mPermissionDataProvider;
+
+        // Do not register any Watchables
+    }
+
+    /**
+     * Return a snapshot.  If the cached snapshot is null, build a new one.  The logic in
+     * the function ensures that this function returns a valid snapshot even if a race
+     * condition causes the cached snapshot to be cleared asynchronously to this method.
+     */
+    public Settings snapshot() {
+        Settings s = mSnapshot;
+        if (s == null) {
+            s = new Settings(this);
+            s.mWatchable.seal();
+            mSnapshot = s;
+        }
+        return s;
+    }
+
+    private void invalidatePackageCache() {
         PackageManagerService.invalidatePackageInfoCache();
         ChangeIdStateCache.invalidate();
+        onChanged();
     }
 
     PackageSetting getPackageLPr(String pkgName) {
         return mPackages.get(pkgName);
     }
 
-    ArrayMap<String, PackageSetting> getPackagesLocked() {
+    WatchedArrayMap<String, PackageSetting> getPackagesLocked() {
         return mPackages;
     }
 
@@ -5557,6 +5705,7 @@
     /** This method takes a specific user id as well as UserHandle.USER_ALL. */
     void clearPackagePreferredActivities(String packageName,
             @NonNull SparseBooleanArray outUserChanged, int userId) {
+        boolean changed = false;
         ArrayList<PreferredActivity> removed = null;
         for (int i = 0; i < mPreferredActivities.size(); i++) {
             final int thisUserId = mPreferredActivities.keyAt(i);
@@ -5584,8 +5733,12 @@
                     pir.removeFilter(pa);
                 }
                 outUserChanged.put(thisUserId, true);
+                changed = true;
             }
         }
+        if (changed) {
+            onChanged();
+        }
     }
 
     boolean clearPackagePersistentPreferredActivities(String packageName, int userId) {
@@ -5616,6 +5769,9 @@
                 changed = true;
             }
         }
+        if (changed) {
+            onChanged();
+        }
         return changed;
     }
 
@@ -5648,6 +5804,7 @@
                 changed.add(mPreferredActivities.keyAt(i));
             }
         }
+        onChanged();
         return changed;
     }
 
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 6103f558..9b1c08d 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -93,6 +93,7 @@
                     proc.addStateFrom(newProc);
                 }
             }
+            onChanged();
         }
     }
 
@@ -117,6 +118,7 @@
         }
         // recalculate processes.
         updateProcesses();
+        onChanged();
         return true;
     }
 
@@ -129,6 +131,7 @@
         if (packages.add(packageSetting)) {
             setFlags(this.pkgFlags | packageSetting.pkgFlags);
             setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
+            onChanged();
         }
         if (packageSetting.pkg != null) {
             addProcesses(packageSetting.pkg.getProcesses());
@@ -169,6 +172,7 @@
             }
             if (ps.pkg.getTargetSdkVersion() < seInfoTargetSdkVersion) {
                 seInfoTargetSdkVersion = ps.pkg.getTargetSdkVersion();
+                onChanged();
             }
         }
 
@@ -179,6 +183,7 @@
             final boolean isPrivileged = isPrivileged() | ps.pkg.isPrivileged();
             ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps.pkg, isPrivileged,
                     seInfoTargetSdkVersion));
+            onChanged();
         }
     }
 
@@ -234,6 +239,7 @@
         } else {
             this.processes = null;
         }
+        onChanged();
         return this;
     }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 0ac0c8d..9f07695 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -737,7 +737,7 @@
                     || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
 
             if (!getPinnedByAnyLauncher) {
-                if (si.isFloating()) {
+                if (si.isFloating() && !si.isCached()) {
                     if (!isPinnedByCaller) {
                         continue;
                     }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c68fe81..95ce140 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);
+            }
         }
     }
 
@@ -2737,7 +2739,8 @@
 
                 // Default launcher from role manager.
                 final long startGetHomeRoleHoldersAsUser = getStatStartTime();
-                final String defaultLauncher = injectGetHomeRoleHolderAsUser(userId);
+                final String defaultLauncher = injectGetHomeRoleHolderAsUser(
+                        getParentOrSelfUserId(userId));
                 logDurationStat(Stats.GET_DEFAULT_HOME, startGetHomeRoleHoldersAsUser);
 
                 if (defaultLauncher != null) {
@@ -4692,7 +4695,7 @@
                 final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
                 // Default launcher from package manager.
                 final ComponentName defaultLauncher = mPackageManagerInternal
-                        .getHomeActivitiesAsUser(allHomeCandidates, mUserId);
+                        .getHomeActivitiesAsUser(allHomeCandidates, getParentOrSelfUserId(mUserId));
                 getOutPrintWriter().println("Launcher: " + defaultLauncher);
             }
         }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 85c4ab2..545567c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser.PackageParserException;
@@ -59,6 +60,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;
@@ -81,6 +83,7 @@
 import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 /**
@@ -101,7 +104,7 @@
     private String mFailureReason;
 
     @GuardedBy("mStagedSessions")
-    private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
+    private final SparseArray<StagedSession> mStagedSessions = new SparseArray<>();
 
     @GuardedBy("mFailedPackageNames")
     private final List<String> mFailedPackageNames = new ArrayList<>();
@@ -110,6 +113,35 @@
     @GuardedBy("mSuccessfulStagedSessionIds")
     private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();
 
+    interface StagedSession {
+        boolean isMultiPackage();
+        boolean isApexSession();
+        boolean isCommitted();
+        boolean isInTerminalState();
+        boolean isDestroyed();
+        boolean isSessionReady();
+        boolean isSessionApplied();
+        boolean isSessionFailed();
+        List<StagedSession> getChildSessions();
+        String getPackageName();
+        int getParentSessionId();
+        int sessionId();
+        PackageInstaller.SessionParams sessionParams();
+        boolean sessionContains(Predicate<StagedSession> filter);
+        boolean containsApkSession();
+        boolean containsApexSession();
+        void setSessionReady();
+        void setSessionFailed(@StagedSessionErrorCode int errorCode, String errorMessage);
+        void setSessionApplied();
+        void installSession(IntentSender statusReceiver);
+        boolean hasParentSessionId();
+        long getCommittedMillis();
+        void abandon();
+        boolean notifyStartPreRebootVerification();
+        void notifyEndPreRebootVerification();
+        void verifySession();
+    }
+
     StagingManager(Context context, Supplier<PackageParser2> packageParserSupplier) {
         mContext = context;
         mPackageParserSupplier = packageParserSupplier;
@@ -212,20 +244,20 @@
                         + " compatible with the one currently installed on device");
     }
 
-    private List<PackageInfo> submitSessionToApexService(@NonNull PackageInstallerSession session,
+    private List<PackageInfo> submitSessionToApexService(@NonNull StagedSession session,
             int rollbackId) throws PackageManagerException {
         final IntArray childSessionIds = new IntArray();
         if (session.isMultiPackage()) {
-            for (PackageInstallerSession s : session.getChildSessions()) {
+            for (StagedSession s : session.getChildSessions()) {
                 if (s.isApexSession()) {
-                    childSessionIds.add(s.sessionId);
+                    childSessionIds.add(s.sessionId());
                 }
             }
         }
         ApexSessionParams apexSessionParams = new ApexSessionParams();
-        apexSessionParams.sessionId = session.sessionId;
+        apexSessionParams.sessionId = session.sessionId();
         apexSessionParams.childSessionIds = childSessionIds.toArray();
-        if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+        if (session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
             apexSessionParams.isRollback = true;
             apexSessionParams.rollbackId = rollbackId;
         } else {
@@ -268,7 +300,7 @@
             result.add(packageInfo);
             apexPackageNames.add(packageInfo.packageName);
         }
-        Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: "
+        Slog.d(TAG, "Session " + session.sessionId() + " has following APEX packages: "
                 + apexPackageNames);
         return result;
     }
@@ -287,22 +319,23 @@
                 "Could not find rollback id for commit session: " + sessionId);
     }
 
-    private void checkRequiredVersionCode(final PackageInstallerSession session,
+    private void checkRequiredVersionCode(final StagedSession session,
             final PackageInfo activePackage) throws PackageManagerException {
-        if (session.params.requiredInstalledVersionCode == PackageManager.VERSION_CODE_HIGHEST) {
+        if (session.sessionParams().requiredInstalledVersionCode
+                == PackageManager.VERSION_CODE_HIGHEST) {
             return;
         }
         final long activeVersion = activePackage.applicationInfo.longVersionCode;
-        if (activeVersion != session.params.requiredInstalledVersionCode) {
+        if (activeVersion != session.sessionParams().requiredInstalledVersionCode) {
             throw new PackageManagerException(
                     SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                     "Installed version of APEX package " + activePackage.packageName
                             + " does not match required. Active version: " + activeVersion
-                            + " required: " + session.params.requiredInstalledVersionCode);
+                            + " required: " + session.sessionParams().requiredInstalledVersionCode);
         }
     }
 
-    private void checkDowngrade(final PackageInstallerSession session,
+    private void checkDowngrade(final StagedSession session,
             final PackageInfo activePackage, final PackageInfo newPackage)
             throws PackageManagerException {
         final long activeVersion = activePackage.applicationInfo.longVersionCode;
@@ -310,7 +343,7 @@
         final boolean isAppDebuggable = (activePackage.applicationInfo.flags
                 & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         final boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted(
-                session.params.installFlags, isAppDebuggable);
+                session.sessionParams().installFlags, isAppDebuggable);
         if (activeVersion > newVersionCode && !allowsDowngrade) {
             throw new PackageManagerException(
                     SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
@@ -362,10 +395,10 @@
     /**
      * Utility function for extracting apex sessions out of multi-package/single session.
      */
-    private List<PackageInstallerSession> extractApexSessions(PackageInstallerSession session) {
-        List<PackageInstallerSession> apexSessions = new ArrayList<>();
+    private List<StagedSession> extractApexSessions(StagedSession session) {
+        List<StagedSession> apexSessions = new ArrayList<>();
         if (session.isMultiPackage()) {
-            for (PackageInstallerSession s : session.getChildSessions()) {
+            for (StagedSession s : session.getChildSessions()) {
                 if (s.containsApexSession()) {
                     apexSessions.add(s);
                 }
@@ -382,14 +415,14 @@
      *
      * @throws PackageManagerException if any apk-in-apex failed to install
      */
-    private void checkInstallationOfApkInApexSuccessful(PackageInstallerSession session)
+    private void checkInstallationOfApkInApexSuccessful(StagedSession session)
             throws PackageManagerException {
-        final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
+        final List<StagedSession> apexSessions = extractApexSessions(session);
         if (apexSessions.isEmpty()) {
             return;
         }
 
-        for (PackageInstallerSession apexSession : apexSessions) {
+        for (StagedSession apexSession : apexSessions) {
             String packageName = apexSession.getPackageName();
             if (!mApexManager.isApkInApexInstallSuccess(packageName)) {
                 throw new PackageManagerException(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
@@ -404,16 +437,16 @@
      * directory directly by PackageManager, as such, RollbackManager need to handle their data
      * separately here.
      */
-    private void snapshotAndRestoreForApexSession(PackageInstallerSession session) {
+    private void snapshotAndRestoreForApexSession(StagedSession session) {
         boolean doSnapshotOrRestore =
-                (session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
-                || session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
+                (session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
+                || session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
         if (!doSnapshotOrRestore) {
             return;
         }
 
         // Find all the apex sessions that needs processing
-        final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
+        final List<StagedSession> apexSessions = extractApexSessions(session);
         if (apexSessions.isEmpty()) {
             return;
         }
@@ -474,7 +507,7 @@
      *  session package names.
      *  Logging needs to wait until the ACTION_BOOT_COMPLETED broadcast is sent.
      */
-    private void prepareForLoggingApexdRevert(@NonNull PackageInstallerSession session,
+    private void prepareForLoggingApexdRevert(@NonNull StagedSession session,
             @NonNull String nativeFailureReason) {
         synchronized (mFailedPackageNames) {
             mNativeFailureReason = nativeFailureReason;
@@ -484,15 +517,15 @@
         }
     }
 
-    private void resumeSession(@NonNull PackageInstallerSession session)
+    private void resumeSession(@NonNull StagedSession session)
             throws PackageManagerException {
-        Slog.d(TAG, "Resuming session " + session.sessionId);
+        Slog.d(TAG, "Resuming session " + session.sessionId());
 
         final boolean hasApex = session.containsApexSession();
         ApexSessionInfo apexSessionInfo = null;
         if (hasApex) {
             // Check with apexservice whether the apex packages have been activated.
-            apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
+            apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId());
 
             // Prepare for logging a native crash during boot, if one occurred.
             if (apexSessionInfo != null && !TextUtils.isEmpty(
@@ -505,7 +538,7 @@
                 // pre-reboot verification, perhaps because the device rebooted in the meantime.
                 // Greedily re-trigger the pre-reboot verification. We want to avoid marking it as
                 // failed when not in checkpoint mode, hence it is being processed separately.
-                Slog.d(TAG, "Found pending staged session " + session.sessionId + " still to "
+                Slog.d(TAG, "Found pending staged session " + session.sessionId() + " still to "
                         + "be verified, resuming pre-reboot verification");
                 mPreRebootVerificationHandler.startPreRebootVerification(session);
                 return;
@@ -522,21 +555,21 @@
             // mode. If not, we fail all sessions.
             if (supportsCheckpoint() && !needsCheckpoint()) {
                 String revertMsg = "Reverting back to safe state. Marking "
-                        + session.sessionId + " as failed.";
+                        + session.sessionId() + " as failed.";
                 final String reasonForRevert = getReasonForRevert();
                 if (!TextUtils.isEmpty(reasonForRevert)) {
                     revertMsg += " Reason for revert: " + reasonForRevert;
                 }
                 Slog.d(TAG, revertMsg);
-                session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg);
+                session.setSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg);
                 return;
             }
         } catch (RemoteException e) {
             // Cannot continue staged install without knowing if fs-checkpoint is supported
             Slog.e(TAG, "Checkpoint support unknown. Aborting staged install for session "
-                    + session.sessionId, e);
+                    + session.sessionId(), e);
             // TODO: Mark all staged sessions together and reboot only once
-            session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN,
+            session.setSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN,
                     "Checkpoint support unknown. Aborting staged install.");
             if (hasApex) {
                 mApexManager.revertActiveSessions();
@@ -567,7 +600,7 @@
                 // Apexd did not apply the session for some unknown reason. There is no
                 // guarantee that apexd will install it next time. Safer to proactively mark
                 // it as failed.
-                final String errorMsg = "Staged session " + session.sessionId + "at boot "
+                final String errorMsg = "Staged session " + session.sessionId() + "at boot "
                         + "didn't activate nor fail. Marking it as failed anyway.";
                 throw new PackageManagerException(
                         SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
@@ -579,38 +612,38 @@
             checkInstallationOfApkInApexSuccessful(session);
             checkDuplicateApkInApex(session);
             snapshotAndRestoreForApexSession(session);
-            Slog.i(TAG, "APEX packages in session " + session.sessionId
+            Slog.i(TAG, "APEX packages in session " + session.sessionId()
                     + " were successfully activated. Proceeding with APK packages, if any");
         }
         // The APEX part of the session is activated, proceed with the installation of APKs.
-        Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
+        Slog.d(TAG, "Installing APK packages in session " + session.sessionId());
         installApksInSession(session);
 
-        Slog.d(TAG, "Marking session " + session.sessionId + " as applied");
-        session.setStagedSessionApplied();
+        Slog.d(TAG, "Marking session " + session.sessionId() + " as applied");
+        session.setSessionApplied();
         if (hasApex) {
             try {
                 if (supportsCheckpoint()) {
                     // Store the session ID, which will be marked as successful by ApexManager
                     // upon boot completion.
                     synchronized (mSuccessfulStagedSessionIds) {
-                        mSuccessfulStagedSessionIds.add(session.sessionId);
+                        mSuccessfulStagedSessionIds.add(session.sessionId());
                     }
                 } else {
                     // Mark sessions as successful immediately on non-checkpointing devices.
-                    mApexManager.markStagedSessionSuccessful(session.sessionId);
+                    mApexManager.markStagedSessionSuccessful(session.sessionId());
                 }
             } catch (RemoteException e) {
                 Slog.w(TAG, "Checkpoint support unknown, marking session as successful "
                         + "immediately.");
-                mApexManager.markStagedSessionSuccessful(session.sessionId);
+                mApexManager.markStagedSessionSuccessful(session.sessionId());
             }
         }
     }
 
-    void onInstallationFailure(PackageInstallerSession session, PackageManagerException e) {
-        session.setStagedSessionFailed(e.error, e.getMessage());
-        abortCheckpoint(session.sessionId, e.getMessage());
+    void onInstallationFailure(StagedSession session, PackageManagerException e) {
+        session.setSessionFailed(e.error, e.getMessage());
+        abortCheckpoint(session.sessionId(), e.getMessage());
 
         // If checkpoint is not supported, we have to handle failure for one staged session.
         if (!session.containsApexSession()) {
@@ -640,26 +673,26 @@
     /**
      * Throws a PackageManagerException if there are duplicate packages in apk and apk-in-apex.
      */
-    private void checkDuplicateApkInApex(@NonNull PackageInstallerSession session)
+    private void checkDuplicateApkInApex(@NonNull StagedSession session)
             throws PackageManagerException {
         if (!session.isMultiPackage()) {
             return;
         }
         final Set<String> apkNames = new ArraySet<>();
-        for (PackageInstallerSession s : session.getChildSessions()) {
+        for (StagedSession s : session.getChildSessions()) {
             if (!s.isApexSession()) {
                 apkNames.add(s.getPackageName());
             }
         }
-        final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
-        for (PackageInstallerSession apexSession : apexSessions) {
+        final List<StagedSession> apexSessions = extractApexSessions(session);
+        for (StagedSession apexSession : apexSessions) {
             String packageName = apexSession.getPackageName();
             for (String apkInApex : mApexManager.getApksInApex(packageName)) {
                 if (!apkNames.add(apkInApex)) {
                     throw new PackageManagerException(
                             SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
                             "Package: " + packageName + " in session: "
-                                    + apexSession.sessionId + " has duplicate apk-in-apex: "
+                                    + apexSession.sessionId() + " has duplicate apk-in-apex: "
                                     + apkInApex, null);
 
                 }
@@ -667,14 +700,14 @@
         }
     }
 
-    private void installApksInSession(PackageInstallerSession session)
+    private void installApksInSession(StagedSession session)
             throws PackageManagerException {
         if (!session.containsApkSession()) {
             return;
         }
 
         final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync();
-        session.installStagedSession(receiver.getIntentSender());
+        session.installSession(receiver.getIntentSender());
         final Intent result = receiver.getResult();
         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                 PackageInstaller.STATUS_FAILURE);
@@ -682,31 +715,31 @@
             final String errorMessage = result.getStringExtra(
                     PackageInstaller.EXTRA_STATUS_MESSAGE);
             Slog.e(TAG, "Failure to install APK staged session "
-                    + session.sessionId + " [" + errorMessage + "]");
+                    + session.sessionId() + " [" + errorMessage + "]");
             throw new PackageManagerException(
                     SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMessage);
         }
     }
 
-    void commitSession(@NonNull PackageInstallerSession session) {
+    void commitSession(@NonNull StagedSession session) {
         // Store this parent session which will be used to check overlapping later
         createSession(session);
         mPreRebootVerificationHandler.startPreRebootVerification(session);
     }
 
-    private int getSessionIdForParentOrSelf(PackageInstallerSession session) {
-        return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId;
+    private int getSessionIdForParentOrSelf(StagedSession session) {
+        return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId();
     }
 
-    private PackageInstallerSession getParentSessionOrSelf(PackageInstallerSession session) {
+    private StagedSession getParentSessionOrSelf(StagedSession session) {
         return session.hasParentSessionId()
                 ? getStagedSession(session.getParentSessionId())
                 : session;
     }
 
-    private boolean isRollback(PackageInstallerSession session) {
-        final PackageInstallerSession root = getParentSessionOrSelf(session);
-        return root.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
+    private boolean isRollback(StagedSession session) {
+        final StagedSession root = getParentSessionOrSelf(session);
+        return root.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
     }
 
     /**
@@ -720,7 +753,8 @@
      * </ul>
      * @throws PackageManagerException if session fails the check
      */
-    private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+    @VisibleForTesting
+    void checkNonOverlappingWithStagedSessions(@NonNull StagedSession session)
             throws PackageManagerException {
         if (session.isMultiPackage()) {
             // We cannot say a parent session overlaps until we process its children
@@ -730,7 +764,7 @@
         String packageName = session.getPackageName();
         if (packageName == null) {
             throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
-                    "Cannot stage session " + session.sessionId + " with package name null");
+                    "Cannot stage session " + session.sessionId() + " with package name null");
         }
 
         boolean supportsCheckpoint = ((StorageManager) mContext.getSystemService(
@@ -740,18 +774,25 @@
 
         synchronized (mStagedSessions) {
             for (int i = 0; i < mStagedSessions.size(); i++) {
-                final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
+                final StagedSession stagedSession = mStagedSessions.valueAt(i);
                 if (stagedSession.hasParentSessionId() || !stagedSession.isCommitted()
-                        || stagedSession.isStagedAndInTerminalState()
+                        || stagedSession.isInTerminalState()
                         || stagedSession.isDestroyed()) {
                     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
-                if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId) {
-                    Slog.w(TAG, "Session " + session.sessionId + " is already staged");
+                if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId()) {
+                    Slog.w(TAG, "Session " + session.sessionId() + " is already staged");
                     continue;
                 }
 
@@ -760,24 +801,25 @@
                     if (isRollback) {
                         // If the new session is a rollback, then it gets priority. The existing
                         // session is failed to unblock rollback.
-                        final PackageInstallerSession root = stagedSession;
+                        final StagedSession root = stagedSession;
                         if (!ensureActiveApexSessionIsAborted(root)) {
-                            Slog.e(TAG, "Failed to abort apex session " + root.sessionId);
+                            Slog.e(TAG, "Failed to abort apex session " + root.sessionId());
                             // Safe to ignore active apex session abort failure since session
                             // will be marked failed on next step and staging directory for session
                             // will be deleted.
                         }
-                        root.setStagedSessionFailed(
+                        root.setSessionFailed(
                                 SessionInfo.STAGED_SESSION_CONFLICT,
-                                "Session was blocking rollback session: " + session.sessionId);
-                        Slog.i(TAG, "Session " + root.sessionId + " is marked failed due to "
-                                + "blocking rollback session: " + session.sessionId);
+                                "Session was blocking rollback session: " + session.sessionId());
+                        Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
+                                + "blocking rollback session: " + session.sessionId());
                     } else {
                         throw new PackageManagerException(
                                 SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                                 "Package: " + session.getPackageName() + " in session: "
-                                        + session.sessionId + " has been staged already by session:"
-                                        + " " + stagedSession.sessionId, null);
+                                        + session.sessionId()
+                                        + " has been staged already by session: "
+                                        + stagedSession.sessionId(), null);
                     }
                 }
 
@@ -793,24 +835,25 @@
         }
     }
 
-    private void createSession(@NonNull PackageInstallerSession sessionInfo) {
+    @VisibleForTesting
+    void createSession(@NonNull StagedSession sessionInfo) {
         synchronized (mStagedSessions) {
-            mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
+            mStagedSessions.append(sessionInfo.sessionId(), sessionInfo);
         }
     }
 
-    void abortSession(@NonNull PackageInstallerSession session) {
+    void abortSession(@NonNull StagedSession session) {
         synchronized (mStagedSessions) {
-            mStagedSessions.remove(session.sessionId);
+            mStagedSessions.remove(session.sessionId());
         }
     }
 
     /**
      * <p>Abort committed staged session
      */
-    void abortCommittedSession(@NonNull PackageInstallerSession session) {
-        int sessionId = session.sessionId;
-        if (session.isStagedAndInTerminalState()) {
+    void abortCommittedSession(@NonNull StagedSession session) {
+        int sessionId = session.sessionId();
+        if (session.isInTerminalState()) {
             Slog.w(TAG, "Cannot abort session in final state: " + sessionId);
             return;
         }
@@ -824,12 +867,12 @@
         }
 
         // A session could be marked ready once its pre-reboot verification ends
-        if (session.isStagedSessionReady()) {
+        if (session.isSessionReady()) {
             if (!ensureActiveApexSessionIsAborted(session)) {
                 // Failed to ensure apex session is aborted, so it can still be staged. We can still
                 // safely cleanup the staged session since pre-reboot verification is complete.
                 // Also, cleaning up the stageDir prevents the apex from being activated.
-                Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+                Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
             }
         }
 
@@ -843,15 +886,15 @@
      *
      * @return returns true if it is ensured that there is no active apex session, otherwise false
      */
-    private boolean ensureActiveApexSessionIsAborted(PackageInstallerSession session) {
+    private boolean ensureActiveApexSessionIsAborted(StagedSession session) {
         if (!session.containsApexSession()) {
             return true;
         }
-        final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId);
+        final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId());
         if (apexSession == null || isApexSessionFinalized(apexSession)) {
             return true;
         }
-        return mApexManager.abortStagedSession(session.sessionId);
+        return mApexManager.abortStagedSession(session.sessionId());
     }
 
     private boolean isApexSessionFinalized(ApexSessionInfo session) {
@@ -868,7 +911,7 @@
                 || apexSessionInfo.isRevertFailed;
     }
 
-    void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
+    void restoreSession(@NonNull StagedSession session, boolean isDeviceUpgrading) {
         if (session.hasParentSessionId()) {
             // Only parent sessions can be restored
             return;
@@ -877,16 +920,16 @@
         createSession(session);
         // The preconditions used during pre-reboot verification might have changed when device
         // is upgrading. Updated staged sessions to activation failed before we resume the session.
-        PackageInstallerSession sessionToResume = session;
-        if (isDeviceUpgrading && !sessionToResume.isStagedAndInTerminalState()) {
-            sessionToResume.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+        StagedSession sessionToResume = session;
+        if (isDeviceUpgrading && !sessionToResume.isInTerminalState()) {
+            sessionToResume.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
                         "Build fingerprint has changed");
             return;
         }
         checkStateAndResume(sessionToResume);
     }
 
-    private void checkStateAndResume(@NonNull PackageInstallerSession session) {
+    private void checkStateAndResume(@NonNull StagedSession session) {
         // Do not resume session if boot completed already
         if (SystemProperties.getBoolean("sys.boot_completed", false)) {
             return;
@@ -897,7 +940,7 @@
             return;
         }
         // Check the state of the session and decide what to do next.
-        if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) {
+        if (session.isSessionFailed() || session.isSessionApplied()) {
             // Final states, nothing to do.
             return;
         }
@@ -906,7 +949,7 @@
             session.abandon();
             return;
         }
-        if (!session.isStagedSessionReady()) {
+        if (!session.isSessionReady()) {
             // The framework got restarted before the pre-reboot verification could complete,
             // restart the verification.
             mPreRebootVerificationHandler.startPreRebootVerification(session);
@@ -988,8 +1031,8 @@
         }
     }
 
-    private PackageInstallerSession getStagedSession(int sessionId) {
-        PackageInstallerSession session;
+    private StagedSession getStagedSession(int sessionId) {
+        StagedSession session;
         synchronized (mStagedSessions) {
             session = mStagedSessions.get(sessionId);
         }
@@ -999,20 +1042,20 @@
     // TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
     //  verification logic is extracted out of StagingManager into PMS, we can remove
     //  this.
-    void notifyVerificationComplete(PackageInstallerSession session) {
+    void notifyVerificationComplete(StagedSession session) {
         mPreRebootVerificationHandler.onPreRebootVerificationComplete(session);
     }
 
     // TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
     //  verification logic is extracted out of StagingManager into PMS, we can remove
     //  this.
-    void notifyPreRebootVerification_Apk_Complete(@NonNull PackageInstallerSession session) {
+    void notifyPreRebootVerification_Apk_Complete(@NonNull StagedSession session) {
         mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
     }
 
     private final class PreRebootVerificationHandler extends Handler {
         // Hold sessions before handler gets ready to do the verification.
-        private List<PackageInstallerSession> mPendingSessions;
+        private List<StagedSession> mPendingSessions;
         private boolean mIsReady;
 
         PreRebootVerificationHandler(Looper looper) {
@@ -1042,8 +1085,8 @@
         public void handleMessage(Message msg) {
             final int sessionId = msg.arg1;
             final int rollbackId = msg.arg2;
-            final PackageInstallerSession session = (PackageInstallerSession) msg.obj;
-            if (session.isDestroyed() || session.isStagedSessionFailed()) {
+            final StagedSession session = (StagedSession) msg.obj;
+            if (session.isDestroyed() || session.isSessionFailed()) {
                 // No point in running verification on a destroyed/failed session
                 onPreRebootVerificationComplete(session);
                 return;
@@ -1076,7 +1119,7 @@
             mIsReady = true;
             if (mPendingSessions != null) {
                 for (int i = 0; i < mPendingSessions.size(); i++) {
-                    PackageInstallerSession session = mPendingSessions.get(i);
+                    StagedSession session = mPendingSessions.get(i);
                     startPreRebootVerification(session);
                 }
                 mPendingSessions = null;
@@ -1085,7 +1128,7 @@
 
         // Method for starting the pre-reboot verification
         private synchronized void startPreRebootVerification(
-                @NonNull PackageInstallerSession session) {
+                @NonNull StagedSession session) {
             if (!mIsReady) {
                 if (mPendingSessions == null) {
                     mPendingSessions = new ArrayList<>();
@@ -1094,47 +1137,47 @@
                 return;
             }
 
-            if (session.notifyStagedStartPreRebootVerification()) {
-                int sessionId = session.sessionId;
+            if (session.notifyStartPreRebootVerification()) {
+                int sessionId = session.sessionId();
                 Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
                 obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
                         .sendToTarget();
             }
         }
 
-        private void onPreRebootVerificationFailure(PackageInstallerSession session,
+        private void onPreRebootVerificationFailure(StagedSession session,
                 @SessionInfo.StagedSessionErrorCode int errorCode, String errorMessage) {
             if (!ensureActiveApexSessionIsAborted(session)) {
-                Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+                Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
                 // Safe to ignore active apex session abortion failure since session will be marked
                 // failed on next step and staging directory for session will be deleted.
             }
-            session.setStagedSessionFailed(errorCode, errorMessage);
+            session.setSessionFailed(errorCode, errorMessage);
             onPreRebootVerificationComplete(session);
         }
 
         // Things to do when pre-reboot verification completes for a particular sessionId
-        private void onPreRebootVerificationComplete(PackageInstallerSession session) {
-            int sessionId = session.sessionId;
+        private void onPreRebootVerificationComplete(StagedSession session) {
+            int sessionId = session.sessionId();
             Slog.d(TAG, "Stopping preRebootVerification for session " + sessionId);
-            session.notifyStagedEndPreRebootVerification();
+            session.notifyEndPreRebootVerification();
         }
 
         private void notifyPreRebootVerification_Start_Complete(
-                @NonNull PackageInstallerSession session, int rollbackId) {
-            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId, rollbackId, session)
-                    .sendToTarget();
+                @NonNull StagedSession session, int rollbackId) {
+            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId(), rollbackId,
+                    session).sendToTarget();
         }
 
         private void notifyPreRebootVerification_Apex_Complete(
-                @NonNull PackageInstallerSession session) {
-            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId, -1, session)
+                @NonNull StagedSession session) {
+            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId(), -1, session)
                     .sendToTarget();
         }
 
         private void notifyPreRebootVerification_Apk_Complete(
-                @NonNull PackageInstallerSession session) {
-            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId, -1, session)
+                @NonNull StagedSession session) {
+            obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId(), -1, session)
                     .sendToTarget();
         }
 
@@ -1143,10 +1186,10 @@
          *
          * See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
          */
-        private void handlePreRebootVerification_Start(@NonNull PackageInstallerSession session) {
+        private void handlePreRebootVerification_Start(@NonNull StagedSession session) {
             try {
                 if (session.isMultiPackage()) {
-                    for (PackageInstallerSession s : session.getChildSessions()) {
+                    for (StagedSession s : session.getChildSessions()) {
                         checkNonOverlappingWithStagedSessions(s);
                     }
                 } else {
@@ -1158,7 +1201,8 @@
             }
 
             int rollbackId = -1;
-            if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
+            if ((session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK)
+                    != 0) {
                 // If rollback is enabled for this session, we call through to the RollbackManager
                 // with the list of sessions it must enable rollback for. Note that
                 // notifyStagedSession is a synchronous operation.
@@ -1167,14 +1211,15 @@
                 try {
                     // NOTE: To stay consistent with the non-staged install flow, we don't fail the
                     // entire install if rollbacks can't be enabled.
-                    rollbackId = rm.notifyStagedSession(session.sessionId);
+                    rollbackId = rm.notifyStagedSession(session.sessionId());
                 } catch (RuntimeException re) {
                     Slog.e(TAG, "Failed to notifyStagedSession for session: "
-                            + session.sessionId, re);
+                            + session.sessionId(), re);
                 }
-            } else if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+            } else if (session.sessionParams().installReason
+                    == PackageManager.INSTALL_REASON_ROLLBACK) {
                 try {
-                    rollbackId = retrieveRollbackIdForCommitSession(session.sessionId);
+                    rollbackId = retrieveRollbackIdForCommitSession(session.sessionId());
                 } catch (PackageManagerException e) {
                     onPreRebootVerificationFailure(session, e.error, e.getMessage());
                     return;
@@ -1193,7 +1238,7 @@
          * </ul></p>
          */
         private void handlePreRebootVerification_Apex(
-                @NonNull PackageInstallerSession session, int rollbackId) {
+                @NonNull StagedSession session, int rollbackId) {
             final boolean hasApex = session.containsApexSession();
 
             // APEX checks. For single-package sessions, check if they contain an APEX. For
@@ -1223,12 +1268,12 @@
          * {@link PackageManagerService} for verification and it notifies back the result via
          * {@link #notifyPreRebootVerification_Apk_Complete}
          */
-        private void handlePreRebootVerification_Apk(@NonNull PackageInstallerSession session) {
+        private void handlePreRebootVerification_Apk(@NonNull StagedSession session) {
             if (!session.containsApkSession()) {
                 notifyPreRebootVerification_Apk_Complete(session);
                 return;
             }
-            session.verifyStagedSession();
+            session.verifySession();
         }
 
         /**
@@ -1238,7 +1283,7 @@
          *     <li>marks session as ready</li>
          * </ul></p>
          */
-        private void handlePreRebootVerification_End(@NonNull PackageInstallerSession session) {
+        private void handlePreRebootVerification_End(@NonNull StagedSession session) {
             // Before marking the session as ready, start checkpoint service if available
             try {
                 IStorageManager storageManager = PackageHelper.getStorageManager();
@@ -1270,15 +1315,15 @@
             // On the other hand, if the order of the calls was inverted (first call apexd, then
             // mark session as ready), then if a device gets rebooted right after the call to apexd,
             // only apex part of the train will be applied, leaving device in an inconsistent state.
-            Slog.d(TAG, "Marking session " + session.sessionId + " as ready");
-            session.setStagedSessionReady();
-            if (session.isStagedSessionReady()) {
+            Slog.d(TAG, "Marking session " + session.sessionId() + " as ready");
+            session.setSessionReady();
+            if (session.isSessionReady()) {
                 final boolean hasApex = session.containsApexSession();
                 if (hasApex) {
                     try {
-                        mApexManager.markStagedSessionReady(session.sessionId);
+                        mApexManager.markStagedSessionReady(session.sessionId());
                     } catch (PackageManagerException e) {
-                        session.setStagedSessionFailed(e.error, e.getMessage());
+                        session.setSessionFailed(e.error, e.getMessage());
                         return;
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
index a098484..7ca9f05 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
@@ -99,52 +99,6 @@
      */
     void scheduleReadDefaultPermissionExceptions();
 
-    // TODO(zhanghai): The following methods should be moved to a new AIDL to support
-    //  the legacy PermissionManager directly in a later CL.
-
-    /**
-     * Grant default permissions to currently active LUI app
-     * @param packageName The package name for the LUI app
-     * @param userId The user ID
-     */
-    void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId);
-
-    /**
-     * Revoke default permissions to currently active LUI app
-     * @param packageNames The package names for the LUI apps
-     * @param userId The user ID
-     */
-    void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId);
-
-    /**
-     * Grant default permissions to currently active Ims services
-     * @param packageNames The package names for the Ims services
-     * @param userId The user ID
-     */
-    void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId);
-
-    /**
-     * Grant default permissions to currently enabled telephony data services
-     * @param packageNames The package name for the services
-     * @param userId The user ID
-     */
-    void grantDefaultPermissionsToEnabledTelephonyDataServices(String[] packageNames, int userId);
-
-    /**
-     * Revoke default permissions to currently active telephony data services
-     * @param packageNames The package name for the services
-     * @param userId The IDhandle
-     */
-    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(String[] packageNames,
-            int userId);
-
-    /**
-     * Grant default permissions to currently enabled carrier apps
-     * @param packageNames Package names of the apps to be granted permissions
-     * @param userId The user ID
-     */
-    void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId);
-
     /**
      * Provider for package names.
      */
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
index 0c0a8df..f453d74 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
@@ -17,16 +17,31 @@
 package com.android.server.pm.permission;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.permission.ILegacyPermissionManager;
+import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.pm.PackageManagerServiceUtils;
 
 /**
  * Legacy permission manager service.
  */
-public class LegacyPermissionManagerService {
+public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stub {
+    private static final String TAG = "PackageManager";
+
+    /** Injector that can be used to facilitate testing. */
+    private final Injector mInjector;
+
     @NonNull
     private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
 
@@ -51,8 +66,126 @@
     }
 
     private LegacyPermissionManagerService(@NonNull Context context) {
-        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(context);
+        this(context, new Injector(context));
+
         LocalServices.addService(LegacyPermissionManagerInternal.class, new Internal());
+        ServiceManager.addService("legacy_permission", this);
+    }
+
+    @VisibleForTesting
+    LegacyPermissionManagerService(@NonNull Context context, @NonNull Injector injector) {
+        mInjector = injector;
+        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(context);
+    }
+
+    @Override
+    public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
+            @Nullable String callingFeatureId, int pid, int uid) {
+        // If the check is being requested by an app then only allow the app to query its own
+        // access status.
+        int callingUid = mInjector.getCallingUid();
+        int callingPid = mInjector.getCallingPid();
+        if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid
+                || callingPid != pid)) {
+            String response = String.format(
+                    "Calling uid %d, pid %d cannot check device identifier access for package %s "
+                            + "(uid=%d, pid=%d)",
+                    callingUid, callingPid, packageName, uid, pid);
+            Log.w(TAG, response);
+            throw new SecurityException(response);
+        }
+        // Allow system and root access to the device identifiers.
+        final int appId = UserHandle.getAppId(uid);
+        if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+        // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission.
+        if (mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid,
+                uid) == PackageManager.PERMISSION_GRANTED) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+        // If the calling package is not null then perform the appop and device / profile owner
+        // check.
+        if (packageName != null) {
+            // Allow access to a package that has been granted the READ_DEVICE_IDENTIFIERS appop.
+            final long token = mInjector.clearCallingIdentity();
+            AppOpsManager appOpsManager = (AppOpsManager) mInjector.getSystemService(
+                    Context.APP_OPS_SERVICE);
+            try {
+                if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
+                        packageName, callingFeatureId, message) == AppOpsManager.MODE_ALLOWED) {
+                    return PackageManager.PERMISSION_GRANTED;
+                }
+            } finally {
+                mInjector.restoreCallingIdentity(token);
+            }
+            // Check if the calling packages meets the device / profile owner requirements for
+            // identifier access.
+            DevicePolicyManager devicePolicyManager =
+                    (DevicePolicyManager) mInjector.getSystemService(Context.DEVICE_POLICY_SERVICE);
+            if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess(
+                    packageName, pid, uid)) {
+                return PackageManager.PERMISSION_GRANTED;
+            }
+        }
+        return PackageManager.PERMISSION_DENIED;
+    }
+
+    @Override
+    public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "grantDefaultPermissionsToActiveLuiApp", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
+    }
+
+    @Override
+    public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "revokeDefaultPermissionsFromLuiApps", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
+    }
+
+    @Override
+    public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "grantDefaultPermissionsToEnabledImsServices", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
+    }
+
+    @Override
+    public void grantDefaultPermissionsToEnabledTelephonyDataServices(
+            String[] packageNames, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId));
+    }
+
+    @Override
+    public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+            String[] packageNames, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames,
+                        userId));
+    }
+
+    @Override
+    public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
+                "grantPermissionsToEnabledCarrierApps", callingUid);
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
     }
 
     private class Internal implements LegacyPermissionManagerInternal {
@@ -117,65 +250,74 @@
         public void scheduleReadDefaultPermissionExceptions() {
             mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
         }
+    }
 
-        // TODO(zhanghai): The following methods should be moved to a new AIDL to support
-        //  the legacy PermissionManager directly in a later CL.
+    /**
+     * Allows injection of services and method responses to facilitate testing.
+     *
+     * <p>Test classes can create a mock of this class and pass it to the PermissionManagerService
+     * constructor to control behavior of services and external methods during execution.
+     * @hide
+     */
+    @VisibleForTesting
+    public static class Injector {
+        private final Context mContext;
 
-        @Override
-        public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "grantDefaultPermissionsToActiveLuiApp", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
+        /**
+         * Public constructor that accepts a {@code context} within which to operate.
+         */
+        public Injector(@NonNull Context context) {
+            mContext = context;
         }
 
-        @Override
-        public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "revokeDefaultPermissionsFromLuiApps", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
+        /**
+         * Returns the UID of the calling package.
+         */
+        public int getCallingUid() {
+            return Binder.getCallingUid();
         }
 
-        @Override
-        public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "grantDefaultPermissionsToEnabledImsServices", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
+        /**
+         * Returns the process ID of the calling package.
+         */
+        public int getCallingPid() {
+            return Binder.getCallingPid();
         }
 
-        @Override
-        public void grantDefaultPermissionsToEnabledTelephonyDataServices(
-                String[] packageNames, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId));
+        /**
+         * Checks if the package running under the specified {@code pid} and {@code uid} has been
+         * granted the provided {@code permission}.
+         *
+         * @return {@link PackageManager#PERMISSION_GRANTED} if the package has been granted the
+         * permission, {@link PackageManager#PERMISSION_DENIED} otherwise
+         */
+        public int checkPermission(@NonNull String permission, int pid, int uid) {
+            return mContext.checkPermission(permission, pid, uid);
         }
 
-        @Override
-        public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-                String[] packageNames, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames,
-                            userId));
+        /**
+         * Clears the calling identity to allow subsequent calls to be treated as coming from this
+         * package.
+         *
+         * @return a token that can be used to restore the calling identity
+         */
+        public long clearCallingIdentity() {
+            return Binder.clearCallingIdentity();
         }
 
-        @Override
-        public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
-                    "grantPermissionsToEnabledCarrierApps", callingUid);
-            Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
-                    .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
+        /**
+         * Restores the calling identity to that of the calling package based on the provided
+         * {@code token}.
+         */
+        public void restoreCallingIdentity(long token) {
+            Binder.restoreCallingIdentity(token);
+        }
+
+        /**
+         * Returns the system service with the provided {@code name}.
+         */
+        public Object getSystemService(@NonNull String name) {
+            return mContext.getSystemService(name);
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index 995b59e..30c334d 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -61,6 +61,7 @@
             PermissionInfo.PROTECTION_NORMAL,
             PermissionInfo.PROTECTION_SIGNATURE,
             PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM,
+            PermissionInfo.PROTECTION_INTERNAL,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionLevel {}
@@ -246,6 +247,11 @@
                 == PermissionInfo.PROTECTION_SIGNATURE;
     }
 
+    public boolean isInternal() {
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                == PermissionInfo.PROTECTION_INTERNAL;
+    }
+
     public boolean isAppOp() {
         return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
     }
@@ -335,6 +341,10 @@
         return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0;
     }
 
+    public boolean isRole() {
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_ROLE) != 0;
+    }
+
     public void transfer(@NonNull String oldPackageName, @NonNull String newPackageName) {
         if (!oldPackageName.equals(mPermissionInfo.packageName)) {
             return;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 389010a..2107536f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -66,9 +66,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
-import android.app.ApplicationPackageManager;
 import android.app.IActivityManager;
-import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.role.RoleManager;
 import android.compat.annotation.ChangeId;
@@ -126,7 +124,6 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -160,6 +157,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -263,9 +261,6 @@
     @NonNull
     private final PermissionRegistry mRegistry = new PermissionRegistry();
 
-    /** Injector that can be used to facilitate testing. */
-    private final Injector mInjector;
-
     @GuardedBy("mLock")
     @Nullable
     private ArraySet<String> mPrivappPermissionsViolations;
@@ -363,17 +358,11 @@
     };
 
     PermissionManagerService(@NonNull Context context) {
-        this(context, new Injector(context));
-    }
-
-    @VisibleForTesting
-    PermissionManagerService(@NonNull Context context, @NonNull Injector injector) {
-        mInjector = injector;
         // The package info cache is the cache for package and permission information.
         // Disable the package info and package permission caches locally but leave the
         // checkPermission cache active.
-        mInjector.invalidatePackageInfoCache();
-        mInjector.disablePackageNamePermissionCache();
+        PackageManager.invalidatePackageInfoCache();
+        PermissionManager.disablePackageNamePermissionCache();
 
         mContext = context;
         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
@@ -805,8 +794,8 @@
     private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
             int flagValues, int callingUid, int userId, boolean overridePolicy,
             PermissionCallback callback) {
-        if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+        if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
+                && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
             Log.i(TAG, "System is updating flags for " + packageName + " "
                             + permName + " for user " + userId  + " "
                             + DebugUtils.flagsToString(
@@ -1112,59 +1101,6 @@
     }
 
     @Override
-    public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
-            @Nullable String callingFeatureId, int pid, int uid) {
-        // If the check is being requested by an app then only allow the app to query its own
-        // access status.
-        int callingUid = mInjector.getCallingUid();
-        int callingPid = mInjector.getCallingPid();
-        if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid
-                || callingPid != pid)) {
-            String response = String.format(
-                    "Calling uid %d, pid %d cannot check device identifier access for package %s "
-                            + "(uid=%d, pid=%d)",
-                    callingUid, callingPid, packageName, uid, pid);
-            Log.w(TAG, response);
-            throw new SecurityException(response);
-        }
-        // Allow system and root access to the device identifiers.
-        final int appId = UserHandle.getAppId(uid);
-        if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
-        // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission.
-        if (mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid,
-                uid) == PackageManager.PERMISSION_GRANTED) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
-        // If the calling package is not null then perform the appop and device / profile owner
-        // check.
-        if (packageName != null) {
-            // Allow access to a package that has been granted the READ_DEVICE_IDENTIFIERS appop.
-            final long token = mInjector.clearCallingIdentity();
-            AppOpsManager appOpsManager = (AppOpsManager) mInjector.getSystemService(
-                    Context.APP_OPS_SERVICE);
-            try {
-                if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
-                        packageName, callingFeatureId, message) == AppOpsManager.MODE_ALLOWED) {
-                    return PackageManager.PERMISSION_GRANTED;
-                }
-            } finally {
-                mInjector.restoreCallingIdentity(token);
-            }
-            // Check if the calling packages meets the device / profile owner requirements for
-            // identifier access.
-            DevicePolicyManager devicePolicyManager =
-                    (DevicePolicyManager) mInjector.getSystemService(Context.DEVICE_POLICY_SERVICE);
-            if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess(
-                    packageName, pid, uid)) {
-                return PackageManager.PERMISSION_GRANTED;
-            }
-        }
-        return PackageManager.PERMISSION_DENIED;
-    }
-
-    @Override
     public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
         mContext.enforceCallingOrSelfPermission(
                 Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
@@ -1181,8 +1117,9 @@
         mOnPermissionChangeListeners.removeListener(listener);
     }
 
+    @Nullable
     @Override
-    @Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
+    public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
             @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
         Objects.requireNonNull(packageName);
         Preconditions.checkFlagsArgument(flags,
@@ -1195,7 +1132,7 @@
         if (UserHandle.getCallingUserId() != userId) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS,
-                    "getWhitelistedRestrictedPermissions for user " + userId);
+                    "getAllowlistedRestrictedPermissions for user " + userId);
         }
 
         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1281,7 +1218,7 @@
     }
 
     @Override
-    public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
+    public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
             @NonNull String permName, @PermissionWhitelistFlags int flags,
             @UserIdInt int userId) {
         // Other argument checks are done in get/setAllowlistedRestrictedPermissions
@@ -1292,7 +1229,7 @@
         }
 
         List<String> permissions =
-                getWhitelistedRestrictedPermissions(packageName, flags, userId);
+                getAllowlistedRestrictedPermissions(packageName, flags, userId);
         if (permissions == null) {
             permissions = new ArrayList<>(1);
         }
@@ -1319,14 +1256,14 @@
         if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
                 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
                 != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Cannot modify whitelisting of an immutably "
+            throw new SecurityException("Cannot modify allowlisting of an immutably "
                     + "restricted permission: " + permName);
         }
         return true;
     }
 
     @Override
-    public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
+    public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
             @NonNull String permName, @PermissionWhitelistFlags int flags,
             @UserIdInt int userId) {
         // Other argument checks are done in get/setAllowlistedRestrictedPermissions
@@ -1337,7 +1274,7 @@
         }
 
         final List<String> permissions =
-                getWhitelistedRestrictedPermissions(packageName, flags, userId);
+                getAllowlistedRestrictedPermissions(packageName, flags, userId);
         if (permissions != null && permissions.remove(permName)) {
             return setAllowlistedRestrictedPermissions(packageName, permissions,
                     flags, userId);
@@ -1392,20 +1329,20 @@
                         + " being installer on record or "
                         + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
             }
-            final List<String> whitelistedPermissions =
-                    getWhitelistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
+            final List<String> allowlistedPermissions =
+                    getAllowlistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
             if (permissions == null || permissions.isEmpty()) {
-                if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
+                if (allowlistedPermissions == null || allowlistedPermissions.isEmpty()) {
                     return true;
                 }
             } else {
                 // Only the system can add and remove while the installer can only remove.
                 final int permissionCount = permissions.size();
                 for (int i = 0; i < permissionCount; i++) {
-                    if ((whitelistedPermissions == null
-                            || !whitelistedPermissions.contains(permissions.get(i)))
+                    if ((allowlistedPermissions == null
+                            || !allowlistedPermissions.contains(permissions.get(i)))
                             && !isCallerPrivileged) {
-                        throw new SecurityException("Adding to upgrade whitelist requires"
+                        throw new SecurityException("Adding to upgrade allowlist requires"
                                 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
                     }
                 }
@@ -1413,7 +1350,7 @@
 
             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
                 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
-                    throw new SecurityException("Modifying installer whitelist requires"
+                    throw new SecurityException("Modifying installer allowlist requires"
                             + " being installer on record or "
                             + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
                 }
@@ -1431,8 +1368,8 @@
     }
 
     @Override
-    public boolean setAutoRevokeWhitelisted(
-            @NonNull String packageName, boolean whitelisted, int userId) {
+    public boolean setAutoRevokeExempted(
+            @NonNull String packageName, boolean exempted, int userId) {
         Objects.requireNonNull(packageName);
 
         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1442,7 +1379,7 @@
             return false;
         }
 
-        return setAutoRevokeExemptedInternal(pkg, whitelisted, userId);
+        return setAutoRevokeExemptedInternal(pkg, exempted, userId);
     }
 
     private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
@@ -1450,7 +1387,7 @@
         final int packageUid = UserHandle.getUid(userId, pkg.getUid());
         if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
                 packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
-            // Whitelist user set - don't override
+            // Allowlist user set - don't override
             return false;
         }
 
@@ -1484,7 +1421,7 @@
     }
 
     @Override
-    public boolean isAutoRevokeWhitelisted(@NonNull String packageName, int userId) {
+    public boolean isAutoRevokeExempted(@NonNull String packageName, int userId) {
         Objects.requireNonNull(packageName);
 
         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1519,8 +1456,8 @@
     // TODO swap permission name and package name
     private void grantRuntimePermissionInternal(String permName, String packageName,
             boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
-        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+        if (PermissionManager.DEBUG_TRACE_GRANTS
+                && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
             Log.i(TAG, "System is granting " + packageName + " "
                     + permName + " for user " + userId + " on behalf of uid " + callingUid
                     + " " + mPackageManagerInt.getNameForUid(callingUid),
@@ -1550,18 +1487,24 @@
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
+        final boolean isRolePermission;
         final boolean isSoftRestrictedPermission;
         synchronized (mLock) {
             final Permission permission = mRegistry.getPermission(permName);
-            isSoftRestrictedPermission = permission != null && permission.isSoftRestricted();
+            if (permission == null) {
+                throw new IllegalArgumentException("Unknown permission: " + permName);
+            }
+            isRolePermission = permission.isRole();
+            isSoftRestrictedPermission = permission.isSoftRestricted();
         }
+        final boolean mayGrantRolePermission = isRolePermission
+                && mayManageRolePermission(callingUid);
         final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
                 && SoftRestrictedPermissionPolicy.forPermission(mContext,
                         pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
                         .mayGrantPermission();
 
         final boolean isRuntimePermission;
-        final boolean isDevelopmentPermission;
         final boolean permissionHasGids;
         synchronized (mLock) {
             final Permission bp = mRegistry.getPermission(permName);
@@ -1570,9 +1513,14 @@
             }
 
             isRuntimePermission = bp.isRuntime();
-            isDevelopmentPermission = bp.isDevelopment();
             permissionHasGids = bp.hasGids();
-            if (!(isRuntimePermission || isDevelopmentPermission)) {
+            if (isRuntimePermission || bp.isDevelopment()) {
+                // Good.
+            } else if (bp.isRole()) {
+                if (!mayGrantRolePermission) {
+                    throw new SecurityException("Permission " + permName + " is managed by role");
+                }
+            } else {
                 throw new SecurityException("Permission " + permName + " requested by "
                         + pkg.getPackageName() + " is not a changeable permission type");
             }
@@ -1623,7 +1571,7 @@
                 return;
             }
 
-            if (bp.isDevelopment()) {
+            if (bp.isDevelopment() || bp.isRole()) {
                 // Development permissions must be handled specially, since they are not
                 // normal runtime permissions.  For now they apply to all users.
                 // TODO(zhanghai): We are breaking the behavior above by making all permission state
@@ -1654,10 +1602,10 @@
 
         final int uid = UserHandle.getUid(userId, pkg.getUid());
         if (callback != null) {
-            if (isDevelopmentPermission) {
-                callback.onInstallPermissionGranted();
-            } else {
+            if (isRuntimePermission) {
                 callback.onPermissionGranted(uid, userId);
+            } else {
+                callback.onInstallPermissionGranted();
             }
             if (permissionHasGids) {
                 callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
@@ -1685,8 +1633,8 @@
     private void revokeRuntimePermissionInternal(String permName, String packageName,
             boolean overridePolicy, int callingUid, final int userId, String reason,
             PermissionCallback callback) {
-        if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+        if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
+                && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
             Log.i(TAG, "System is revoking " + packageName + " "
                             + permName + " for user " + userId + " on behalf of uid " + callingUid
                             + " " + mPackageManagerInt.getNameForUid(callingUid),
@@ -1715,8 +1663,18 @@
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
+        final boolean isRolePermission;
+        synchronized (mLock) {
+            final Permission permission = mRegistry.getPermission(permName);
+            if (permission == null) {
+                throw new IllegalArgumentException("Unknown permission: " + permName);
+            }
+            isRolePermission = permission.isRole();
+        }
+        final boolean mayRevokeRolePermission = isRolePermission
+                && mayManageRolePermission(callingUid);
+
         final boolean isRuntimePermission;
-        final boolean isDevelopmentPermission;
         synchronized (mLock) {
             final Permission bp = mRegistry.getPermission(permName);
             if (bp == null) {
@@ -1724,8 +1682,13 @@
             }
 
             isRuntimePermission = bp.isRuntime();
-            isDevelopmentPermission = bp.isDevelopment();
-            if (!(isRuntimePermission || isDevelopmentPermission)) {
+            if (isRuntimePermission || bp.isDevelopment()) {
+                // Good.
+            } else if (bp.isRole()) {
+                if (!mayRevokeRolePermission) {
+                    throw new SecurityException("Permission " + permName + " is managed by role");
+                }
+            } else {
                 throw new SecurityException("Permission " + permName + " requested by "
                         + pkg.getPackageName() + " is not a changeable permission type");
             }
@@ -1777,11 +1740,11 @@
         }
 
         if (callback != null) {
-            if (isDevelopmentPermission) {
-                mDefaultPermissionCallback.onInstallPermissionRevoked();
-            } else {
+            if (isRuntimePermission) {
                 callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
                         reason);
+            } else {
+                mDefaultPermissionCallback.onInstallPermissionRevoked();
             }
         }
 
@@ -1790,6 +1753,17 @@
         }
     }
 
+    private boolean mayManageRolePermission(int uid) {
+        final PackageManager packageManager = mContext.getPackageManager();
+        final String[] packageNames = packageManager.getPackagesForUid(uid);
+        if (packageNames == null) {
+            return false;
+        }
+        final String permissionControllerPackageName =
+                packageManager.getPermissionControllerPackageName();
+        return Arrays.asList(packageNames).contains(permissionControllerPackageName);
+    }
+
     @Override
     public void resetRuntimePermissions() {
         mContext.enforceCallingOrSelfPermission(
@@ -1999,44 +1973,6 @@
         mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true);
     }
 
-    @Override
-    public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
-    }
-
-    @Override
-    public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .grantDefaultPermissionsToEnabledImsServices(packageNames, userId);
-    }
-
-    @Override
-    public void grantDefaultPermissionsToEnabledTelephonyDataServices(
-            String[] packageNames, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId);
-    }
-
-    @Override
-    public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-            String[] packageNames, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, userId);
-    }
-
-    @Override
-    public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .grantDefaultPermissionsToActiveLuiApp(packageName, userId);
-    }
-
-    @Override
-    public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
-        LocalServices.getService(LegacyPermissionManagerInternal.class)
-                .revokeDefaultPermissionsFromLuiApps(packageNames, userId);
-    }
-
     /**
      * This change makes it so that apps are told to show rationale for asking for background
      * location access every time they request.
@@ -2679,7 +2615,8 @@
         boolean runtimePermissionsRevoked = false;
         int[] updatedUserIds = EMPTY_INT_ARRAY;
 
-        final ArraySet<String> shouldGrantSignaturePermission = new ArraySet<>();
+        ArraySet<String> shouldGrantSignaturePermission = null;
+        ArraySet<String> shouldGrantInternalPermission = null;
         final List<String> requestedPermissions = pkg.getRequestedPermissions();
         final int requestedPermissionsSize = requestedPermissions.size();
         for (int i = 0; i < requestedPermissionsSize; i++) {
@@ -2692,9 +2629,20 @@
             if (permission == null) {
                 continue;
             }
-            if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps, permission)) {
+            if (permission.isSignature() && (shouldGrantSignaturePermission(pkg, permission)
+                    || shouldGrantPermissionByProtectionFlags(pkg, ps, permission))) {
+                if (shouldGrantSignaturePermission == null) {
+                    shouldGrantSignaturePermission = new ArraySet<>();
+                }
                 shouldGrantSignaturePermission.add(permissionName);
             }
+            if (permission.isInternal()
+                    && shouldGrantPermissionByProtectionFlags(pkg, ps, permission)) {
+                if (shouldGrantInternalPermission == null) {
+                    shouldGrantInternalPermission = new ArraySet<>();
+                }
+                shouldGrantInternalPermission.add(permissionName);
+            }
         }
 
         final SparseBooleanArray isPermissionPolicyInitialized = new SparseBooleanArray();
@@ -2835,12 +2783,13 @@
                             // TODO(zhanghai): This calls into SystemConfig, which generally
                             //  shouldn't  cause deadlock, but maybe we should keep a cache of the
                             //  split permission  list and just eliminate the possibility.
-                            final List<SplitPermissionInfoParcelable> permissionList =
-                                    getSplitPermissions();
+                            final List<PermissionManager.SplitPermissionInfo> permissionList =
+                                    getSplitPermissionInfos();
                             int numSplitPerms = permissionList.size();
                             for (int splitPermNum = 0; splitPermNum < numSplitPerms;
                                     splitPermNum++) {
-                                SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
+                                PermissionManager.SplitPermissionInfo sp = permissionList.get(
+                                        splitPermNum);
                                 String splitPermName = sp.getSplitPermission();
                                 if (sp.getNewPermissions().contains(permName)
                                         && origState.isPermissionGranted(splitPermName)) {
@@ -2904,9 +2853,17 @@
                                 + pkg.getPackageName());
                     }
 
-                    if ((bp.isNormal() && shouldGrantNormalPermission) || (bp.isSignature()
-                            && (shouldGrantSignaturePermission.contains(permName)
-                            || (bp.isDevelopment() && origState.isPermissionGranted(permName))))) {
+                    if ((bp.isNormal() && shouldGrantNormalPermission)
+                            || (bp.isSignature()
+                                    && ((shouldGrantSignaturePermission != null
+                                            && shouldGrantSignaturePermission.contains(permName))
+                                            || ((bp.isDevelopment() || bp.isRole())
+                                                    && origState.isPermissionGranted(permName))))
+                            || (bp.isInternal()
+                                    && ((shouldGrantInternalPermission != null
+                                            && shouldGrantInternalPermission.contains(permName))
+                                            || ((bp.isDevelopment() || bp.isRole())
+                                                    && origState.isPermissionGranted(permName))))) {
                         // Grant an install permission.
                         if (uidState.grantPermission(bp)) {
                             changedInstallPermission = true;
@@ -2916,7 +2873,7 @@
                         boolean softRestricted = bp.isSoftRestricted();
 
                         // If permission policy is not ready we don't deal with restricted
-                        // permissions as the policy may whitelist some permissions. Once
+                        // permissions as the policy may allowlist some permissions. Once
                         // the policy is initialized we would re-evaluate permissions.
                         final boolean permissionPolicyInitialized =
                                 isPermissionPolicyInitialized.get(userId);
@@ -3229,10 +3186,11 @@
         String pkgName = pkg.getPackageName();
         ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
 
-        final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions();
+        final List<PermissionManager.SplitPermissionInfo> permissionList =
+                getSplitPermissionInfos();
         int numSplitPerms = permissionList.size();
         for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-            SplitPermissionInfoParcelable spi = permissionList.get(splitPermNum);
+            PermissionManager.SplitPermissionInfo spi = permissionList.get(splitPermNum);
 
             List<String> newPerms = spi.getNewPermissions();
             int numNewPerms = newPerms.size();
@@ -3298,10 +3256,15 @@
         return updatedUserIds;
     }
 
+    @NonNull
     @Override
     public List<SplitPermissionInfoParcelable> getSplitPermissions() {
-        return PermissionManager.splitPermissionInfoListToParcelableList(
-                SystemConfig.getInstance().getSplitPermissions());
+        return PermissionManager.splitPermissionInfoListToParcelableList(getSplitPermissionInfos());
+    }
+
+    @NonNull
+    private List<PermissionManager.SplitPermissionInfo> getSplitPermissionInfos() {
+        return SystemConfig.getInstance().getSplitPermissions();
     }
 
     @NonNull
@@ -3406,7 +3369,7 @@
     }
 
     private boolean shouldGrantSignaturePermission(@NonNull AndroidPackage pkg,
-            @NonNull PackageSetting pkgSetting, @NonNull Permission bp) {
+            @NonNull Permission bp) {
         // expect single system package
         String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
                 PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
@@ -3421,8 +3384,7 @@
         //     - or it shares the above relationships with the system package
         final PackageParser.SigningDetails sourceSigningDetails =
                 getSourcePackageSigningDetails(bp);
-        boolean allowed =
-                pkg.getSigningDetails().hasAncestorOrSelf(sourceSigningDetails)
+        return pkg.getSigningDetails().hasAncestorOrSelf(sourceSigningDetails)
                 || sourceSigningDetails.checkCapability(
                         pkg.getSigningDetails(),
                         PackageParser.SigningDetails.CertCapabilities.PERMISSION)
@@ -3430,6 +3392,11 @@
                 || systemPackage.getSigningDetails().checkCapability(
                         pkg.getSigningDetails(),
                         PackageParser.SigningDetails.CertCapabilities.PERMISSION);
+    }
+
+    private boolean shouldGrantPermissionByProtectionFlags(@NonNull AndroidPackage pkg,
+            @NonNull PackageSetting pkgSetting, @NonNull Permission bp) {
+        boolean allowed = false;
         final boolean isVendorPrivilegedPermission = bp.isVendorPrivileged();
         final boolean isPrivilegedPermission = bp.isPrivileged() || isVendorPrivilegedPermission;
         final boolean isOemPermission = bp.isOem();
@@ -3472,12 +3439,12 @@
         //                  need a separate flag anymore. Hence we need to check which
         //                  permissions are needed by the permission controller
         if (!allowed && bp.isInstaller()
-                && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                && (ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
                         PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
                 pkg.getPackageName()) || ArrayUtils.contains(
                         mPackageManagerInt.getKnownPackageNames(
                                 PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
-                UserHandle.USER_SYSTEM), pkg.getPackageName())) {
+                UserHandle.USER_SYSTEM), pkg.getPackageName()))) {
             // If this permission is to be granted to the system installer and
             // this app is an installer, then it gets the permission.
             allowed = true;
@@ -3610,9 +3577,9 @@
         if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
             return true;
         }
-        // Only enforce whitelist this on boot
+        // Only enforce the allowlist on boot
         if (!mSystemReady
-                // Updated system apps do not need to be whitelisted
+                // Updated system apps do not need to be allowlisted
                 && !isUpdatedSystemApp) {
             final ApexManager apexManager = ApexManager.getInstance();
             final String packageName = pkg.getPackageName();
@@ -3621,7 +3588,7 @@
             final boolean isInUpdatedApex = containingApexPackageName != null
                     && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
                     MATCH_ACTIVE_PACKAGE));
-            // Apps that are in updated apexs' do not need to be whitelisted
+            // Apps that are in updated apexs' do not need to be allowlisted
             if (!isInUpdatedApex) {
                 // it's only a reportable violation if the permission isn't explicitly
                 // denied
@@ -3630,7 +3597,7 @@
                 }
                 Slog.w(TAG, "Privileged permission " + permissionName + " for package "
                         + packageName + " (" + pkg.getPath()
-                        + ") not in privapp-permissions whitelist");
+                        + ") not in privapp-permissions allowlist");
                 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                     synchronized (mLock) {
                         if (mPrivappPermissionsViolations == null) {
@@ -3809,10 +3776,10 @@
 
             int newFlags = oldFlags;
             int mask = 0;
-            int whitelistFlagsCopy = allowlistFlags;
-            while (whitelistFlagsCopy != 0) {
-                final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
-                whitelistFlagsCopy &= ~flag;
+            int allowlistFlagsCopy = allowlistFlags;
+            while (allowlistFlagsCopy != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(allowlistFlagsCopy);
+                allowlistFlagsCopy &= ~flag;
                 switch (flag) {
                     case FLAG_PERMISSION_WHITELIST_SYSTEM: {
                         mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
@@ -3859,26 +3826,26 @@
 
             updatePermissions = true;
 
-            final boolean wasWhitelisted = (oldFlags
+            final boolean wasAllowlisted = (oldFlags
                     & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
-            final boolean isWhitelisted = (newFlags
+            final boolean isAllowlisted = (newFlags
                     & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
 
             // If the permission is policy fixed as granted but it is no longer
-            // on any of the whitelists we need to clear the policy fixed flag
-            // as whitelisting trumps policy i.e. policy cannot grant a non
+            // on any of the allowlists we need to clear the policy fixed flag
+            // as allowlisting trumps policy i.e. policy cannot grant a non
             // grantable permission.
             if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
-                if (!isWhitelisted && isGranted) {
+                if (!isAllowlisted && isGranted) {
                     mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
                     newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
                 }
             }
 
-            // If we are whitelisting an app that does not support runtime permissions
+            // If we are allowlisting an app that does not support runtime permissions
             // we need to make sure it goes through the permission review UI at launch.
             if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
-                    && !wasWhitelisted && isWhitelisted) {
+                    && !wasAllowlisted && isAllowlisted) {
                 mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
                 newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
             }
@@ -3888,7 +3855,7 @@
         }
 
         if (updatePermissions) {
-            // Update permission of this app to take into account the new whitelist state.
+            // Update permission of this app to take into account the new allowlist state.
             restorePermissionState(pkg, false, pkg.getPackageName(), mDefaultPermissionCallback);
 
             // If this resulted in losing a permission we need to kill the app.
@@ -4521,7 +4488,7 @@
         synchronized (mLock) {
             if (mPrivappPermissionsViolations != null) {
                 throw new IllegalStateException("Signature|privileged permissions not in "
-                        + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+                        + "privapp-permissions allowlist: " + mPrivappPermissionsViolations);
             }
         }
 
@@ -4902,13 +4869,6 @@
         }
     }
 
-    private boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
-        synchronized (mLock) {
-            final Permission bp = mRegistry.getPermission(permissionName);
-            return bp != null && (bp.isRuntime() || bp.isDevelopment()) && bp.isInstant();
-        }
-    }
-
     @NonNull
     private List<LegacyPermission> getLegacyPermissions() {
         synchronized (mLock) {
@@ -4988,7 +4948,7 @@
 
     private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
         @Override
-        public void systemReady() {
+        public void onSystemReady() {
             PermissionManagerService.this.systemReady();
         }
 
@@ -5046,11 +5006,6 @@
             Preconditions.checkArgumentNonNegative(userId, "userId");
             resetRuntimePermissionsInternal(pkg, userId);
         }
-        @Override
-        public void resetAllRuntimePermissions(@UserIdInt int userId) {
-            Preconditions.checkArgumentNonNegative(userId, "userId");
-            mPackageManagerInt.forEachPackage(pkg -> resetRuntimePermissionsInternal(pkg, userId));
-        }
 
         @Override
         public Permission getPermissionTEMP(String permName) {
@@ -5191,11 +5146,6 @@
             onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userId);
         }
 
-        @Override
-        public boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
-            return PermissionManagerService.this.canPropagatePermissionToInstantApp(permissionName);
-        }
-
         @NonNull
         @Override
         public List<LegacyPermission> getLegacyPermissions() {
@@ -5394,94 +5344,4 @@
                     || mDelegatedPermissionNames.contains(permissionName);
         }
     }
-
-    /**
-     * Allows injection of services and method responses to facilitate testing.
-     *
-     * <p>Test classes can create a mock of this class and pass it to the PermissionManagerService
-     * constructor to control behavior of services and external methods during execution.
-     * @hide
-     */
-    @VisibleForTesting
-    public static class Injector {
-        private final Context mContext;
-
-        /**
-         * Public constructor that accepts a {@code context} within which to operate.
-         */
-        public Injector(@NonNull Context context) {
-            mContext = context;
-        }
-
-        /**
-         * Returns the UID of the calling package.
-         */
-        public int getCallingUid() {
-            return Binder.getCallingUid();
-        }
-
-        /**
-         * Returns the process ID of the calling package.
-         */
-        public int getCallingPid() {
-            return Binder.getCallingPid();
-        }
-
-        /**
-         * Invalidates the package info cache.
-         */
-        public void invalidatePackageInfoCache() {
-            PackageManager.invalidatePackageInfoCache();
-        }
-
-        /**
-         * Disables the permission cache.
-         */
-        public void disablePermissionCache() {
-            PermissionManager.disablePermissionCache();
-        }
-
-        /**
-         * Disables the package name permission cache.
-         */
-        public void disablePackageNamePermissionCache() {
-            PermissionManager.disablePackageNamePermissionCache();
-        }
-
-        /**
-         * Checks if the package running under the specified {@code pid} and {@code uid} has been
-         * granted the provided {@code permission}.
-         *
-         * @return {@link PackageManager#PERMISSION_GRANTED} if the package has been granted the
-         * permission, {@link PackageManager#PERMISSION_DENIED} otherwise
-         */
-        public int checkPermission(@NonNull String permission, int pid, int uid) {
-            return mContext.checkPermission(permission, pid, uid);
-        }
-
-        /**
-         * Clears the calling identity to allow subsequent calls to be treated as coming from this
-         * package.
-         *
-         * @return a token that can be used to restore the calling identity
-         */
-        public long clearCallingIdentity() {
-            return Binder.clearCallingIdentity();
-        }
-
-        /**
-         * Restores the calling identity to that of the calling package based on the provided
-         * {@code token}.
-         */
-        public void restoreCallingIdentity(long token) {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        /**
-         * Returns the system service with the provided {@code name}.
-         */
-        public Object getSystemService(@NonNull String name) {
-            return mContext.getSystemService(name);
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 0817d4f..1cfae00 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -54,8 +54,6 @@
     void removeOnRuntimePermissionStateChangedListener(
             @NonNull OnRuntimePermissionStateChangedListener listener);
 
-    void systemReady();
-
     /**
      * Get whether permission review is required for a package.
      *
@@ -94,14 +92,6 @@
             @UserIdInt int userId);
 
     /**
-     * Reset the runtime permission state changes for all packages.
-     *
-     * @param userId the user ID
-     */
-    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    void resetAllRuntimePermissions(@UserIdInt int userId);
-
-    /**
      * Read legacy permission state from package settings.
      *
      * TODO(zhanghai): This is a temporary method because we should not expose
@@ -201,6 +191,12 @@
     void writeLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
 
     /**
+     * Callback when the system is ready.
+     */
+    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    void onSystemReady();
+
+    /**
      * Callback when a user has been created.
      *
      * @param userId the created user ID
@@ -265,14 +261,6 @@
             @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
 
     /**
-     * Check whether a permission can be propagated to instant app.
-     *
-     * @param permissionName the name of the permission
-     * @return whether the permission can be propagated
-     */
-    boolean canPropagatePermissionToInstantApp(@NonNull String permissionName);
-
-    /**
      * Listener for package permission state (permissions or flags) changes.
      */
     interface OnRuntimePermissionStateChangedListener {
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index b007a75..ff51237 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -20,12 +20,10 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.hardware.ICameraService;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -63,7 +61,8 @@
     private String mFocusedApp;
     private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger();
 
-    DisplayFoldController(WindowManagerInternal windowManagerInternal,
+    DisplayFoldController(
+            Context context, WindowManagerInternal windowManagerInternal,
             DisplayManagerInternal displayManagerInternal,
             @Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea,
             Handler handler) {
@@ -73,6 +72,10 @@
         mDisplayId = displayId;
         mFoldedArea = new Rect(foldedArea);
         mHandler = handler;
+
+        DeviceStateManager deviceStateManager = context.getSystemService(DeviceStateManager.class);
+        deviceStateManager.registerDeviceStateListener(new DeviceStateListener(context),
+                new HandlerExecutor(handler));
     }
 
     void finishedGoingToSleep() {
@@ -83,11 +86,7 @@
         mDurationLogger.onFinishedWakingUp(mFolded);
     }
 
-    void requestDeviceFolded(boolean folded) {
-        mHandler.post(() -> setDeviceFolded(folded));
-    }
-
-    void setDeviceFolded(boolean folded) {
+    private void setDeviceFolded(boolean folded) {
         if (mFolded != null && mFolded == folded) {
             return;
         }
@@ -179,33 +178,6 @@
         }
     }
 
-    /**
-     * Only used for the case that persist.debug.force_foldable is set.
-     * This is using proximity sensor to simulate the fold state switch.
-     */
-    static DisplayFoldController createWithProxSensor(Context context, int displayId) {
-        final SensorManager sensorManager = context.getSystemService(SensorManager.class);
-        final Sensor proxSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
-        if (proxSensor == null) {
-            return null;
-        }
-
-        final DisplayFoldController result = create(context, displayId);
-        sensorManager.registerListener(new SensorEventListener() {
-            @Override
-            public void onSensorChanged(SensorEvent event) {
-                result.requestDeviceFolded(event.values[0] < 1f);
-            }
-
-            @Override
-            public void onAccuracyChanged(Sensor sensor, int accuracy) {
-                // Ignore.
-            }
-        }, proxSensor, SensorManager.SENSOR_DELAY_NORMAL);
-
-        return result;
-    }
-
     void onDefaultDisplayFocusChanged(String pkg) {
         mFocusedApp = pkg;
     }
@@ -227,7 +199,26 @@
             foldedArea = Rect.unflattenFromString(configFoldedArea);
         }
 
-        return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy,
-                displayId, foldedArea, DisplayThread.getHandler());
+        return new DisplayFoldController(context, windowManagerService, displayService,
+                cameraServiceProxy, displayId, foldedArea, DisplayThread.getHandler());
+    }
+
+    /**
+     * Listens to changes in device state and reports the state as folded if the device state
+     * matches the value in the {@link com.android.internal.R.integer.config_foldedDeviceState}
+     * resource.
+     */
+    private class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
+        private final int mFoldedDeviceState;
+
+        DeviceStateListener(Context context) {
+            mFoldedDeviceState = context.getResources().getInteger(
+                    com.android.internal.R.integer.config_foldedDeviceState);
+        }
+
+        @Override
+        public void onDeviceStateChanged(int deviceState) {
+            setDeviceFolded(deviceState == mFoldedDeviceState);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..8887e40
--- /dev/null
+++ b/services/core/java/com/android/server/policy/OWNERS
@@ -0,0 +1,3 @@
+include /services/core/java/com/android/server/wm/OWNERS
+include /services/core/java/com/android/server/input/OWNERS
+include /services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 75868e3..6919cea 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -472,7 +472,6 @@
 
     int mLidKeyboardAccessibility;
     int mLidNavigationAccessibility;
-    private boolean mLidControlsDisplayFold;
     int mShortPressOnPowerBehavior;
     int mLongPressOnPowerBehavior;
     int mVeryLongPressOnPowerBehavior;
@@ -648,8 +647,8 @@
                     break;
                 case MSG_LAUNCH_ASSIST:
                     final int deviceId = msg.arg1;
-                    final String hint = (String) msg.obj;
-                    launchAssistAction(hint, deviceId);
+                    final Long eventTime = (Long) msg.obj;
+                    launchAssistAction(null /* hint */, deviceId, eventTime);
                     break;
                 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
                     launchVoiceAssistWithWakeLock();
@@ -659,7 +658,7 @@
                     finishPowerKeyPress();
                     break;
                 case MSG_POWER_LONG_PRESS:
-                    powerLongPress();
+                    powerLongPress((Long) msg.obj /* eventTime */);
                     break;
                 case MSG_POWER_VERY_LONG_PRESS:
                     powerVeryLongPress();
@@ -934,9 +933,10 @@
                 // Wait for a long press or for the button to be released to decide what to do.
                 if (hasLongPressOnPowerBehavior()) {
                     if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
-                        powerLongPress();
+                        powerLongPress(event.getEventTime());
                     } else {
-                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS,
+                                event.getEventTime());
                         msg.setAsynchronous(true);
                         mHandler.sendMessageDelayed(msg,
                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
@@ -953,9 +953,10 @@
 
                 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
                     if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
-                        powerLongPress();
+                        powerLongPress(event.getEventTime());
                     } else {
-                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS,
+                                event.getEventTime());
                         msg.setAsynchronous(true);
                         mHandler.sendMessageDelayed(msg,
                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
@@ -1188,7 +1189,7 @@
         return 1;
     }
 
-    private void powerLongPress() {
+    private void powerLongPress(long eventTime) {
         final int behavior = getResolvedLongPressOnPowerBehavior();
         switch (behavior) {
             case LONG_PRESS_POWER_NOTHING:
@@ -1221,7 +1222,7 @@
                 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
                         "Power - Long Press - Go To Assistant");
                 final int powerKeyDeviceId = Integer.MIN_VALUE;
-                launchAssistAction(null, powerKeyDeviceId);
+                launchAssistAction(null, powerKeyDeviceId, eventTime);
                 break;
         }
     }
@@ -1624,7 +1625,8 @@
             } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
                 if (!keyguardOn) {
                     // Post to main thread to avoid blocking input pipeline.
-                    mHandler.post(() -> handleLongPressOnHome(event.getDeviceId()));
+                    mHandler.post(() -> handleLongPressOnHome(event.getDeviceId(),
+                            event.getEventTime()));
                 }
             }
             return -1;
@@ -1637,7 +1639,7 @@
             }
         }
 
-        private void handleLongPressOnHome(int deviceId) {
+        private void handleLongPressOnHome(int deviceId, long eventTime) {
             if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
                 return;
             }
@@ -1649,7 +1651,7 @@
                     launchAllAppsAction();
                     break;
                 case LONG_PRESS_HOME_ASSIST:
-                    launchAssistAction(null, deviceId);
+                    launchAssistAction(null, deviceId, eventTime);
                     break;
                 case LONG_PRESS_HOME_NOTIFICATION_PANEL:
                     toggleNotificationPanel();
@@ -1789,8 +1791,6 @@
                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
         mLidNavigationAccessibility = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lidNavigationAccessibility);
-        mLidControlsDisplayFold = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_lidControlsDisplayFold);
 
         mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
@@ -1847,12 +1847,7 @@
 
         readConfigurationDependentBehaviors();
 
-        if (mLidControlsDisplayFold) {
-            mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
-        } else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) {
-            mDisplayFoldController = DisplayFoldController.createWithProxSensor(context,
-                    DEFAULT_DISPLAY);
-        }
+        mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
 
         mAccessibilityManager = (AccessibilityManager) context.getSystemService(
                 Context.ACCESSIBILITY_SERVICE);
@@ -2413,15 +2408,6 @@
             wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
             view = win.getDecorView();
 
-            // Ignore to show splash screen if the decorView is not opaque.
-            if (!view.isOpaque()) {
-                if (DEBUG_SPLASH_SCREEN) {
-                    Slog.d(TAG, "addSplashScreen: the view of " + packageName
-                            + " is not opaque, cancel it");
-                }
-                return null;
-            }
-
             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
                 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
 
@@ -2800,7 +2786,8 @@
             if (down) {
                 mPendingMetaAction = true;
             } else if (mPendingMetaAction) {
-                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
+                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId(),
+                        event.getEventTime());
             }
             return -1;
         }
@@ -3143,7 +3130,8 @@
         }
     }
 
-    private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) {
+    @Override
+    public int applyKeyguardOcclusionChange() {
         if (mKeyguardOccludedChanged) {
             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
                     + mPendingKeyguardOccluded);
@@ -3152,6 +3140,12 @@
                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
             }
         }
+        return 0;
+    }
+
+    private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) {
+        final int res = applyKeyguardOcclusionChange();
+        if (res != 0) return res;
         if (keyguardGoingAway) {
             if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
             startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
@@ -3163,22 +3157,24 @@
     // various parts of the UI.
 
     /** Asks the status bar to startAssist(), usually a full "assistant" interface */
-    private void launchAssistAction(String hint, int deviceId) {
+    private void launchAssistAction(String hint, int deviceId, long eventTime) {
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
         if (!isUserSetupComplete()) {
             // Disable opening assist window during setup
             return;
         }
+
+        // Add Intent Extra data.
         Bundle args = null;
-        if (deviceId > Integer.MIN_VALUE || hint != null) {
-            args = new Bundle();
-            if (deviceId > Integer.MIN_VALUE) {
-                args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
-            }
-            if (hint != null) {
-                args.putBoolean(hint, true);
-            }
+        args = new Bundle();
+        if (deviceId > Integer.MIN_VALUE) {
+            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
         }
+        if (hint != null) {
+            args.putBoolean(hint, true);
+        }
+        args.putLong(Intent.EXTRA_TIME, eventTime);
+
         ((SearchManager) mContext.createContextAsUser(UserHandle.of(mCurrentUserId), 0)
                 .getSystemService(Context.SEARCH_SERVICE)).launchAssist(args);
     }
@@ -3800,7 +3796,7 @@
                 final boolean longPressed = event.getRepeatCount() > 0;
                 if (down && !longPressed) {
                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
-                            0 /* unused */, null /* hint */);
+                            0 /* unused */, event.getEventTime() /* eventTime */);
                     msg.setAsynchronous(true);
                     msg.sendToTarget();
                 }
@@ -4021,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;
         }
 
@@ -4862,9 +4861,7 @@
 
     private void applyLidSwitchState() {
         final int lidState = mDefaultDisplayPolicy.getLidState();
-        if (mLidControlsDisplayFold && mDisplayFoldController != null) {
-            mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
-        } else if (lidState == LID_CLOSED) {
+        if (lidState == LID_CLOSED) {
             int lidBehavior = getLidBehavior();
             switch (lidBehavior) {
                 case LID_BEHAVIOR_LOCK:
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 6934e5c..1553966 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -172,6 +172,9 @@
      */
     void onKeyguardOccludedChangedLw(boolean occluded);
 
+    /** Applies a keyguard occlusion change if one happened. */
+    int applyKeyguardOcclusionChange();
+
     /**
      * Interface to the Window Manager state associated with a particular
      * window. You can hold on to an instance of this interface from the call
@@ -493,6 +496,32 @@
      * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
      */
     default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
+        return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow,
+                false /* roundedCornerOverlay */);
+    }
+
+    /**
+     * Returns the layer assignment for the window type. Allows you to control how different
+     * kinds of windows are ordered on-screen.
+     *
+     * @param type The type of window being assigned.
+     * @param canAddInternalSystemWindow If the owner window associated with the type we are
+     *        evaluating can add internal system windows. I.e they have
+     *        {@link Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window
+     *        types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}
+     *        can be assigned layers greater than the layer for
+     *        {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their
+     *        layers would be lesser.
+     * @param roundedCornerOverlay {#code true} to indicate that the owner window is rounded corner
+     *                             overlay.
+     * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
+     */
+    default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
+            boolean roundedCornerOverlay) {
+        // Always put the rounded corner layer to the top most.
+        if (roundedCornerOverlay && canAddInternalSystemWindow) {
+            return getMaxWindowLayer();
+        }
         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
             return APPLICATION_LAYER;
         }
@@ -595,8 +624,17 @@
         }
     }
 
+    // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded corner
+    //  overlay.
+    /**
+     * Returns the max window layer.
+     * <p>Note that the max window layer should be higher that the maximum value which reported
+     * by {@link #getWindowLayerFromTypeLw(int, boolean)} to contain rounded corner overlay.</p>
+     *
+     * @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
+     */
     default int getMaxWindowLayer() {
-        return 35;
+        return 36;
     }
 
     /**
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 017c684..b95c5efc 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -33,6 +33,7 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.CollectionUtils;
 import com.android.server.LocalServices;
+import com.android.server.role.LegacyRoleHolderProvider;
 import com.android.server.role.RoleManagerService;
 
 import java.util.Collections;
@@ -48,7 +49,7 @@
  *
  * @see RoleManagerService#migrateRoleIfNecessary
  */
-public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHoldersResolver {
+public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "LegacyRoleResolutionPol";
@@ -62,7 +63,7 @@
 
     @NonNull
     @Override
-    public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
+    public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
         switch (roleName) {
             case RoleManager.ROLE_ASSISTANT: {
                 String packageName;
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 68d038b..16f5069 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -113,11 +113,6 @@
     private boolean mIsInteractive;
 
     /**
-     * Read-only list of plugins. No need for synchronization.
-     */
-    private final Plugin[] mPlugins;
-
-    /**
      * Package name that will receive an explicit manifest broadcast for
      * {@link PowerManager#ACTION_POWER_SAVE_MODE_CHANGED}. It's {@code null} if it hasn't been
      * retrieved yet.
@@ -172,15 +167,6 @@
         }
     }
 
-    /**
-     * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
-     */
-    public interface Plugin {
-        void onSystemReady(BatterySaverController caller);
-
-        void onBatterySaverChanged(BatterySaverController caller);
-    }
-
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -194,6 +180,7 @@
                         updateBatterySavingStats();
                         return; // No need to send it if not enabled.
                     }
+                    // We currently evaluate state only for CPU frequency changes.
                     // Don't send the broadcast, because we never did so in this case.
                     mHandler.postStateChanged(/*sendBroadcast=*/ false,
                             REASON_INTERACTIVE_CHANGED);
@@ -224,9 +211,6 @@
         mFileUpdater = new FileUpdater(context);
         mBatterySavingStats = batterySavingStats;
 
-        // TODO(79580230): remove plugin code and maybe screen on/off listeners?
-        // Initialize plugins.
-        mPlugins = new Plugin[0];
         PowerManager.invalidatePowerSaveModeCaches();
     }
 
@@ -300,12 +284,6 @@
                             msg.arg1 == ARG_SEND_BROADCAST,
                             msg.arg2);
                     break;
-
-                case MSG_SYSTEM_READY:
-                    for (Plugin p : mPlugins) {
-                        p.onSystemReady(BatterySaverController.this);
-                    }
-                    break;
             }
         }
     }
@@ -479,10 +457,6 @@
             mFileUpdater.writeFiles(fileValues);
         }
 
-        for (Plugin p : mPlugins) {
-            p.onBatterySaverChanged(this);
-        }
-
         if (sendBroadcast) {
 
             if (DEBUG) {
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/powerstats/OWNERS b/services/core/java/com/android/server/powerstats/OWNERS
new file mode 100644
index 0000000..c22f6a4
--- /dev/null
+++ b/services/core/java/com/android/server/powerstats/OWNERS
@@ -0,0 +1,2 @@
+include /BATTERY_STATS_OWNERS
+include /services/core/java/com/android/server/power/OWNERS
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/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index e0701e8..5c01e43 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -16,8 +16,10 @@
 
 package com.android.server.recoverysystem;
 
+import android.annotation.IntDef;
 import android.content.Context;
 import android.content.IntentSender;
+import android.content.pm.PackageManager;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.os.Binder;
@@ -30,8 +32,11 @@
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.SystemProperties;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.LockSettingsInternal;
 import com.android.internal.widget.RebootEscrowListener;
@@ -76,9 +81,53 @@
     private final Injector mInjector;
     private final Context mContext;
 
-    private boolean mPreparedForReboot;
-    private String mUnattendedRebootToken;
-    private IntentSender mPreparedForRebootIntentSender;
+    @GuardedBy("this")
+    private final ArrayMap<String, IntentSender> mCallerPendingRequest = new ArrayMap<>();
+    @GuardedBy("this")
+    private final ArraySet<String> mCallerPreparedForReboot = new ArraySet<>();
+
+    /**
+     * Need to prepare for resume on reboot.
+     */
+    private static final int ROR_NEED_PREPARATION = 0;
+    /**
+     * Resume on reboot has been prepared, notify the caller.
+     */
+    private static final int ROR_SKIP_PREPARATION_AND_NOTIFY = 1;
+    /**
+     * Resume on reboot has been requested. Caller won't be notified until the preparation is done.
+     */
+    private static final int ROR_SKIP_PREPARATION_NOT_NOTIFY = 2;
+
+    /**
+     * The caller never requests for resume on reboot, no need for clear.
+     */
+    private static final int ROR_NOT_REQUESTED = 0;
+    /**
+     * Clear the resume on reboot preparation state.
+     */
+    private static final int ROR_REQUESTED_NEED_CLEAR = 1;
+    /**
+     * The caller has requested for resume on reboot. No need for clear since other callers may
+     * exist.
+     */
+    private static final int ROR_REQUESTED_SKIP_CLEAR = 2;
+
+    /**
+     * The action to perform upon new resume on reboot prepare request for a given client.
+     */
+    @IntDef({ ROR_NEED_PREPARATION,
+            ROR_SKIP_PREPARATION_AND_NOTIFY,
+            ROR_SKIP_PREPARATION_NOT_NOTIFY })
+    private @interface ResumeOnRebootActionsOnRequest {}
+
+    /**
+     * The action to perform upon resume on reboot clear request for a given client.
+     */
+    @IntDef({ROR_NOT_REQUESTED,
+            ROR_REQUESTED_NEED_CLEAR,
+            ROR_REQUESTED_SKIP_CLEAR})
+    private @interface ResumeOnRebootActionsOnClear{}
 
     static class Injector {
         protected final Context mContext;
@@ -286,47 +335,95 @@
         }
     }
 
-    @Override // Binder call
-    public boolean requestLskf(String updateToken, IntentSender intentSender) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+    private void enforcePermissionForResumeOnReboot() {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
+                != PackageManager.PERMISSION_GRANTED
+                && mContext.checkCallingOrSelfPermission(android.Manifest.permission.REBOOT)
+                        != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller must have " + android.Manifest.permission.RECOVERY
+                    + " or " + android.Manifest.permission.REBOOT + " for resume on reboot.");
+        }
+    }
 
-        if (updateToken == null) {
+    @Override // Binder call
+    public boolean requestLskf(String packageName, IntentSender intentSender) {
+        enforcePermissionForResumeOnReboot();
+
+        if (packageName == null) {
+            Slog.w(TAG, "Missing packageName when requesting lskf.");
             return false;
         }
 
-        // No need to prepare again for the same token.
-        if (mPreparedForReboot && updateToken.equals(mUnattendedRebootToken)) {
-            return true;
+        @ResumeOnRebootActionsOnRequest int action = updateRoRPreparationStateOnNewRequest(
+                packageName, intentSender);
+        switch (action) {
+            case ROR_SKIP_PREPARATION_AND_NOTIFY:
+                // We consider the preparation done if someone else has prepared.
+                sendPreparedForRebootIntentIfNeeded(intentSender);
+                return true;
+            case ROR_SKIP_PREPARATION_NOT_NOTIFY:
+                return true;
+            case ROR_NEED_PREPARATION:
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    mInjector.getLockSettingsService().prepareRebootEscrow();
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+                return true;
+            default:
+                throw new IllegalStateException("Unsupported action type on new request " + action);
+        }
+    }
+
+    // Checks and updates the resume on reboot preparation state.
+    private synchronized @ResumeOnRebootActionsOnRequest int updateRoRPreparationStateOnNewRequest(
+            String packageName, IntentSender intentSender) {
+        if (!mCallerPreparedForReboot.isEmpty()) {
+            if (mCallerPreparedForReboot.contains(packageName)) {
+                Slog.i(TAG, "RoR already has prepared for " + packageName);
+            }
+
+            // Someone else has prepared. Consider the preparation done, and send back the intent.
+            mCallerPreparedForReboot.add(packageName);
+            return ROR_SKIP_PREPARATION_AND_NOTIFY;
         }
 
-        mPreparedForReboot = false;
-        mUnattendedRebootToken = updateToken;
-        mPreparedForRebootIntentSender = intentSender;
-
-        final long origId = Binder.clearCallingIdentity();
-        try {
-            mInjector.getLockSettingsService().prepareRebootEscrow();
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+        boolean needPreparation = mCallerPendingRequest.isEmpty();
+        if (mCallerPendingRequest.containsKey(packageName)) {
+            Slog.i(TAG, "Duplicate RoR preparation request for " + packageName);
         }
-
-        return true;
+        // Update the request with the new intentSender.
+        mCallerPendingRequest.put(packageName, intentSender);
+        return needPreparation ? ROR_NEED_PREPARATION : ROR_SKIP_PREPARATION_NOT_NOTIFY;
     }
 
     @Override
     public void onPreparedForReboot(boolean ready) {
-        if (mUnattendedRebootToken == null) {
-            Slog.w(TAG, "onPreparedForReboot called when mUnattendedRebootToken is null");
+        if (!ready) {
+            return;
         }
-
-        mPreparedForReboot = ready;
-        if (ready) {
-            sendPreparedForRebootIntentIfNeeded();
-        }
+        updateRoRPreparationStateOnPreparedForReboot();
     }
 
-    private void sendPreparedForRebootIntentIfNeeded() {
-        final IntentSender intentSender = mPreparedForRebootIntentSender;
+    private synchronized void updateRoRPreparationStateOnPreparedForReboot() {
+        if (!mCallerPreparedForReboot.isEmpty()) {
+            Slog.w(TAG, "onPreparedForReboot called when some clients have prepared.");
+        }
+
+        if (mCallerPendingRequest.isEmpty()) {
+            Slog.w(TAG, "onPreparedForReboot called but no client has requested.");
+        }
+
+        // Send intents to notify callers
+        for (int i = 0; i < mCallerPendingRequest.size(); i++) {
+            sendPreparedForRebootIntentIfNeeded(mCallerPendingRequest.valueAt(i));
+            mCallerPreparedForReboot.add(mCallerPendingRequest.keyAt(i));
+        }
+        mCallerPendingRequest.clear();
+    }
+
+    private void sendPreparedForRebootIntentIfNeeded(IntentSender intentSender) {
         if (intentSender != null) {
             try {
                 intentSender.sendIntent(null, 0, null, null, null);
@@ -337,37 +434,59 @@
     }
 
     @Override // Binder call
-    public boolean clearLskf() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
-        mPreparedForReboot = false;
-        mUnattendedRebootToken = null;
-        mPreparedForRebootIntentSender = null;
-
-        final long origId = Binder.clearCallingIdentity();
-        try {
-            mInjector.getLockSettingsService().clearRebootEscrow();
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+    public boolean clearLskf(String packageName) {
+        enforcePermissionForResumeOnReboot();
+        if (packageName == null) {
+            Slog.w(TAG, "Missing packageName when clearing lskf.");
+            return false;
         }
 
-        return true;
+        @ResumeOnRebootActionsOnClear int action = updateRoRPreparationStateOnClear(packageName);
+        switch (action) {
+            case ROR_NOT_REQUESTED:
+                Slog.w(TAG, "RoR clear called before preparation for caller " + packageName);
+                return true;
+            case ROR_REQUESTED_SKIP_CLEAR:
+                return true;
+            case ROR_REQUESTED_NEED_CLEAR:
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    mInjector.getLockSettingsService().clearRebootEscrow();
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+                return true;
+            default:
+                throw new IllegalStateException("Unsupported action type on clear " + action);
+        }
     }
 
-    @Override // Binder call
-    public boolean rebootWithLskf(String updateToken, String reason) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+    private synchronized @ResumeOnRebootActionsOnClear int updateRoRPreparationStateOnClear(
+            String packageName) {
+        if (!mCallerPreparedForReboot.contains(packageName) && !mCallerPendingRequest.containsKey(
+                packageName)) {
+            Slog.w(TAG, packageName + " hasn't prepared for resume on reboot");
+            return ROR_NOT_REQUESTED;
+        }
+        mCallerPendingRequest.remove(packageName);
+        mCallerPreparedForReboot.remove(packageName);
 
-        if (!mPreparedForReboot) {
-            Slog.i(TAG, "Reboot requested before prepare completed");
+        // Check if others have prepared ROR.
+        boolean needClear = mCallerPendingRequest.isEmpty() && mCallerPreparedForReboot.isEmpty();
+        return needClear ? ROR_REQUESTED_NEED_CLEAR : ROR_REQUESTED_SKIP_CLEAR;
+    }
+
+    private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
+        if (packageName == null) {
+            Slog.w(TAG, "Missing packageName when rebooting with lskf.");
+            return false;
+        }
+        if (!isLskfCaptured(packageName)) {
             return false;
         }
 
-        if (updateToken != null && !updateToken.equals(mUnattendedRebootToken)) {
-            Slog.i(TAG, "Reboot requested after preparation, but with mismatching token");
-            return false;
-        }
-
+        // TODO(xunchang) check the slot to boot into, and fail the reboot upon slot mismatch.
+        // TODO(xunchang) write the vbmeta digest along with the escrowKey before reboot.
         if (!mInjector.getLockSettingsService().armRebootEscrow()) {
             Slog.w(TAG, "Failure to escrow key for reboot");
             return false;
@@ -378,6 +497,34 @@
         return true;
     }
 
+    @Override // Binder call for the legacy rebootWithLskf
+    public boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+        return rebootWithLskfImpl(packageName, reason, true);
+    }
+
+    @Override // Binder call
+    public boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) {
+        enforcePermissionForResumeOnReboot();
+        return rebootWithLskfImpl(packageName, reason, slotSwitch);
+    }
+
+    @Override // Binder call
+    public boolean isLskfCaptured(String packageName) {
+        enforcePermissionForResumeOnReboot();
+        boolean captured;
+        synchronized (this) {
+            captured = mCallerPreparedForReboot.contains(packageName);
+        }
+
+        if (!captured) {
+            Slog.i(TAG, "Reboot requested before prepare completed for caller "
+                    + packageName);
+            return false;
+        }
+        return true;
+    }
+
     /**
      * Check if any of the init services is still running. If so, we cannot
      * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
index c6905b5..f20d80d 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
@@ -56,26 +56,31 @@
     }
 
     private int requestLskf() throws RemoteException {
-        String updateToken = getNextArgRequired();
-        boolean success = mService.requestLskf(updateToken, null);
+        String packageName = getNextArgRequired();
+        boolean success = mService.requestLskf(packageName, null);
         PrintWriter pw = getOutPrintWriter();
-        pw.println("Request LSKF status: " + (success ? "success" : "failure"));
+        pw.printf("Request LSKF for packageName: %s, status: %s\n", packageName,
+                success ? "success" : "failure");
         return 0;
     }
 
     private int clearLskf() throws RemoteException {
-        boolean success = mService.clearLskf();
+        String packageName = getNextArgRequired();
+        boolean success = mService.clearLskf(packageName);
         PrintWriter pw = getOutPrintWriter();
-        pw.println("Clear LSKF: " + (success ? "success" : "failure"));
+        pw.printf("Clear LSKF for packageName: %s, status: %s\n", packageName,
+                success ? "success" : "failure");
         return 0;
     }
 
     private int rebootAndApply() throws RemoteException {
-        String updateToken = getNextArgRequired();
+        String packageName = getNextArgRequired();
         String rebootReason = getNextArgRequired();
-        boolean success = mService.rebootWithLskf(updateToken, rebootReason);
+        boolean success = mService.rebootWithLskf(packageName, rebootReason, true);
         PrintWriter pw = getOutPrintWriter();
-        pw.println("Reboot and apply status: " + (success ? "success" : "failure"));
+        // Keep the old message for cts test.
+        pw.printf("%s Reboot and apply status: %s\n", packageName,
+                success ? "success" : "failure");
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
new file mode 100644
index 0000000..ed0d675
--- /dev/null
+++ b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
@@ -0,0 +1,40 @@
+/*
+ * 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.role;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+
+import java.util.List;
+
+/**
+ * A provider for migrating legacy "role"s to their actual role implementation.
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface LegacyRoleHolderProvider {
+    /**
+     * Get the list of holders of a legacy "role" before its actual role is introduced.
+     * <p>
+     * This method will only be called for the first time a role is made available in the platform.
+     *
+     * @param roleName the name of the role
+     * @param userId the user ID
+     * @return a list of holders for the given role
+     */
+    @NonNull
+    List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index eb15c80..d6add78 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -34,7 +34,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
@@ -57,7 +56,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.infra.ThrottledRunnable;
-import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.CollectionUtils;
@@ -105,14 +103,7 @@
     private final Object mLock = new Object();
 
     @NonNull
-    private final RoleHoldersResolver mLegacyRoleResolver;
-
-    /** @see #getRoleHolders(String, int) */
-    public interface RoleHoldersResolver {
-        /** @return a list of packages that hold a given role for a given user */
-        @NonNull
-        List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId);
-    }
+    private final LegacyRoleHolderProvider mLegacyRoleHolderProvider;
 
     /**
      * Maps user id to its state.
@@ -148,10 +139,10 @@
             new SparseArray<>();
 
     public RoleManagerService(@NonNull Context context,
-            @NonNull RoleHoldersResolver legacyRoleResolver) {
+            @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) {
         super(context);
 
-        mLegacyRoleResolver = legacyRoleResolver;
+        mLegacyRoleHolderProvider = legacyRoleHolderProvider;
 
         RoleControllerManager.initializeRemoteServiceComponentName(context);
 
@@ -277,7 +268,7 @@
         // Any role for which we have a record are already migrated
         RoleUserState userState = getOrCreateUserState(userId);
         if (!userState.isRoleAvailable(role)) {
-            List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
+            List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId);
             if (roleHolders.isEmpty()) {
                 return;
             }
@@ -393,16 +384,13 @@
     }
 
     @Override
-    public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
-            @Nullable String removedHolder, @Nullable String addedHolder) {
+    public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
         mListenerHandler.sendMessage(PooledLambda.obtainMessage(
-                RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId,
-                removedHolder, addedHolder));
+                RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId));
     }
 
     @WorkerThread
-    private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
-            @Nullable String removedHolder, @Nullable String addedHolder) {
+    private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
         RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
         if (listeners != null) {
             notifyRoleHoldersChangedForListeners(listeners, roleName, userId);
@@ -413,12 +401,6 @@
         if (allUsersListeners != null) {
             notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
         }
-
-        // Legacy: sms app changed broadcasts
-        if (RoleManager.ROLE_SMS.equals(roleName)) {
-            SmsApplication.broadcastSmsAppChange(getContext(), UserHandle.of(userId),
-                    removedHolder, addedHolder);
-        }
     }
 
     @WorkerThread
@@ -754,18 +736,6 @@
 
             dumpOutputStream.flush();
         }
-
-        private int getUidForPackage(String packageName) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                return getContext().getPackageManager().getApplicationInfo(packageName,
-                        PackageManager.MATCH_ANY_USER).uid;
-            } catch (NameNotFoundException nnfe) {
-                return -1;
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
     }
 
     private class Internal extends RoleManagerInternal {
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 7751397..7d77450 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -281,7 +281,7 @@
         }
 
         if (changed) {
-            mCallback.onRoleHoldersChanged(roleName, mUserId, null, packageName);
+            mCallback.onRoleHoldersChanged(roleName, mUserId);
         }
         return true;
     }
@@ -313,7 +313,7 @@
         }
 
         if (changed) {
-            mCallback.onRoleHoldersChanged(roleName, mUserId, packageName, null);
+            mCallback.onRoleHoldersChanged(roleName, mUserId);
         }
         return true;
     }
@@ -566,7 +566,6 @@
          * @param roleName the name of the role whose holders are changed
          * @param userId the user id for this role holder change
          */
-        void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId,
-                @Nullable String removedHolder, @Nullable String addedHolder);
+        void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId);
     }
 }
diff --git a/services/core/java/com/android/server/rollback/OWNERS b/services/core/java/com/android/server/rollback/OWNERS
new file mode 100644
index 0000000..7feb85f
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/OWNERS
@@ -0,0 +1 @@
+olilan@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/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 192a003..bd66aa3 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1316,7 +1316,7 @@
     private SparseIntArray getExtensionVersions() {
         // This list must be updated whenever the current API level is increased, or should be
         // replaced when we have another way of determining the relevant SDK versions.
-        final int[] relevantSdkVersions = { Build.VERSION_CODES.R };
+        final int[] relevantSdkVersions = { Build.VERSION_CODES.R, Build.VERSION_CODES.S };
 
         SparseIntArray result = new SparseIntArray(relevantSdkVersions.length);
         for (int i = 0; i < relevantSdkVersions.length; i++) {
diff --git a/services/core/java/com/android/server/slice/OWNERS b/services/core/java/com/android/server/slice/OWNERS
new file mode 100644
index 0000000..3d0859f
--- /dev/null
+++ b/services/core/java/com/android/server/slice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/slice/OWNERS
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 cf20cf4..8071672 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -31,6 +31,7 @@
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
 import static android.os.Debug.getIonHeapsSizeKb;
+import static android.os.Process.LAST_SHARED_APPLICATION_GID;
 import static android.os.Process.getUidForPid;
 import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
 import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
@@ -168,7 +169,6 @@
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
-import java.util.concurrent.ExecutionException;
 import libcore.io.IoUtils;
 
 import org.json.JSONArray;
@@ -191,6 +191,7 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
@@ -1517,14 +1518,53 @@
     }
 
     int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
+        // Aggregate times for the same uids.
+        SparseArray<long[]> aggregated = new SparseArray<>();
         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
-            for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
-                if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
-                    pulledData.add(FrameworkStatsLog.buildStatsEvent(
-                            atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex]));
+            // For uids known to be aggregated from many entries allow mutating in place to avoid
+            // many copies. Otherwise, copy before aggregating.
+            boolean mutateInPlace = false;
+            if (UserHandle.isIsolated(uid)) {
+                // Skip individual isolated uids because they are recycled and quickly removed from
+                // the underlying data source.
+                return;
+            } else if (UserHandle.isSharedAppGid(uid)) {
+                // All shared app gids are accounted together.
+                uid = LAST_SHARED_APPLICATION_GID;
+                mutateInPlace = true;
+            } else {
+                // Everything else is accounted under their base uid.
+                uid = UserHandle.getAppId(uid);
+            }
+
+            long[] aggCpuFreqTimeMs = aggregated.get(uid);
+            if (aggCpuFreqTimeMs != null) {
+                if (!mutateInPlace) {
+                    aggCpuFreqTimeMs = Arrays.copyOf(aggCpuFreqTimeMs, cpuFreqTimeMs.length);
+                    aggregated.put(uid, aggCpuFreqTimeMs);
                 }
+                for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
+                    aggCpuFreqTimeMs[freqIndex] += cpuFreqTimeMs[freqIndex];
+                }
+            } else {
+                if (mutateInPlace) {
+                    cpuFreqTimeMs = Arrays.copyOf(cpuFreqTimeMs, cpuFreqTimeMs.length);
+                }
+                aggregated.put(uid, cpuFreqTimeMs);
             }
         });
+
+        int size = aggregated.size();
+        for (int i = 0; i < size; ++i) {
+            int uid = aggregated.keyAt(i);
+            long[] aggCpuFreqTimeMs = aggregated.valueAt(i);
+            for (int freqIndex = 0; freqIndex < aggCpuFreqTimeMs.length; ++freqIndex) {
+                if (aggCpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
+                    pulledData.add(FrameworkStatsLog.buildStatsEvent(
+                            atomTag, uid, freqIndex, aggCpuFreqTimeMs[freqIndex]));
+                }
+            }
+        }
         return StatsManager.PULL_SUCCESS;
     }
 
@@ -3124,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/statusbar/OWNERS b/services/core/java/com/android/server/statusbar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/services/core/java/com/android/server/statusbar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index de06c92..da56824 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -472,8 +472,8 @@
             final CharSequence details = context.getText(
                     com.android.internal.R.string.low_internal_storage_view_text);
 
-            PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0,
-                    null, UserHandle.CURRENT);
+            PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent,
+                    PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
             Notification notification =
                     new Notification.Builder(context, SystemNotificationChannels.ALERTS)
                             .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
diff --git a/services/core/java/com/android/server/storage/OWNERS b/services/core/java/com/android/server/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/services/core/java/com/android/server/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 0abeac8..808d130 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
+import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.provider.MediaStore;
 import android.service.storage.ExternalStorageService;
@@ -133,6 +134,28 @@
         }
     }
 
+    /**
+     * Frees any cache held by ExternalStorageService.
+     *
+     * <p> Blocks until the service frees the cache or fails in doing so.
+     *
+     * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+     * @param bytes number of bytes which need to be freed
+     * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
+     */
+    public void freeCache(String volumeUuid, long bytes)
+            throws ExternalStorageServiceException {
+        synchronized (mLock) {
+            int size = mConnections.size();
+            for (int i = 0; i < size; i++) {
+                int key = mConnections.keyAt(i);
+                StorageUserConnection connection = mConnections.get(key);
+                if (connection != null) {
+                    connection.freeCache(volumeUuid, bytes);
+                }
+            }
+        }
+    }
 
     /**
      * Removes and returns the {@link StorageUserConnection} for {@code vol}.
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index af26289..13cceee 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -125,6 +125,24 @@
     }
 
     /**
+     * Frees any cache held by ExternalStorageService.
+     *
+     * <p> Blocks until the service frees the cache or fails in doing so.
+     *
+     * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+     * @param bytes number of bytes which need to be freed
+     * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
+     */
+    public void freeCache(String volumeUuid, long bytes)
+            throws ExternalStorageServiceException {
+        synchronized (mSessionsLock) {
+            for (String sessionId : mSessions.keySet()) {
+                mActiveConnection.freeCache(sessionId, volumeUuid, bytes);
+            }
+        }
+    }
+
+    /**
      * Removes a session without ending it or waiting for exit.
      *
      * This should only be used if the session has certainly been ended because the volume was
@@ -214,7 +232,7 @@
         // A list of outstanding futures for async calls, for which we are still waiting
         // for a callback. Used to unblock waiters if the service dies.
         @GuardedBy("mLock")
-        private ArrayList<CompletableFuture<Void>> mOutstandingOps = new ArrayList<>();
+        private final ArrayList<CompletableFuture<Void>> mOutstandingOps = new ArrayList<>();
 
         @Override
         public void close() {
@@ -309,6 +327,17 @@
             }
         }
 
+        public void freeCache(String sessionId, String volumeUuid, long bytes)
+                throws ExternalStorageServiceException {
+            try {
+                waitForAsync((service, callback) ->
+                        service.freeCache(sessionId, volumeUuid, bytes, callback));
+            } catch (Exception e) {
+                throw new ExternalStorageServiceException("Failed to free " + bytes
+                        + " bytes for volumeUuid : " + volumeUuid, e);
+            }
+        }
+
         private void setResult(Bundle result, CompletableFuture<Void> future) {
             ParcelableException ex = result.getParcelable(EXTRA_ERROR);
             if (ex != null) {
diff --git a/services/core/java/com/android/server/textclassifier/OWNERS b/services/core/java/com/android/server/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/services/core/java/com/android/server/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/services/core/java/com/android/server/timedetector/OWNERS b/services/core/java/com/android/server/timedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 7de0e87..c7fe204 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ITimeDetectorService;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
@@ -129,6 +130,14 @@
         mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
     }
 
+    @Override
+    public void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) {
+        enforceSuggestGnssTimePermission();
+        Objects.requireNonNull(timeSignal);
+
+        mHandler.post(() -> mTimeDetectorStrategy.suggestGnssTime(timeSignal));
+    }
+
     /** Internal method for handling the auto time setting being changed. */
     @VisibleForTesting
     public void handleAutoTimeDetectionChanged() {
@@ -162,4 +171,10 @@
                 android.Manifest.permission.SET_TIME,
                 "set time");
     }
+
+    private void enforceSuggestGnssTimePermission() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SET_TIME,
+                "suggest gnss time");
+    }
 }
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index f278ef6..b539f01 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
@@ -41,7 +42,7 @@
  */
 public interface TimeDetectorStrategy extends Dumpable {
 
-    @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
+    @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK, ORIGIN_GNSS })
     @Retention(RetentionPolicy.SOURCE)
     @interface Origin {}
 
@@ -57,6 +58,10 @@
     @Origin
     int ORIGIN_NETWORK = 3;
 
+    /** Used when a time value originated from a gnss signal. */
+    @Origin
+    int ORIGIN_GNSS = 4;
+
     /** Processes the suggested time from telephony sources. */
     void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
 
@@ -71,6 +76,9 @@
     /** Processes the suggested time from network sources. */
     void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
 
+    /** Processes the suggested time from gnss sources. */
+    void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion);
+
     /**
      * Handles the auto-time configuration changing For example, when the auto-time setting is
      * toggled on or off.
@@ -100,6 +108,8 @@
                 return "network";
             case ORIGIN_TELEPHONY:
                 return "telephony";
+            case ORIGIN_GNSS:
+                return "gnss";
             default:
                 throw new IllegalArgumentException("origin=" + origin);
         }
@@ -117,6 +127,8 @@
                 return ORIGIN_NETWORK;
             case "telephony":
                 return ORIGIN_TELEPHONY;
+            case "gnss":
+                return ORIGIN_GNSS;
             default:
                 throw new IllegalArgumentException("originString=" + originString);
         }
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index b5d49cf..48af81e5 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -23,6 +23,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
@@ -108,6 +109,10 @@
     private final ReferenceWithHistory<NetworkTimeSuggestion> mLastNetworkSuggestion =
             new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
 
+    @GuardedBy("this")
+    private final ReferenceWithHistory<GnssTimeSuggestion> mLastGnssSuggestion =
+            new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
     /**
      * The interface used by the strategy to interact with the surrounding service.
      *
@@ -165,6 +170,20 @@
     }
 
     @Override
+    public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion) {
+        final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
+
+        if (!validateAutoSuggestionTime(newUtcTime, timeSuggestion)) {
+            return;
+        }
+
+        mLastGnssSuggestion.set(timeSuggestion);
+
+        String reason = "GNSS time suggestion received: suggestion=" + timeSuggestion;
+        doAutoTimeDetection(reason);
+    }
+
+    @Override
     public synchronized boolean suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
         final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
 
@@ -278,6 +297,11 @@
         mLastNetworkSuggestion.dump(ipw);
         ipw.decreaseIndent(); // level 2
 
+        ipw.println("Gnss suggestion history:");
+        ipw.increaseIndent(); // level 2
+        mLastGnssSuggestion.dump(ipw);
+        ipw.decreaseIndent(); // level 2
+
         ipw.decreaseIndent(); // level 1
     }
 
@@ -383,6 +407,14 @@
                             + ", networkSuggestion=" + networkSuggestion
                             + ", detectionReason=" + detectionReason;
                 }
+            } else if (origin == ORIGIN_GNSS) {
+                GnssTimeSuggestion gnssTimeSuggestion = findLatestValidGnssSuggestion();
+                if (gnssTimeSuggestion != null) {
+                    newUtcTime = gnssTimeSuggestion.getUtcTime();
+                    cause = "Found good gnss suggestion."
+                            + ", gnssTimeSuggestion=" + gnssTimeSuggestion
+                            + ", detectionReason=" + detectionReason;
+                }
             } else {
                 Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin
                         + " in " + Arrays.toString(originPriorities)
@@ -524,6 +556,26 @@
         return networkSuggestion;
     }
 
+    /** Returns the latest, valid, gnss suggestion. Returns {@code null} if there isn't one. */
+    @GuardedBy("this")
+    @Nullable
+    private GnssTimeSuggestion findLatestValidGnssSuggestion() {
+        GnssTimeSuggestion gnssTimeSuggestion = mLastGnssSuggestion.get();
+        if (gnssTimeSuggestion == null) {
+            // No gnss suggestions received. This is normal if there's no gnss signal.
+            return null;
+        }
+
+        TimestampedValue<Long> utcTime = gnssTimeSuggestion.getUtcTime();
+        long elapsedRealTimeMillis = mCallback.elapsedRealtimeMillis();
+        if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+            // The latest suggestion is not valid, usually due to its age.
+            return null;
+        }
+
+        return gnssTimeSuggestion;
+    }
+
     @GuardedBy("this")
     private boolean setSystemClockIfRequired(
             @Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
@@ -652,6 +704,16 @@
     }
 
     /**
+     * Returns the latest valid gnss suggestion. Not intended for general use: it is used during
+     * tests to check strategy behavior.
+     */
+    @VisibleForTesting
+    @Nullable
+    public synchronized GnssTimeSuggestion findLatestValidGnssSuggestionForTests() {
+        return findLatestValidGnssSuggestion();
+    }
+
+    /**
      * A method used to inspect state during tests. Not intended for general use.
      */
     @VisibleForTesting
@@ -669,6 +731,15 @@
         return mLastNetworkSuggestion.get();
     }
 
+    /**
+     * A method used to inspect state during tests. Not intended for general use.
+     */
+    @VisibleForTesting
+    @Nullable
+    public synchronized GnssTimeSuggestion getLatestGnssSuggestion() {
+        return mLastGnssSuggestion.get();
+    }
+
     private static boolean validateSuggestionUtcTime(
             long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) {
         long referenceTimeMillis = utcTime.getReferenceTimeMillis();
diff --git a/services/core/java/com/android/server/timezone/OWNERS b/services/core/java/com/android/server/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/core/java/com/android/server/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/trust/OWNERS b/services/core/java/com/android/server/trust/OWNERS
new file mode 100644
index 0000000..b039c4b
--- /dev/null
+++ b/services/core/java/com/android/server/trust/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/trust/OWNERS
diff --git a/services/core/java/com/android/server/tv/OWNERS b/services/core/java/com/android/server/tv/OWNERS
new file mode 100644
index 0000000..305027c
--- /dev/null
+++ b/services/core/java/com/android/server/tv/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/tv/OWNERS
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 1754e59..ff5b65b 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -77,6 +77,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -100,6 +101,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -329,18 +331,27 @@
             userState.packageSet.add(si.packageName);
         }
 
+        // sort the input list by input id so that TvInputState.inputNumber is stable.
+        Collections.sort(inputList, Comparator.comparing(TvInputInfo::getId));
         Map<String, TvInputState> inputMap = new HashMap<>();
+        ArrayMap<String, Integer> tisInputCount = new ArrayMap<>(inputMap.size());
         for (TvInputInfo info : inputList) {
+            String inputId = info.getId();
             if (DEBUG) {
-                Slog.d(TAG, "add " + info.getId());
+                Slog.d(TAG, "add " + inputId);
             }
-            TvInputState inputState = userState.inputMap.get(info.getId());
+            // Running count of input for each input service
+            Integer count = tisInputCount.get(inputId);
+            count = count == null ? Integer.valueOf(1) : count + 1;
+            tisInputCount.put(inputId, count);
+            TvInputState inputState = userState.inputMap.get(inputId);
             if (inputState == null) {
                 inputState = new TvInputState();
             }
             inputState.info = info;
             inputState.uid = getInputUid(info);
-            inputMap.put(info.getId(), inputState);
+            inputMap.put(inputId, inputState);
+            inputState.inputNumber = count;
         }
 
         for (String inputId : inputMap.keySet()) {
@@ -2452,11 +2463,31 @@
      */
     private void logTuneStateChanged(int state, SessionState sessionState,
             @Nullable TvInputState inputState) {
-        // TODO(b/173536904): log input type and id
+        int tisUid = Process.INVALID_UID;
+        int inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TIF_INPUT_TYPE_UNKNOWN;
+        int inputId = 0;
+        int hdmiPort = 0;
+        if (inputState != null) {
+            tisUid = inputState.uid;
+            inputType = inputState.info.getType();
+            if (inputType == TvInputInfo.TYPE_TUNER) {
+                inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TUNER;
+            }
+            inputId = inputState.inputNumber;
+            HdmiDeviceInfo hdmiDeviceInfo = inputState.info.getHdmiDeviceInfo();
+            if (hdmiDeviceInfo != null) {
+                hdmiPort = hdmiDeviceInfo.getPortId();
+            }
+        }
         FrameworkStatsLog.write(FrameworkStatsLog.TIF_TUNE_CHANGED,
                 new int[]{sessionState.callingUid,
-                        inputState == null ? Process.INVALID_UID : inputState.uid},
-                new String[]{"tif_player", "tv_input_service"}, state, sessionState.sessionId);
+                        tisUid},
+                new String[]{"tif_player", "tv_input_service"},
+                state,
+                sessionState.sessionId,
+                inputType,
+                inputId,
+                hdmiPort);
     }
 
     private static final class UserState {
@@ -2569,6 +2600,11 @@
         private TvInputInfo info;
 
         /**
+         * ID unique to a specific TvInputService.
+         */
+        private int inputNumber;
+
+        /**
          * The kernel user-ID that has been assigned to the application the TvInput is a part of.
          *
          * <p>
diff --git a/services/core/java/com/android/server/uri/OWNERS b/services/core/java/com/android/server/uri/OWNERS
new file mode 100644
index 0000000..cdc07ed
--- /dev/null
+++ b/services/core/java/com/android/server/uri/OWNERS
@@ -0,0 +1,3 @@
+jsharkey@android.com
+jsharkey@google.com
+varunshah@google.com
diff --git a/services/core/java/com/android/server/utils/Snapshots.java b/services/core/java/com/android/server/utils/Snapshots.java
index 33b2bd4..f2406ab 100644
--- a/services/core/java/com/android/server/utils/Snapshots.java
+++ b/services/core/java/com/android/server/utils/Snapshots.java
@@ -48,7 +48,7 @@
      * @param dst The destination array.  It must be empty.
      * @param src The source array
      */
-    public <E> void copy(@NonNull SparseArray<E> dst, @NonNull SparseArray<E> src) {
+    public static <E> void copy(@NonNull SparseArray<E> dst, @NonNull SparseArray<E> src) {
         if (dst.size() != 0) {
             throw new IllegalArgumentException("copy destination is not empty");
         }
@@ -83,7 +83,7 @@
      * @param dst The destination array.  It must be empty.
      * @param src The source array
      */
-    public void snapshot(@NonNull SparseIntArray dst, @NonNull SparseIntArray src) {
+    public static void snapshot(@NonNull SparseIntArray dst, @NonNull SparseIntArray src) {
         if (dst.size() != 0) {
             throw new IllegalArgumentException("snapshot destination is not empty");
         }
diff --git a/services/core/java/com/android/server/utils/WatchableIntentResolver.java b/services/core/java/com/android/server/utils/WatchableIntentResolver.java
new file mode 100644
index 0000000..767fc07
--- /dev/null
+++ b/services/core/java/com/android/server/utils/WatchableIntentResolver.java
@@ -0,0 +1,93 @@
+/*
+ * 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.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.server.IntentResolver;
+
+import java.util.List;
+
+/**
+ * A watched {@link IntentResolver}.  The parameters are inherited from the superclass.
+ * @param <F> The filter type
+ * @param <R> The resolver type.
+ * {@hide}
+ */
+public abstract class WatchableIntentResolver<F, R extends Object>
+        extends IntentResolver<F, R>
+        implements Watchable {
+
+    /**
+     * Watchable machinery
+     */
+    private final Watchable mWatchable = new WatchableImpl();
+    /**
+     * Register an observer to receive change notifications.
+     * @param observer The observer to register.
+     */
+    public void registerObserver(@NonNull Watcher observer) {
+        mWatchable.registerObserver(observer);
+    }
+    /**
+     * Unregister the observer, which will no longer receive change notifications.
+     * @param observer The observer to unregister.
+     */
+    public void unregisterObserver(@NonNull Watcher observer) {
+        mWatchable.unregisterObserver(observer);
+    }
+    /**
+     * Notify listeners that the object has changd.  The argument is a hint as to the
+     * source of the change.
+     * @param what The attribute or sub-object that changed, if not null.
+     */
+    public void dispatchChange(@Nullable Watchable what) {
+        mWatchable.dispatchChange(what);
+    }
+    /**
+     * Notify listeners that this object has changed.
+     */
+    protected void onChanged() {
+        dispatchChange(this);
+    }
+
+    @Override
+    public void addFilter(F f) {
+        super.addFilter(f);
+        onChanged();
+    }
+
+    @Override
+    public void removeFilter(F f) {
+        super.removeFilter(f);
+        onChanged();
+    }
+
+    @Override
+    protected void removeFilterInternal(F f) {
+        super.removeFilterInternal(f);
+        onChanged();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected void sortResults(List<R> results) {
+        super.sortResults(results);
+        onChanged();
+    }
+}
diff --git a/services/core/java/com/android/server/vcn/Android.bp b/services/core/java/com/android/server/vcn/Android.bp
new file mode 100644
index 0000000..5ed204f
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/Android.bp
@@ -0,0 +1,4 @@
+filegroup {
+    name: "framework-vcn-util-sources",
+    srcs: ["util/**/*.java"],
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
new file mode 100644
index 0000000..c060807
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -0,0 +1,314 @@
+/*
+ * 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.vcn;
+
+import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
+import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
+import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * TelephonySubscriptionTracker provides a caching layer for tracking active subscription groups.
+ *
+ * <p>This class performs two roles:
+ *
+ * <ol>
+ *   <li>De-noises subscription changes by ensuring that only changes in active and ready
+ *       subscription groups are acted upon
+ *   <li>Caches mapping between subIds and subscription groups
+ * </ol>
+ *
+ * <p>An subscription group is active and ready if any of its contained subIds has had BOTH the
+ * {@link CarrierConfigManager#isConfigForIdentifiedCarrier()} return true, AND the subscription is
+ * listed as active per SubscriptionManager#getAllSubscriptionInfoList().
+ *
+ * <p>Note that due to the asynchronous nature of callbacks and broadcasts, the output of this class
+ * is (only) eventually consistent.
+ *
+ * @hide
+ */
+public class TelephonySubscriptionTracker extends BroadcastReceiver {
+    @NonNull private static final String TAG = TelephonySubscriptionTracker.class.getSimpleName();
+    private static final boolean LOG_DBG = false; // STOPSHIP if true
+
+    @NonNull private final Context mContext;
+    @NonNull private final Handler mHandler;
+    @NonNull private final TelephonySubscriptionTrackerCallback mCallback;
+    @NonNull private final Dependencies mDeps;
+
+    @NonNull private final SubscriptionManager mSubscriptionManager;
+    @NonNull private final CarrierConfigManager mCarrierConfigManager;
+
+    // TODO (Android T+): Add ability to handle multiple subIds per slot.
+    @NonNull private final Map<Integer, Integer> mReadySubIdsBySlotId = new HashMap<>();
+    @NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener;
+
+    @NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot;
+
+    public TelephonySubscriptionTracker(
+            @NonNull Context context,
+            @NonNull Handler handler,
+            @NonNull TelephonySubscriptionTrackerCallback callback) {
+        this(context, handler, callback, new Dependencies());
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    TelephonySubscriptionTracker(
+            @NonNull Context context,
+            @NonNull Handler handler,
+            @NonNull TelephonySubscriptionTrackerCallback callback,
+            @NonNull Dependencies deps) {
+        mContext = Objects.requireNonNull(context, "Missing context");
+        mHandler = Objects.requireNonNull(handler, "Missing handler");
+        mCallback = Objects.requireNonNull(callback, "Missing callback");
+        mDeps = Objects.requireNonNull(deps, "Missing deps");
+
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+
+        mSubscriptionChangedListener =
+                new OnSubscriptionsChangedListener() {
+                    @Override
+                    public void onSubscriptionsChanged() {
+                        handleSubscriptionsChanged();
+                    }
+                };
+    }
+
+    /** Registers the receivers, and starts tracking subscriptions. */
+    public void register() {
+        mContext.registerReceiver(
+                this, new IntentFilter(ACTION_CARRIER_CONFIG_CHANGED), null, mHandler);
+        mSubscriptionManager.addOnSubscriptionsChangedListener(
+                new HandlerExecutor(mHandler), mSubscriptionChangedListener);
+    }
+
+    /** Unregisters the receivers, and stops tracking subscriptions. */
+    public void unregister() {
+        mContext.unregisterReceiver(this);
+        mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener);
+    }
+
+    /**
+     * Handles subscription changes, correlating available subscriptions and loaded carrier configs
+     *
+     * <p>The subscription change listener is registered with a HandlerExecutor backed by mHandler,
+     * so callbacks & broadcasts are all serialized on mHandler, avoiding the need for locking.
+     */
+    public void handleSubscriptionsChanged() {
+        final Set<ParcelUuid> activeSubGroups = new ArraySet<>();
+        final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>();
+
+        final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList();
+        if (allSubs == null) {
+            return; // Telephony crashed; no way to verify subscriptions.
+        }
+
+        // If allSubs is empty, no subscriptions exist. Cache will be cleared by virtue of no active
+        // subscriptions
+        for (SubscriptionInfo subInfo : allSubs) {
+            if (subInfo.getGroupUuid() == null) {
+                continue;
+            }
+
+            // Build subId -> subGrp cache
+            newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid());
+
+            // Update subscription groups that are both ready, and active. For a group to be
+            // considered active, both of the following must be true:
+            //
+            // 1. A final CARRIER_CONFIG_CHANGED (where config is for an identified carrier)
+            // broadcast must have been received for the subId
+            // 2. A active subscription (is loaded into a SIM slot) must be part of the subscription
+            // group.
+            if (subInfo.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX
+                    && mReadySubIdsBySlotId.values().contains(subInfo.getSubscriptionId())) {
+                activeSubGroups.add(subInfo.getGroupUuid());
+            }
+        }
+
+        final TelephonySubscriptionSnapshot newSnapshot =
+                new TelephonySubscriptionSnapshot(newSubIdToGroupMap, activeSubGroups);
+
+        // If snapshot was meaningfully updated, fire the callback
+        if (!newSnapshot.equals(mCurrentSnapshot)) {
+            mCurrentSnapshot = newSnapshot;
+            mHandler.post(
+                    () -> {
+                        mCallback.onNewSnapshot(newSnapshot);
+                    });
+        }
+    }
+
+    /**
+     * Broadcast receiver for ACTION_CARRIER_CONFIG_CHANGED
+     *
+     * <p>The broadcast receiver is registered with mHandler, so callbacks & broadcasts are all
+     * serialized on mHandler, avoiding the need for locking.
+     */
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // Accept sticky broadcasts; if CARRIER_CONFIG_CHANGED was previously broadcast and it
+        // already was for an identified carrier, we can stop waiting for initial load to complete
+        if (!ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
+            return;
+        }
+
+        final int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID);
+        final int slotId = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX);
+
+        if (slotId == INVALID_SIM_SLOT_INDEX) {
+            return;
+        }
+
+        if (SubscriptionManager.isValidSubscriptionId(subId)) {
+            final PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId);
+            if (mDeps.isConfigForIdentifiedCarrier(carrierConfigs)) {
+                Slog.v(TAG, String.format("SubId %s ready for SlotId %s", subId, slotId));
+                mReadySubIdsBySlotId.put(slotId, subId);
+                handleSubscriptionsChanged();
+            }
+        } else {
+            Slog.v(TAG, "Slot unloaded: " + slotId);
+            mReadySubIdsBySlotId.remove(slotId);
+            handleSubscriptionsChanged();
+        }
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    void setReadySubIdsBySlotId(Map<Integer, Integer> readySubIdsBySlotId) {
+        mReadySubIdsBySlotId.putAll(readySubIdsBySlotId);
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    Map<Integer, Integer> getReadySubIdsBySlotId() {
+        return Collections.unmodifiableMap(mReadySubIdsBySlotId);
+    }
+
+    /** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */
+    public static class TelephonySubscriptionSnapshot {
+        private final Map<Integer, ParcelUuid> mSubIdToGroupMap;
+        private final Set<ParcelUuid> mActiveGroups;
+
+        @VisibleForTesting(visibility = Visibility.PRIVATE)
+        TelephonySubscriptionSnapshot(
+                @NonNull Map<Integer, ParcelUuid> subIdToGroupMap,
+                @NonNull Set<ParcelUuid> activeGroups) {
+            mSubIdToGroupMap = Collections.unmodifiableMap(
+                    Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null"));
+            mActiveGroups = Collections.unmodifiableSet(
+                    Objects.requireNonNull(activeGroups, "activeGroups was null"));
+        }
+
+        /** Returns the active subscription groups */
+        @NonNull
+        public Set<ParcelUuid> getActiveSubscriptionGroups() {
+            return mActiveGroups;
+        }
+
+        /** Returns the Subscription Group for a given subId. */
+        @Nullable
+        public ParcelUuid getGroupForSubId(int subId) {
+            return mSubIdToGroupMap.get(subId);
+        }
+
+        /**
+         * Returns all the subIds in a given group, including available, but inactive subscriptions.
+         */
+        @NonNull
+        public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) {
+            final Set<Integer> subIds = new ArraySet<>();
+
+            for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) {
+                if (subGrp.equals(entry.getValue())) {
+                    subIds.add(entry.getKey());
+                }
+            }
+
+            return subIds;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mSubIdToGroupMap, mActiveGroups);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof TelephonySubscriptionSnapshot)) {
+                return false;
+            }
+
+            final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
+
+            return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+                    && mActiveGroups.equals(other.mActiveGroups);
+        }
+    }
+
+    /**
+     * Interface for listening to changes in subscriptions
+     *
+     * @see TelephonySubscriptionTracker
+     */
+    public interface TelephonySubscriptionTrackerCallback {
+        /**
+         * Called when subscription information changes, and a new subscription snapshot was taken
+         *
+         * @param snapshot the snapshot of subscription information.
+         */
+        void onNewSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot);
+    }
+
+    /** External static dependencies for test injection */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static class Dependencies {
+        /** Checks if the given bundle is for an identified carrier */
+        public boolean isConfigForIdentifiedCarrier(PersistableBundle bundle) {
+            return CarrierConfigManager.isConfigForIdentifiedCarrier(bundle);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/vibrator/OWNERS b/services/core/java/com/android/server/vibrator/OWNERS
new file mode 100644
index 0000000..7e7335d
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/OWNERS
@@ -0,0 +1 @@
+michaelwr@google.com
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index e2cdd02..b0266d0 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -47,7 +47,7 @@
         FINISHED,
         FORWARDED_TO_INPUT_DEVICES,
         CANCELLED,
-        ERROR_APP_OPS,
+        IGNORED_ERROR_APP_OPS,
         IGNORED,
         IGNORED_APP_OPS,
         IGNORED_BACKGROUND,
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 6a5d1c4..a34a507 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -16,12 +16,18 @@
 
 package com.android.server.vibrator;
 
+import android.app.ActivityManager;
+import android.app.IUidObserver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
@@ -30,7 +36,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -53,6 +59,7 @@
     private final Vibrator mVibrator;
     private final AudioManager mAudioManager;
     private final SettingsObserver mSettingObserver;
+    private final UidObserver mUidObserver;
 
     @GuardedBy("mLock")
     private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -72,12 +79,15 @@
     private int mNotificationIntensity;
     @GuardedBy("mLock")
     private int mRingIntensity;
+    @GuardedBy("mLock")
+    private boolean mLowPowerMode;
 
     public VibrationSettings(Context context, Handler handler) {
         mContext = context;
         mVibrator = context.getSystemService(Vibrator.class);
         mAudioManager = context.getSystemService(AudioManager.class);
         mSettingObserver = new SettingsObserver(handler);
+        mUidObserver = new UidObserver();
 
         registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
         registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
@@ -107,6 +117,35 @@
         mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK,
                 VibrationEffect.get(VibrationEffect.EFFECT_TICK, false));
 
+        try {
+            ActivityManager.getService().registerUidObserver(mUidObserver,
+                    ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
+                    ActivityManager.PROCESS_STATE_UNKNOWN, null);
+        } catch (RemoteException e) {
+            // ignored; both services live in system_server
+        }
+
+        PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class);
+        pm.registerLowPowerModeObserver(
+                new PowerManagerInternal.LowPowerModeListener() {
+                    @Override
+                    public int getServiceType() {
+                        return PowerManager.ServiceType.VIBRATION;
+                    }
+
+                    @Override
+                    public void onLowPowerModeChanged(PowerSaveState result) {
+                        boolean shouldNotifyListeners;
+                        synchronized (mLock) {
+                            shouldNotifyListeners = result.batterySaverEnabled != mLowPowerMode;
+                            mLowPowerMode = result.batterySaverEnabled;
+                        }
+                        if (shouldNotifyListeners) {
+                            notifyListeners();
+                        }
+                    }
+                });
+
         // Update with current values from settings.
         updateSettings();
     }
@@ -184,12 +223,15 @@
     }
 
     /**
-     * Return {@code true} if the device should vibrate for ringtones.
+     * Return {@code true} if the device should vibrate for current ringer mode.
      *
      * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings
-     * for vibrations while ringing.
+     * for ringtone usage only. All other usages are allowed independently of ringer mode.
      */
-    public boolean shouldVibrateForRingtone() {
+    public boolean shouldVibrateForRingerMode(int usageHint) {
+        if (!isRingtone(usageHint)) {
+            return true;
+        }
         int ringerMode = mAudioManager.getRingerModeInternal();
         synchronized (mLock) {
             if (mVibrateWhenRinging) {
@@ -202,6 +244,28 @@
         }
     }
 
+    /**
+     * Returns {@code true} if this vibration is allowed for given {@code uid}.
+     *
+     * <p>This checks if the user is aware of this foreground process, or if the vibration usage is
+     * allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration).
+     */
+    public boolean shouldVibrateForUid(int uid, int usageHint) {
+        return mUidObserver.isUidForeground(uid) || isNotification(usageHint)
+                || isRingtone(usageHint) || isAlarm(usageHint);
+    }
+
+    /**
+     * Returns {@code true} if this vibration is allowed for current power mode state.
+     *
+     * <p>This checks if the device is in battery saver mode, in which case only alarm, ringtone and
+     * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate.
+     */
+    public boolean shouldVibrateForPowerMode(int usageHint) {
+        return !mLowPowerMode || isRingtone(usageHint) || isAlarm(usageHint)
+                || usageHint == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+    }
+
     /** Return {@code true} if input devices should vibrate instead of this device. */
     public boolean shouldVibrateInputDevices() {
         return mVibrateInputDevices;
@@ -229,9 +293,7 @@
     }
 
     /** Updates all vibration settings and triggers registered listeners. */
-    @VisibleForTesting
     public void updateSettings() {
-        List<OnVibratorSettingsChanged> currentListeners;
         synchronized (mLock) {
             mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
             mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0;
@@ -244,12 +306,8 @@
                     mVibrator.getDefaultRingVibrationIntensity());
             mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
             mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
-            currentListeners = new ArrayList<>(mListeners);
         }
-
-        for (OnVibratorSettingsChanged listener : currentListeners) {
-            listener.onChange();
-        }
+        notifyListeners();
     }
 
     @Override
@@ -258,9 +316,11 @@
                 + "mVibrateInputDevices=" + mVibrateInputDevices
                 + ", mVibrateWhenRinging=" + mVibrateWhenRinging
                 + ", mApplyRampingRinger=" + mApplyRampingRinger
+                + ", mLowPowerMode=" + mLowPowerMode
                 + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode)
+                + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
                 + ", mHapticFeedbackIntensity="
-                +  intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH))
+                + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH))
                 + ", mHapticFeedbackDefaultIntensity="
                 + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_TOUCH))
                 + ", mNotificationIntensity="
@@ -274,6 +334,16 @@
                 + '}';
     }
 
+    private void notifyListeners() {
+        List<OnVibratorSettingsChanged> currentListeners;
+        synchronized (mLock) {
+            currentListeners = new ArrayList<>(mListeners);
+        }
+        for (OnVibratorSettingsChanged listener : currentListeners) {
+            listener.onChange();
+        }
+    }
+
     private static String intensityToString(int intensity) {
         switch (intensity) {
             case Vibrator.VIBRATION_INTENSITY_OFF:
@@ -342,4 +412,36 @@
             updateSettings();
         }
     }
+
+    /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
+    private final class UidObserver extends IUidObserver.Stub {
+        private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
+
+        public boolean isUidForeground(int uid) {
+            return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
+                    <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+        }
+
+        @Override
+        public void onUidGone(int uid, boolean disabled) {
+            mProcStatesCache.delete(uid);
+        }
+
+        @Override
+        public void onUidActive(int uid) {
+        }
+
+        @Override
+        public void onUidIdle(int uid, boolean disabled) {
+        }
+
+        @Override
+        public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
+            mProcStatesCache.put(uid, procState);
+        }
+
+        @Override
+        public void onUidCachedChanged(int uid, boolean cached) {
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index f76c1a1..311c73b 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -23,7 +23,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.VibrationEffect;
-import android.os.Vibrator;
+import android.os.VibratorInfo;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -31,10 +31,6 @@
 
 import libcore.util.NativeAllocationRegistry;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
 /** Controls a single vibrator. */
 // TODO(b/159207608): Make this package-private once vibrator services are moved to this package
 public final class VibratorController {
@@ -42,12 +38,7 @@
 
     private final Object mLock = new Object();
     private final NativeWrapper mNativeWrapper;
-    private final int mVibratorId;
-    private final long mCapabilities;
-    @Nullable
-    private final Set<Integer> mSupportedEffects;
-    @Nullable
-    private final Set<Integer> mSupportedPrimitives;
+    private final VibratorInfo mVibratorInfo;
 
     @GuardedBy("mLock")
     private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
@@ -115,13 +106,11 @@
     @VisibleForTesting
     public VibratorController(int vibratorId, OnVibrationCompleteListener listener,
             NativeWrapper nativeWrapper) {
-        mVibratorId = vibratorId;
         mNativeWrapper = nativeWrapper;
+        mNativeWrapper.init(vibratorId, listener);
 
-        nativeWrapper.init(vibratorId, listener);
-        mCapabilities = nativeWrapper.getCapabilities();
-        mSupportedEffects = asSet(nativeWrapper.getSupportedEffects());
-        mSupportedPrimitives = asSet(nativeWrapper.getSupportedPrimitives());
+        mVibratorInfo = new VibratorInfo(vibratorId, nativeWrapper.getCapabilities(),
+                nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives());
     }
 
     /** Register state listener for this vibrator. */
@@ -153,9 +142,9 @@
         }
     }
 
-    /** Return the id of the vibrator controlled by this instance. */
-    public int getVibratorId() {
-        return mVibratorId;
+    /** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */
+    public VibratorInfo getVibratorInfo() {
+        return mVibratorInfo;
     }
 
     /**
@@ -184,43 +173,7 @@
      * @return true if this vibrator has this capability, false otherwise
      */
     public boolean hasCapability(long capability) {
-        return (mCapabilities & capability) == capability;
-    }
-
-    /**
-     * Check against this vibrator supported effects.
-     *
-     * @param effectIds list of effects, one of VibrationEffect.EFFECT_*
-     * @return one entry per requested effectId, with one of Vibrator.VIBRATION_EFFECT_SUPPORT_*
-     */
-    public int[] areEffectsSupported(int[] effectIds) {
-        int[] supported = new int[effectIds.length];
-        if (mSupportedEffects == null) {
-            Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN);
-        } else {
-            for (int i = 0; i < effectIds.length; i++) {
-                supported[i] = mSupportedEffects.contains(effectIds[i])
-                        ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES
-                        : Vibrator.VIBRATION_EFFECT_SUPPORT_NO;
-            }
-        }
-        return supported;
-    }
-
-    /**
-     * Check against this vibrator supported primitives.
-     *
-     * @param primitiveIds list of primitives, one of VibrationEffect.Composition.EFFECT_*
-     * @return one entry per requested primitiveId, with true if it is supported
-     */
-    public boolean[] arePrimitivesSupported(int[] primitiveIds) {
-        boolean[] supported = new boolean[primitiveIds.length];
-        if (mSupportedPrimitives != null && hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
-            for (int i = 0; i < primitiveIds.length; i++) {
-                supported[i] = mSupportedPrimitives.contains(primitiveIds[i]);
-            }
-        }
-        return supported;
+        return mVibratorInfo.hasCapability(capability);
     }
 
     /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */
@@ -234,7 +187,7 @@
      * <p>This will affect the state of {@link #isUnderExternalControl()}.
      */
     public void setExternalControl(boolean externalControl) {
-        if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
             return;
         }
         synchronized (mLock) {
@@ -248,7 +201,7 @@
      * if given {@code effect} is {@code null}.
      */
     public void updateAlwaysOn(int id, @Nullable VibrationEffect.Prebaked effect) {
-        if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
             return;
         }
         synchronized (mLock) {
@@ -263,7 +216,7 @@
     /** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */
     public void setAmplitude(int amplitude) {
         synchronized (mLock) {
-            if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
+            if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
                 mNativeWrapper.setAmplitude(amplitude);
             }
         }
@@ -306,7 +259,7 @@
      * <p>This will affect the state of {@link #isVibrating()}.
      */
     public void on(VibrationEffect.Composed effect, long vibrationId) {
-        if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
             return;
         }
         synchronized (mLock) {
@@ -327,10 +280,7 @@
     @Override
     public String toString() {
         return "VibratorController{"
-                + "mVibratorId=" + mVibratorId
-                + ", mCapabilities=" + mCapabilities
-                + ", mSupportedEffects=" + mSupportedEffects
-                + ", mSupportedPrimitives=" + mSupportedPrimitives
+                + "mVibratorInfo=" + mVibratorInfo
                 + ", mIsVibrating=" + mIsVibrating
                 + ", mIsUnderExternalControl=" + mIsUnderExternalControl
                 + ", mVibratorStateListeners count="
@@ -375,18 +325,6 @@
         }
     }
 
-    @Nullable
-    private static Set<Integer> asSet(int[] values) {
-        if (values == null) {
-            return null;
-        }
-        HashSet<Integer> set = new HashSet<>();
-        for (int value : values) {
-            set.add(value);
-        }
-        return set;
-    }
-
     /** Wrapper around the static-native methods of {@link VibratorController} for tests. */
     @VisibleForTesting
     public static class NativeWrapper {
diff --git a/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java
index 60b08dd..a4ddf11 100644
--- a/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/IWallpaperManagerService.java
@@ -29,7 +29,7 @@
     void onBootPhase(int phase);
 
     /**
-     * @see com.android.server.SystemService#onUnlockUser(int)
+     * @see com.android.server.SystemService#onUserUnlocking
      */
     void onUnlockUser(final int userId);
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wallpaper/OWNERS b/services/core/java/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 6bd4990..2ecefea 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -654,7 +654,7 @@
 
             private final Path mCircularPath;
 
-            private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain();
+            private final MagnificationSpec mMagnificationSpec = new MagnificationSpec();
 
             private final float mBorderWidth;
             private final int mHalfBorderWidth;
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 9f1152c..1387311 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -39,12 +39,15 @@
 import static com.android.server.wm.Task.ActivityState.DESTROYED;
 import static com.android.server.wm.Task.ActivityState.DESTROYING;
 
+import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.IActivityClientController;
 import android.app.PictureInPictureParams;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.EnterPipRequestedItem;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -538,6 +541,22 @@
     }
 
     @Override
+    public int getLaunchedFromUid(IBinder token) {
+        synchronized (mGlobalLock) {
+            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+            return r != null ? r.launchedFromUid : android.os.Process.INVALID_UID;
+        }
+    }
+
+    @Override
+    public String getLaunchedFromPackage(IBinder token) {
+        synchronized (mGlobalLock) {
+            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+            return r != null ? r.launchedFromPackage : null;
+        }
+    }
+
+    @Override
     public Bundle getActivityOptions(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -720,6 +739,38 @@
         return r;
     }
 
+    /**
+     * Requests that an activity should enter picture-in-picture mode if possible. This method may
+     * be used by the implementation of non-phone form factors.
+     */
+    void requestPictureInPictureMode(@NonNull ActivityRecord r) {
+        if (r.inPinnedWindowingMode()) {
+            throw new IllegalStateException("Activity is already in PIP mode");
+        }
+
+        final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
+                "requestPictureInPictureMode", /* beforeStopping */ false);
+        if (!canEnterPictureInPicture) {
+            throw new IllegalStateException(
+                    "Requested PIP on an activity that doesn't support it");
+        }
+
+        if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
+            mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
+            return;
+        }
+
+        try {
+            final ClientTransaction transaction = ClientTransaction.obtain(
+                    r.app.getThread(), r.token);
+            transaction.addCallback(EnterPipRequestedItem.obtain());
+            mService.getLifecycleManager().scheduleTransaction(transaction);
+        } catch (Exception e) {
+            Slog.w(TAG, "Failed to send enter pip requested item: "
+                    + r.intent.getComponent(), e);
+        }
+    }
+
     @Override
     public void toggleFreeformWindowingMode(IBinder token) {
         final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 6a50b79..b084787 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -631,6 +631,10 @@
         if (info.mLoggedTransitionStarting && info.allDrawn()) {
             done(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs);
         }
+        if (r.mWmService.isRecentsAnimationTarget(r)) {
+            r.mWmService.getRecentsAnimationController().logRecentsAnimationStartTime(
+                    info.mSourceEventDelayMs + info.mWindowsDrawnDelayMs);
+        }
         return infoSnapshot;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 743796b..3390d67 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -95,18 +95,18 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_OLD_UNSET;
+import static android.view.SurfaceControl.getGlobalTransaction;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_UNSET;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -182,7 +182,6 @@
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
-import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.Task.ActivityState.DESTROYED;
 import static com.android.server.wm.Task.ActivityState.DESTROYING;
 import static com.android.server.wm.Task.ActivityState.FINISHING;
@@ -194,6 +193,7 @@
 import static com.android.server.wm.Task.ActivityState.STARTED;
 import static com.android.server.wm.Task.ActivityState.STOPPED;
 import static com.android.server.wm.Task.ActivityState.STOPPING;
+import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.TaskPersister.DEBUG;
 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
@@ -219,7 +219,6 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -294,6 +293,7 @@
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
+import android.window.TaskSnapshot;
 import android.window.WindowContainerToken;
 
 import com.android.internal.R;
@@ -1366,7 +1366,6 @@
         } else if (mLetterbox != null) {
             mLetterbox.hide();
         }
-        task.maybeUpdateLetterboxBounds(this, getLetterboxParams(w));
     }
 
     void updateLetterboxSurface(WindowState winHint) {
@@ -1380,12 +1379,6 @@
         }
     }
 
-    @Nullable
-    private Rect getLetterboxParams(WindowState w) {
-        boolean isLetterboxed = w.isLetterboxedAppWindow() && fillsParent();
-        return isLetterboxed ? getBounds() : null;
-    }
-
     Rect getLetterboxInsets() {
         if (mLetterbox != null) {
             return mLetterbox.getInsets();
@@ -1763,9 +1756,12 @@
             return false;
         }
 
-        final ActivityManager.TaskSnapshot snapshot =
+        final TaskSnapshot snapshot =
                 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
                         false /* restoreFromDisk */, false /* isLowResolution */);
+        final int typeParameter = mWmService.mStartingSurfaceController
+                .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
+                        allowTaskSnapshot, activityCreated);
         final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
                 allowTaskSnapshot, activityCreated, snapshot);
 
@@ -1780,7 +1776,7 @@
                     return false;
                 }
             }
-            return createSnapshot(snapshot);
+            return createSnapshot(snapshot, typeParameter);
         }
 
         // If this is a translucent window, then don't show a starting window -- the current
@@ -1840,18 +1836,18 @@
         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
         mStartingData = new SplashScreenStartingData(mWmService, pkg,
                 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
-                getMergedOverrideConfiguration());
+                getMergedOverrideConfiguration(), typeParameter);
         scheduleAddStartingWindow();
         return true;
     }
 
-    private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
+    private boolean createSnapshot(TaskSnapshot snapshot, int typeParams) {
         if (snapshot == null) {
             return false;
         }
 
         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
-        mStartingData = new SnapshotStartingData(mWmService, snapshot);
+        mStartingData = new SnapshotStartingData(mWmService, snapshot, typeParams);
         scheduleAddStartingWindow();
         return true;
     }
@@ -1930,7 +1926,7 @@
 
     private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
             boolean allowTaskSnapshot, boolean activityCreated,
-            ActivityManager.TaskSnapshot snapshot) {
+            TaskSnapshot snapshot) {
         if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
             return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
         } else if (taskSwitch && allowTaskSnapshot) {
@@ -1951,7 +1947,7 @@
      * rotation must be the same).
      */
     @VisibleForTesting
-    boolean isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot) {
+    boolean isSnapshotCompatible(TaskSnapshot snapshot) {
         if (snapshot == null) {
             return false;
         }
@@ -2562,7 +2558,7 @@
         }
 
         final Task rootTask = getRootTask();
-        final boolean mayAdjustTop = (isState(RESUMED) || rootTask.mResumedActivity == null)
+        final boolean mayAdjustTop = (isState(RESUMED) || rootTask.getResumedActivity() == null)
                 && rootTask.isFocusedStackOnDisplay()
                 // Do not adjust focus task because the task will be reused to launch new activity.
                 && !task.isClearingToReuseTask();
@@ -2634,12 +2630,12 @@
                 // Tell window manager to prepare for this one to be removed.
                 setVisibility(false);
 
-                if (rootTask.mPausingActivity == null) {
+                if (task.getPausingActivity() == null) {
                     ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);
                     if (DEBUG_USER_LEAVING) {
                         Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
                     }
-                    rootTask.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
+                    task.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
                             null /* resuming */, "finish");
                 }
 
@@ -2727,7 +2723,7 @@
         final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED);
         if (isCurrentVisible) {
             final Task stack = getStack();
-            final ActivityRecord activity = stack.mResumedActivity;
+            final ActivityRecord activity = stack.getResumedActivity();
             boolean ensureVisibility = false;
             if (activity != null && !activity.occludesParent()) {
                 // If the resume activity is not opaque, we need to make sure the visibilities of
@@ -2955,10 +2951,10 @@
     boolean safelyDestroy(String reason) {
         if (isDestroyable()) {
             if (DEBUG_SWITCH) {
-                final Task stack = getRootTask();
+                final Task task = getTask();
                 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
-                        + " resumed=" + stack.mResumedActivity
-                        + " pausing=" + stack.mPausingActivity
+                        + " resumed=" + task.getResumedActivity()
+                        + " pausing=" + task.getPausingActivity()
                         + " for reason " + reason);
             }
             return destroyImmediately(reason);
@@ -3131,7 +3127,7 @@
         SurfaceControl.openTransaction();
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final WindowState w = mChildren.get(i);
-            w.mWinAnimator.detachChildren();
+            w.mWinAnimator.detachChildren(getGlobalTransaction());
         }
         SurfaceControl.closeTransaction();
     }
@@ -4443,7 +4439,8 @@
             SurfaceControl.openTransaction();
             try {
                 forAllWindows(win -> {
-                    win.mWinAnimator.hide("immediately hidden"); }, true);
+                    win.mWinAnimator.hide(getGlobalTransaction(), "immediately hidden");
+                }, true);
             } finally {
                 SurfaceControl.closeTransaction();
             }
@@ -4835,7 +4832,7 @@
                     // If the app is capable of entering PIP, we should try pausing it now
                     // so it can PIP correctly.
                     if (deferHidingClient) {
-                        getRootTask().startPausingLocked(userLeaving, false /* uiSleeping */,
+                        task.startPausingLocked(userLeaving, false /* uiSleeping */,
                                 null /* resuming */, "makeInvisible");
                         break;
                     }
@@ -5066,25 +5063,24 @@
         ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken,
                 timeout);
 
-        final Task stack = getStack();
-
-        if (stack != null) {
+        if (task != null) {
             removePauseTimeout();
 
-            if (stack.mPausingActivity == this) {
+            final ActivityRecord pausingActivity = task.getPausingActivity();
+            if (pausingActivity == this) {
                 ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
                         (timeout ? "(due to timeout)" : " (pause complete)"));
                 mAtmService.deferWindowLayout();
                 try {
-                    stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
+                    task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                 } finally {
                     mAtmService.continueWindowLayout();
                 }
                 return;
             } else {
                 EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
-                        shortComponentName, stack.mPausingActivity != null
-                                ? stack.mPausingActivity.shortComponentName : "(none)");
+                        shortComponentName, pausingActivity != null
+                                ? pausingActivity.shortComponentName : "(none)");
                 if (isState(PAUSING)) {
                     setState(PAUSED, "activityPausedLocked");
                     if (finishing) {
@@ -5182,10 +5178,9 @@
 
     void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
             CharSequence description) {
-        final Task stack = getRootTask();
         final boolean isStopping = mState == STOPPING;
         if (!isStopping && mState != RESTARTING_PROCESS) {
-            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
+            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this + " " + mState);
             removeStopTimeout();
             return;
         }
@@ -5222,6 +5217,7 @@
                     mRootWindowContainer.updatePreviousProcess(this);
                 }
             }
+            mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
         }
     }
 
@@ -5714,14 +5710,14 @@
         // First find the real culprit...  if this activity has stopped, then the key dispatching
         // timeout should not be caused by this.
         if (stopped) {
-            final Task stack = mRootWindowContainer.getTopDisplayFocusedRootTask();
-            if (stack == null) {
+            final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
+            if (rootTask == null) {
                 return this;
             }
             // Try to use the one which is closest to top.
-            ActivityRecord r = stack.getResumedActivity();
+            ActivityRecord r = rootTask.getResumedActivity();
             if (r == null) {
-                r = stack.mPausingActivity;
+                r = rootTask.getPausingActivity();
             }
             if (r != null) {
                 return r;
@@ -5799,9 +5795,8 @@
             // This would be redundant.
             return false;
         }
-        final Task stack = getRootTask();
-        if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
-                || !stopped) {
+        if (isState(RESUMED) || getRootTask() == null || this == task.getPausingActivity()
+                || !mHaveState || !stopped) {
             // We're not ready for this kind of thing.
             return false;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1ff3a3f..1b0bec5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1883,7 +1883,7 @@
         }
 
         mSupervisor.getLaunchParamsController().calculate(targetTask, r.info.windowLayout, r,
-                sourceRecord, mOptions, PHASE_BOUNDS, mLaunchParams, mRequest);
+                sourceRecord, mOptions, mRequest, PHASE_BOUNDS, mLaunchParams);
         mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
                 ? mLaunchParams.mPreferredTaskDisplayArea
                 : mRootWindowContainer.getDefaultTaskDisplayArea();
@@ -2274,7 +2274,7 @@
         // Preferred display id is the only state we need for now and it could be updated again
         // after we located a reusable task (which might be resided in another display).
         mSupervisor.getLaunchParamsController().calculate(inTask, r.info.windowLayout, r,
-                sourceRecord, options, PHASE_DISPLAY, mLaunchParams, mRequest);
+                sourceRecord, options, mRequest, PHASE_DISPLAY, mLaunchParams);
         mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
                 ? mLaunchParams.mPreferredTaskDisplayArea
                 : mRootWindowContainer.getDefaultTaskDisplayArea();
@@ -2647,7 +2647,11 @@
             if (next != null) {
                 next.setCurrentLaunchCanTurnScreenOn(true);
             }
-            mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetStack, null, mOptions);
+            if (mTargetStack.isFocusable()) {
+                mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetStack, null, mOptions);
+            } else {
+                mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+            }
         } else {
             ActivityOptions.abort(mOptions);
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index a5df2a6..9ffedde 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.ActivityManager;
 import android.app.AppProtoEnums;
 import android.app.IActivityManager;
 import android.app.IApplicationThread;
@@ -34,6 +33,7 @@
 import android.os.RemoteException;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.proto.ProtoOutputStream;
+import android.window.TaskSnapshot;
 
 import com.android.internal.app.IVoiceInteractor;
 import com.android.server.am.PendingIntentRecord;
@@ -386,6 +386,10 @@
     public abstract void clearPendingResultForActivity(
             IBinder activityToken, WeakReference<PendingIntentRecord> pir);
 
+    /** Returns the component name of the activity token. */
+    @Nullable
+    public abstract ComponentName getActivityName(IBinder activityToken);
+
     /**
      * @return the activity token and IApplicationThread for the top activity in the task or null
      * if there isn't a top activity with a valid process.
@@ -548,7 +552,7 @@
      * <p>Warning! this may restore the snapshot from disk so can block, don't call in a latency
      * sensitive environment.
      */
-    public abstract ActivityManager.TaskSnapshot getTaskSnapshotBlocking(int taskId,
+    public abstract TaskSnapshot getTaskSnapshotBlocking(int taskId,
             boolean isLowResolution);
 
     /** Returns true if uid is considered foreground for activity start purposes. */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8298dfd..ce70978 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -148,8 +148,6 @@
 import android.app.admin.DevicePolicyCache;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
-import android.app.servertransaction.ClientTransaction;
-import android.app.servertransaction.EnterPipRequestedItem;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -220,6 +218,7 @@
 import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager;
 import android.window.IWindowOrganizerController;
+import android.window.TaskSnapshot;
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.R;
@@ -1133,9 +1132,10 @@
         synchronized (mGlobalLock) {
             // If this is coming from the currently resumed activity, it is
             // effectively saying that app switches are allowed at this point.
-            final Task stack = getTopDisplayFocusedRootTask();
-            if (stack != null && stack.mResumedActivity != null
-                    && stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) {
+            final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
+            if (topFocusedRootTask != null && topFocusedRootTask.getResumedActivity() != null
+                    && topFocusedRootTask.getResumedActivity().info.applicationInfo.uid
+                    == Binder.getCallingUid()) {
                 mAppSwitchesAllowedTime = 0;
             }
         }
@@ -1743,29 +1743,6 @@
         }
     }
 
-    @Override
-    public int getLaunchedFromUid(IBinder activityToken) {
-        ActivityRecord srec;
-        synchronized (mGlobalLock) {
-            srec = ActivityRecord.forTokenLocked(activityToken);
-        }
-        if (srec == null) {
-            return -1;
-        }
-        return srec.launchedFromUid;
-    }
-
-    @Override
-    public String getLaunchedFromPackage(IBinder activityToken) {
-        ActivityRecord srec;
-        synchronized (mGlobalLock) {
-            srec = ActivityRecord.forTokenLocked(activityToken);
-        }
-        if (srec == null) {
-            return null;
-        }
-        return srec.launchedFromPackage;
-    }
 
     @Override
     public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException {
@@ -2560,9 +2537,7 @@
 
     @Override
     public int getLockTaskModeState() {
-        synchronized (mGlobalLock) {
-            return getLockTaskController().getLockTaskModeState();
-        }
+        return getLockTaskController().getLockTaskModeState();
     }
 
     @Override
@@ -3228,28 +3203,6 @@
     }
 
     @Override
-    public ComponentName getActivityClassForToken(IBinder token) {
-        synchronized (mGlobalLock) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                return null;
-            }
-            return r.intent.getComponent();
-        }
-    }
-
-    @Override
-    public String getPackageForToken(IBinder token) {
-        synchronized (mGlobalLock) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                return null;
-            }
-            return r.packageName;
-        }
-    }
-
-    @Override
     public void keyguardGoingAway(int flags) {
         enforceNotIsolatedCaller("keyguardGoingAway");
         final long token = Binder.clearCallingIdentity();
@@ -3298,23 +3251,15 @@
         }
     }
 
-    @VisibleForTesting
-    boolean isInPictureInPictureMode(ActivityRecord r) {
-        return r != null
-                && r.getRootTask() != null
-                && r.inPinnedWindowingMode()
-                && r.getRootTask().isInTask(r) != null;
-    }
-
     /**
      * Puts the given activity in picture in picture mode if possible.
      *
      * @return true if the activity is now in picture-in-picture mode, or false if it could not
      * enter picture-in-picture mode.
      */
-    boolean enterPictureInPictureMode(ActivityRecord r, final PictureInPictureParams params) {
+    boolean enterPictureInPictureMode(@NonNull ActivityRecord r, PictureInPictureParams params) {
         // If the activity is already in picture in picture mode, then just return early
-        if (isInPictureInPictureMode(r)) {
+        if (r.inPinnedWindowingMode()) {
             return true;
         }
 
@@ -3509,7 +3454,7 @@
     }
 
     @Override
-    public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
+    public TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
         enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -3519,7 +3464,7 @@
         }
     }
 
-    private ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution,
+    private TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution,
             boolean restoreFromDisk) {
         final Task task;
         synchronized (mGlobalLock) {
@@ -3799,52 +3744,6 @@
         }
     }
 
-    /**
-     * Requests that an activity should enter picture-in-picture mode if possible.
-     */
-    @Override
-    public void requestPictureInPictureMode(IBinder token) throws RemoteException {
-        enforceTaskPermission("requestPictureInPictureMode");
-        final long origId = Binder.clearCallingIdentity();
-        try {
-            synchronized (mGlobalLock) {
-                final ActivityRecord activity = ActivityRecord.forTokenLocked(token);
-                if (activity == null) {
-                    return;
-                }
-
-                if (isInPictureInPictureMode(activity)) {
-                    throw new IllegalStateException("Activity is already in PIP mode");
-                }
-
-                final boolean canEnterPictureInPicture = activity.checkEnterPictureInPictureState(
-                        "requestPictureInPictureMode", /* beforeStopping */ false);
-                if (!canEnterPictureInPicture) {
-                    throw new IllegalStateException(
-                            "Requested PIP on an activity that doesn't support it");
-                }
-
-                if (activity.pictureInPictureArgs.isAutoEnterEnabled()) {
-                    enterPictureInPictureMode(activity, activity.pictureInPictureArgs);
-                    return;
-                }
-
-                try {
-                    final ClientTransaction transaction = ClientTransaction.obtain(
-                            activity.app.getThread(),
-                            activity.token);
-                    transaction.addCallback(EnterPipRequestedItem.obtain());
-                    getLifecycleManager().scheduleTransaction(transaction);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Failed to send enter pip requested item: "
-                            + activity.intent.getComponent(), e);
-                }
-            }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
-        }
-    }
-
     void dumpLastANRLocked(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
         if (mLastANRState == null) {
@@ -4708,8 +4607,11 @@
                             .setContentTitle(text)
                             .setContentText(
                                     mContext.getText(R.string.heavy_weight_notification_detail))
+                            // TODO(b/175194709) Please replace FLAG_MUTABLE_UNAUDITED below
+                            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                             .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
-                                    intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+                                    intent, PendingIntent.FLAG_CANCEL_CURRENT
+                                    | PendingIntent.FLAG_MUTABLE_UNAUDITED, null,
                                     new UserHandle(userId)))
                             .build();
             try {
@@ -5596,6 +5498,14 @@
         }
 
         @Override
+        public ComponentName getActivityName(IBinder activityToken) {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                return r != null ? r.intent.getComponent() : null;
+            }
+        }
+
+        @Override
         public ActivityTokens getTopActivityForTask(int taskId) {
             synchronized (mGlobalLock) {
                 final Task task = mRootWindowContainer.anyTaskForId(taskId);
@@ -6376,7 +6286,7 @@
         }
 
         @Override
-        public ActivityManager.TaskSnapshot getTaskSnapshotBlocking(
+        public TaskSnapshot getTaskSnapshotBlocking(
                 int taskId, boolean isLowResolution) {
             return ActivityTaskManagerService.this.getTaskSnapshot(taskId, isLowResolution,
                     true /* restoreFromDisk */);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 73d9972..400633c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -88,6 +88,7 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.AppOpsManager;
+import android.app.IActivityClientController;
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.app.WaitResult;
@@ -795,6 +796,11 @@
                                 + " old=" + r.app + " new=" + proc);
             }
 
+            // Send the controller to client if the process is the first time to launch activity.
+            // So the client can save binder transactions of getting the controller from activity
+            // task manager service.
+            final IActivityClientController activityClientController =
+                    proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
             r.launchCount++;
             r.lastLaunchTime = SystemClock.uptimeMillis();
             proc.setLastActivityLaunchTime(r.lastLaunchTime);
@@ -863,7 +869,8 @@
                         r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                         r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                         dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
-                        r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
+                        r.assistToken, activityClientController,
+                        r.createFixedRotationAdjustmentsIfNeeded()));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
@@ -2059,7 +2066,7 @@
     void updateTopResumedActivityIfNeeded() {
         final ActivityRecord prevTopActivity = mTopResumedActivity;
         final Task topStack = mRootWindowContainer.getTopDisplayFocusedRootTask();
-        if (topStack == null || topStack.mResumedActivity == prevTopActivity) {
+        if (topStack == null || topStack.getResumedActivity() == prevTopActivity) {
             if (mService.isSleepingLocked()) {
                 // There won't be a next resumed activity. The top process should still be updated
                 // according to the current top focused activity.
@@ -2081,7 +2088,7 @@
         }
 
         // Update the current top activity.
-        mTopResumedActivity = topStack.mResumedActivity;
+        mTopResumedActivity = topStack.getResumedActivity();
         scheduleTopResumedActivityStateIfNeeded();
 
         mService.updateTopApp(mTopResumedActivity);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 758aaa0..605a23e 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams;
-import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
@@ -2092,8 +2092,8 @@
             case TRANSIT_RELAUNCH: {
                 return "TRANSIT_RELAUNCH";
             }
-            case TRANSIT_CHANGE_WINDOWING_MODE: {
-                return "TRANSIT_CHANGE_WINDOWING_MODE";
+            case TRANSIT_CHANGE: {
+                return "TRANSIT_CHANGE";
             }
             case TRANSIT_KEYGUARD_GOING_AWAY: {
                 return "TRANSIT_KEYGUARD_GOING_AWAY";
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 64cbb0de..dde527d 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
@@ -303,7 +303,7 @@
 
         // Special transitions
         // TODO(new-app-transitions): Revisit if those can be rewritten by using flags.
-        if (appTransition.containsTransitRequest(TRANSIT_CHANGE_WINDOWING_MODE)) {
+        if (appTransition.containsTransitRequest(TRANSIT_CHANGE)) {
             return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
         }
         if ((flags & TRANSIT_FLAG_APP_CRASHED) != 0) {
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 07729d1..029056a 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -204,7 +204,7 @@
     }
 
     private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
-            float alpha) {
+            float alpha, int blurRadius) {
         final DimState d = getDimState(container);
 
         if (d == null) {
@@ -220,6 +220,7 @@
             t.setLayer(d.mDimLayer, Integer.MAX_VALUE);
         }
         t.setAlpha(d.mDimLayer, alpha);
+        t.setBackgroundBlurRadius(d.mDimLayer, blurRadius);
 
         d.mDimming = true;
     }
@@ -247,7 +248,7 @@
      * @param alpha The alpha at which to Dim.
      */
     void dimAbove(SurfaceControl.Transaction t, float alpha) {
-        dim(t, null, 1, alpha);
+        dim(t, null, 1, alpha, 0);
     }
 
     /**
@@ -260,19 +261,21 @@
      * @param alpha     The alpha at which to Dim.
      */
     void dimAbove(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
-        dim(t, container, 1, alpha);
+        dim(t, container, 1, alpha, 0);
     }
 
     /**
      * Like {@link #dimAbove} but places the dim below the given container.
      *
-     * @param t         A transaction in which to apply the Dim.
-     * @param container The container which to dim below. Should be a child of our host.
-     * @param alpha     The alpha at which to Dim.
+     * @param t          A transaction in which to apply the Dim.
+     * @param container  The container which to dim below. Should be a child of our host.
+     * @param alpha      The alpha at which to Dim.
+     * @param blurRadius The amount of blur added to the Dim.
      */
 
-    void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
-        dim(t, container, -1, alpha);
+    void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha,
+                  int blurRadius) {
+        dim(t, container, -1, alpha, blurRadius);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index c475da3..53f7009 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -134,7 +134,7 @@
 
     @Override
     public DisplayAreaAppearedInfo createTaskDisplayArea(IDisplayAreaOrganizer organizer,
-            int displayId, int rootFeatureId, String name) {
+            int displayId, int parentFeatureId, String name) {
         enforceTaskPermission("createTaskDisplayArea()");
         final long uid = Binder.getCallingUid();
         final long origId = Binder.clearCallingIdentity();
@@ -149,13 +149,26 @@
                             + displayId);
                 }
 
-                final DisplayArea root = display.getItemFromDisplayAreas(da ->
-                        da.asRootDisplayArea() != null && da.mFeatureId == rootFeatureId
-                                ? da
+                // The parentFeatureId can be either a RootDisplayArea or a TaskDisplayArea.
+                // Check if there is a RootDisplayArea with the given parentFeatureId.
+                final RootDisplayArea parentRoot = display.getItemFromDisplayAreas(da ->
+                        da.asRootDisplayArea() != null && da.mFeatureId == parentFeatureId
+                                ? da.asRootDisplayArea()
                                 : null);
-                if (root == null) {
-                    throw new IllegalArgumentException("Can't find RootDisplayArea with featureId="
-                            + rootFeatureId);
+                final TaskDisplayArea parentTda;
+                if (parentRoot == null) {
+                    // There is no RootDisplayArea matching the parentFeatureId.
+                    // Check if there is a TaskDisplayArea with the given parentFeatureId.
+                    parentTda = display.getItemFromTaskDisplayAreas(taskDisplayArea ->
+                            taskDisplayArea.mFeatureId == parentFeatureId
+                                    ? taskDisplayArea
+                                    : null);
+                } else {
+                    parentTda = null;
+                }
+                if (parentRoot == null && parentTda == null) {
+                    throw new IllegalArgumentException(
+                            "Can't find a parent DisplayArea with featureId=" + parentFeatureId);
                 }
 
                 final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++;
@@ -166,10 +179,13 @@
                     // Oh well...
                 }
 
-                final TaskDisplayArea tda = createTaskDisplayArea(root.asRootDisplayArea(), name,
-                        taskDisplayAreaFeatureId);
-                return organizeDisplayArea(organizer, tda,
+                final TaskDisplayArea tda = parentRoot != null
+                        ? createTaskDisplayArea(parentRoot, name, taskDisplayAreaFeatureId)
+                        : createTaskDisplayArea(parentTda, name, taskDisplayAreaFeatureId);
+                final DisplayAreaAppearedInfo tdaInfo = organizeDisplayArea(organizer, tda,
                         "DisplayAreaOrganizerController.createTaskDisplayArea");
+                mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, organizer);
+                return tdaInfo;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -196,6 +212,7 @@
                                     + "TaskDisplayArea=" + taskDisplayArea);
                 }
 
+                mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId);
                 deleteTaskDisplayArea(taskDisplayArea);
             }
         } finally {
@@ -253,6 +270,9 @@
                 new SurfaceControl(displayArea.getSurfaceControl(), callsite));
     }
 
+    /**
+     * Creates a {@link TaskDisplayArea} as the topmost TDA below the given {@link RootDisplayArea}.
+     */
     private TaskDisplayArea createTaskDisplayArea(RootDisplayArea root, String name,
             int taskDisplayAreaFeatureId) {
         final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(root.mDisplayContent,
@@ -283,6 +303,21 @@
         return taskDisplayArea;
     }
 
+    /**
+     * Creates a {@link TaskDisplayArea} as the topmost child of the given {@link TaskDisplayArea}.
+     */
+    private TaskDisplayArea createTaskDisplayArea(TaskDisplayArea parentTda, String name,
+            int taskDisplayAreaFeatureId) {
+        final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(parentTda.mDisplayContent,
+                parentTda.mWmService, name, taskDisplayAreaFeatureId,
+                true /* createdByOrganizer */);
+
+        // Insert the TaskDisplayArea on the top.
+        parentTda.addChild(taskDisplayArea, WindowContainer.POSITION_TOP);
+
+        return taskDisplayArea;
+    }
+
     private void deleteTaskDisplayArea(TaskDisplayArea taskDisplayArea) {
         taskDisplayArea.setOrganizer(null);
         mService.mRootWindowContainer.mTaskSupervisor.beginDeferResume();
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index c8fadf6..f505daa 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -365,7 +365,7 @@
          */
         private void build(@Nullable List<HierarchyBuilder> displayAreaGroupHierarchyBuilders) {
             final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
-            final int maxWindowLayerCount = policy.getMaxWindowLayer();
+            final int maxWindowLayerCount = policy.getMaxWindowLayer() + 1;
             final DisplayArea.Tokens[] displayAreaForLayer =
                     new DisplayArea.Tokens[maxWindowLayerCount];
             final Map<Feature, List<DisplayArea<WindowContainer>>> featureAreas =
@@ -560,6 +560,7 @@
             private final int mId;
             private final boolean[] mLayers;
             private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new;
+            private boolean mExcludeRoundedCorner = true;
 
             /**
              * Builds a new feature that applies to a set of window types as specified by the
@@ -578,7 +579,7 @@
                 mPolicy = policy;
                 mName = name;
                 mId = id;
-                mLayers = new boolean[mPolicy.getMaxWindowLayer()];
+                mLayers = new boolean[mPolicy.getMaxWindowLayer() + 1];
             }
 
             /**
@@ -633,7 +634,18 @@
                 return this;
             }
 
+            // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded
+            // corner overlay.
+            Builder setExcludeRoundedCornerOverlay(boolean excludeRoundedCorner) {
+                mExcludeRoundedCorner = excludeRoundedCorner;
+                return this;
+            }
+
             Feature build() {
+                if (mExcludeRoundedCorner) {
+                    // Always put the rounded corner layer to the top most layer.
+                    mLayers[mPolicy.getMaxWindowLayer()] = false;
+                }
                 return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier);
             }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e88f8e3..8457933 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -80,6 +80,7 @@
 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
 
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -552,24 +553,56 @@
      * This just indicates the window the input method is on top of, not
      * necessarily the window its input is going to.
      */
-    WindowState mInputMethodTarget;
+    private WindowState mImeLayeringTarget;
 
     /**
      * The window which receives input from the input method. This is also a candidate of the
      * input method control target.
      */
-    WindowState mInputMethodInputTarget;
+    private WindowState mImeInputTarget;
 
     /**
      * This controls the visibility and animation of the input method window.
      */
-    InsetsControlTarget mInputMethodControlTarget;
+    private InsetsControlTarget mImeControlTarget;
+
+    /**
+     * Used by {@link #getImeTarget} to return the IME target which the input method window on
+     * top of for adjusting input method window surface layer Z-Ordering.
+     *
+     * @see #mImeLayeringTarget
+     */
+    static final int IME_TARGET_LAYERING = 0;
+
+    /**
+     * Used by {@link #getImeTarget} to return the IME target which received the input connection
+     * from IME.
+     *
+     * @see #mImeInputTarget
+     */
+    static final int IME_TARGET_INPUT = 1;
+
+    /**
+     * Used by {@link #getImeTarget} to return the IME target which controls the IME insets
+     * visibility and animation.
+     *
+     * @see #mImeControlTarget
+     */
+    static final int IME_TARGET_CONTROL = 2;
+
+    @IntDef(flag = false, prefix = { "IME_TARGET_" }, value = {
+            IME_TARGET_LAYERING,
+            IME_TARGET_INPUT,
+            IME_TARGET_CONTROL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface InputMethodTarget {}
 
     /** The surface parent of the IME container. */
     private SurfaceControl mInputMethodSurfaceParent;
 
-    /** If true hold off on modifying the animation layer of mInputMethodTarget */
-    boolean mInputMethodTargetWaitingAnim;
+    /** If {@code true} hold off on modifying the animation layer of {@link #mImeLayeringTarget} */
+    boolean mImeLayeringTargetWaitingAnim;
 
     private final PointerEventDispatcher mPointerEventDispatcher;
 
@@ -814,7 +847,7 @@
 
     private final Consumer<WindowState> mApplyPostLayoutPolicy =
             w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
-                    mInputMethodTarget);
+                    mImeLayeringTarget);
 
     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
@@ -2256,19 +2289,20 @@
 
     @Nullable
     Task getRootTask(int rootTaskId) {
-        return getItemFromTaskDisplayAreas(taskDisplayArea ->
-                        taskDisplayArea.getRootTask(rootTaskId));
+        return getRootTask(rootTask -> rootTask.getRootTaskId() == rootTaskId);
     }
 
-    protected int getRootTaskCount() {
-        return reduceOnAllTaskDisplayAreas((taskDisplayArea, count) ->
-                count + taskDisplayArea.getRootTaskCount(), 0 /* initValue */);
+    int getRootTaskCount() {
+        final int[] count = new int[1];
+        forAllRootTasks(task -> {
+            count[0]++;
+        });
+        return count[0];
     }
 
-    @VisibleForTesting
     @Nullable
     Task getTopRootTask() {
-        return getItemFromTaskDisplayAreas(TaskDisplayArea::getTopRootTask);
+        return getRootTask(t -> true);
     }
 
     /**
@@ -2298,10 +2332,6 @@
                             .setSubtype(getConfiguration().orientation)
                             .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
         }
-
-        if (mPinnedStackControllerLocked != null) {
-            mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
-        }
     }
 
     /**
@@ -2835,7 +2865,7 @@
     }
 
     void prepareFreezingTaskBounds() {
-        forAllTaskDisplayAreas(TaskDisplayArea::prepareFreezingTaskBounds);
+        forAllRootTasks(Task::prepareFreezingTaskBounds);
     }
 
     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
@@ -2944,15 +2974,15 @@
             proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID);
         }
         proto.write(DISPLAY_READY, isReady());
-        if (mInputMethodTarget != null) {
-            mInputMethodTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel);
+        if (mImeLayeringTarget != null) {
+            mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel);
         }
-        if (mInputMethodInputTarget != null) {
-            mInputMethodInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel);
+        if (mImeInputTarget != null) {
+            mImeInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel);
         }
-        if (mInputMethodControlTarget != null
-                && mInputMethodControlTarget.getWindow() != null) {
-            mInputMethodControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET,
+        if (mImeControlTarget != null
+                && mImeControlTarget.getWindow() != null) {
+            mImeControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET,
                     logLevel);
         }
         if (mCurrentFocus != null) {
@@ -3208,7 +3238,7 @@
         boolean imWindowChanged = false;
         final WindowState imWindow = mInputMethodWindow;
         if (imWindow != null) {
-            final WindowState prevTarget = mInputMethodTarget;
+            final WindowState prevTarget = mImeLayeringTarget;
             final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
             imWindowChanged = prevTarget != newTarget;
 
@@ -3405,6 +3435,7 @@
     boolean destroyLeakedSurfaces() {
         // Used to indicate that a surface was leaked.
         mTmpWindow = null;
+        final Transaction t = mWmService.mTransactionFactory.get();
         forAllWindows(w -> {
             final WindowStateAnimator wsa = w.mWinAnimator;
             if (wsa.mSurfaceController == null) {
@@ -3416,7 +3447,7 @@
                         + " token=" + w.mToken
                         + " pid=" + w.mSession.mPid
                         + " uid=" + w.mSession.mUid);
-                wsa.destroySurface();
+                wsa.destroySurface(t);
                 mWmService.mForceRemoves.add(w);
                 mTmpWindow = w;
             } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) {
@@ -3424,10 +3455,11 @@
                         + w + " surface=" + wsa.mSurfaceController
                         + " token=" + w.mActivityRecord);
                 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w);
-                wsa.destroySurface();
+                wsa.destroySurface(t);
                 mTmpWindow = w;
             }
         }, false /* traverseTopToBottom */);
+        t.apply();
 
         return mTmpWindow != null;
     }
@@ -3460,7 +3492,7 @@
     }
 
     /**
-     * Determine and return the window that should be the IME target.
+     * Determine and return the window that should be the IME target for layering the IME window.
      * @param updateImeTarget If true the system IME target will be updated to match what we found.
      * @return The window that should be used as the IME target or null if there isn't any.
      */
@@ -3469,13 +3501,13 @@
             // There isn't an IME so there shouldn't be a target...That was easy!
             if (updateImeTarget) {
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
-                        + mInputMethodTarget + " to null since mInputMethodWindow is null");
-                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
+                        + mImeLayeringTarget + " to null since mInputMethodWindow is null");
+                setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim);
             }
             return null;
         }
 
-        final WindowState curTarget = mInputMethodTarget;
+        final WindowState curTarget = mImeLayeringTarget;
         if (!canUpdateImeTarget()) {
             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
             return curTarget;
@@ -3530,7 +3562,7 @@
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
                         + Debug.getCallers(4) : ""));
-                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
+                setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim);
             }
 
             return null;
@@ -3557,7 +3589,7 @@
                     if (mAppTransition.isTransitionSet()) {
                         // If we are currently setting up for an animation, hold everything until we
                         // can find out what will happen.
-                        setInputMethodTarget(highestTarget, true);
+                        setImeLayeringTarget(highestTarget, true);
                         return highestTarget;
                     }
                 }
@@ -3565,7 +3597,7 @@
 
             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
                     + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
-            setInputMethodTarget(target, false);
+            setImeLayeringTarget(target, false);
         }
 
         return target;
@@ -3576,24 +3608,24 @@
      * the candidate app window token if needed.
      */
     void computeImeTargetIfNeeded(ActivityRecord candidate) {
-        if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord == candidate) {
+        if (mImeLayeringTarget != null && mImeLayeringTarget.mActivityRecord == candidate) {
             computeImeTarget(true /* updateImeTarget */);
         }
     }
 
     private boolean isImeControlledByApp() {
-        return mInputMethodInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
-                        mInputMethodInputTarget.getWindowingMode());
+        return mImeInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
+                        mImeInputTarget.getWindowingMode());
     }
 
     boolean isImeAttachedToApp() {
         return isImeControlledByApp()
-                && mInputMethodTarget != null
-                && mInputMethodTarget.mActivityRecord != null
-                && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                && mImeLayeringTarget != null
+                && mImeLayeringTarget.mActivityRecord != null
+                && mImeLayeringTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                 // An activity with override bounds should be letterboxed inside its parent bounds,
                 // so it doesn't fill the screen.
-                && mInputMethodTarget.mActivityRecord.matchParentBounds();
+                && mImeLayeringTarget.mActivityRecord.matchParentBounds();
     }
 
     /**
@@ -3620,6 +3652,24 @@
         return statusBar != null ? statusBar : defaultDc.mRemoteInsetsControlTarget;
     }
 
+    /**
+     * Returns the corresponding IME insets control target according the IME target type.
+     *
+     * @param type The type of the IME target.
+     * @see #IME_TARGET_LAYERING
+     * @see #IME_TARGET_INPUT
+     * @see #IME_TARGET_CONTROL
+     */
+    InsetsControlTarget getImeTarget(@InputMethodTarget int type) {
+        switch (type) {
+            case IME_TARGET_LAYERING: return mImeLayeringTarget;
+            case IME_TARGET_INPUT: return mImeInputTarget;
+            case IME_TARGET_CONTROL: return mImeControlTarget;
+            default:
+                return null;
+        }
+    }
+
     @DisplayImePolicy int getImePolicy() {
         if (!isTrusted()) {
             return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
@@ -3637,6 +3687,11 @@
         return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate();
     }
 
+    @VisibleForTesting
+    void setImeLayeringTarget(WindowState target) {
+        mImeLayeringTarget = target;
+    }
+
     /**
      * Sets the window the IME is on top of.
      * @param target window to place the IME surface on top of. If {@code null}, the IME will be
@@ -3644,13 +3699,13 @@
      * @param targetWaitingAnim if {@code true}, hold off on modifying the animation layer of
      *                          the target.
      */
-    private void setInputMethodTarget(@Nullable WindowState target, boolean targetWaitingAnim) {
-        if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
+    private void setImeLayeringTarget(@Nullable WindowState target, boolean targetWaitingAnim) {
+        if (target == mImeLayeringTarget && mImeLayeringTargetWaitingAnim == targetWaitingAnim) {
             return;
         }
         ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target);
-        mInputMethodTarget = target;
-        mInputMethodTargetWaitingAnim = targetWaitingAnim;
+        mImeLayeringTarget = target;
+        mImeLayeringTargetWaitingAnim = targetWaitingAnim;
 
         // 1. Reparent the IME container window to the target root DA to get the correct bounds and
         // config. (Only happens when the target window is in a different root DA)
@@ -3672,23 +3727,33 @@
         updateImeControlTarget();
     }
 
+    @VisibleForTesting
+    void setImeInputTarget(WindowState target) {
+        mImeInputTarget = target;
+    }
+
+    @VisibleForTesting
+    void setImeControlTarget(InsetsControlTarget target) {
+        mImeControlTarget = target;
+    }
+
     /**
      * The IME input target is the window which receives input from IME. It is also a candidate
      * which controls the visibility and animation of the input method window.
      */
-    void setInputMethodInputTarget(WindowState target) {
-        if (mInputMethodInputTarget != target) {
+    void updateImeInputAndControlTarget(WindowState target) {
+        if (mImeInputTarget != target) {
             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
-            mInputMethodInputTarget = target;
+            mImeInputTarget = target;
             updateImeControlTarget();
         }
     }
 
     void updateImeControlTarget() {
-        mInputMethodControlTarget = computeImeControlTarget();
-        mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
+        mImeControlTarget = computeImeControlTarget();
+        mInsetsStateController.onImeControlTargetChanged(mImeControlTarget);
 
-        final WindowState win = InsetsControlTarget.asWindowOrNull(mInputMethodControlTarget);
+        final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget);
         final IBinder token = win != null ? win.mClient.asBinder() : null;
         // Note: not allowed to call into IMMS with the WM lock held, hence the post.
         mWmService.mH.post(() ->
@@ -3711,12 +3776,12 @@
     @VisibleForTesting
     InsetsControlTarget computeImeControlTarget() {
         if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null
-                || (mInputMethodInputTarget != null
-                        && getImeHostOrFallback(mInputMethodInputTarget.getWindow())
+                || (mImeInputTarget != null
+                        && getImeHostOrFallback(mImeInputTarget.getWindow())
                                 == mRemoteInsetsControlTarget)) {
             return mRemoteInsetsControlTarget;
         } else {
-            return mInputMethodInputTarget;
+            return mImeInputTarget;
         }
     }
 
@@ -3733,7 +3798,7 @@
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
         if (allowAttachToApp && isImeAttachedToApp()) {
-            return mInputMethodTarget.mActivityRecord.getSurfaceControl();
+            return mImeLayeringTarget.mActivityRecord.getSurfaceControl();
         }
 
         // Otherwise, we just attach it to where the display area policy put it.
@@ -4190,8 +4255,11 @@
         }
 
         // Initialize state of exiting applications.
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            taskDisplayArea.setExitingTokensHasVisible(hasVisible);
+        forAllRootTasks(task -> {
+            final ArrayList<ActivityRecord> activities = task.mExitingActivities;
+            for (int j = activities.size() - 1; j >= 0; --j) {
+                activities.get(j).hasVisible = hasVisible;
+            }
         });
     }
 
@@ -4204,7 +4272,22 @@
         }
 
         // Time to remove any exiting applications?
-        forAllTaskDisplayAreas(TaskDisplayArea::removeExistingAppTokensIfPossible);
+        forAllRootTasks(task -> {
+            final ArrayList<ActivityRecord> activities = task.mExitingActivities;
+            for (int j = activities.size() - 1; j >= 0; --j) {
+                final ActivityRecord activity = activities.get(j);
+                if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
+                        && (!activity.mIsExiting || activity.isEmpty())) {
+                    // Make sure there is no animation running on this activity, so any windows
+                    // associated with it will be removed as soon as their animations are
+                    // complete.
+                    cancelAnimation();
+                    ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                            "performLayout: Activity exiting now removed %s", activity);
+                    activity.removeIfPossible();
+                }
+            }
+        });
     }
 
     @Override
@@ -4354,7 +4437,7 @@
         private boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
             // We skip IME windows so they're processed just above their target, except
             // in split-screen mode where we process the IME containers above the docked divider.
-            return dc.mInputMethodTarget != null
+            return dc.getImeTarget(IME_TARGET_LAYERING) != null
                     && !dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
         }
 
@@ -4469,7 +4552,7 @@
     @Override
     void assignChildLayers(SurfaceControl.Transaction t) {
         mImeWindowsContainers.setNeedsLayer();
-        final WindowState imeTarget = mInputMethodTarget;
+        final WindowState imeTarget = mImeLayeringTarget;
         // In the case where we have an IME target that is not in split-screen mode IME
         // assignment is easy. We just need the IME to go directly above the target. This way
         // children of the target will naturally go above the IME and everyone is happy.
@@ -5127,15 +5210,56 @@
      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
      */
     void removeRootTasksInWindowingModes(int... windowingModes) {
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            taskDisplayArea.removeRootTasksInWindowingModes(windowingModes);
+        if (windowingModes == null || windowingModes.length == 0) {
+            return;
+        }
+
+        // Collect the root tasks that are necessary to be removed instead of performing the removal
+        // by looping the children, so that we don't miss any root tasks after the children size
+        // changed or reordered.
+        final ArrayList<Task> rootTasks = new ArrayList<>();
+        forAllRootTasks(rootTask -> {
+            for (int windowingMode : windowingModes) {
+                if (rootTask.mCreatedByOrganizer
+                        || rootTask.getWindowingMode() != windowingMode
+                        || !rootTask.isActivityTypeStandardOrUndefined()) {
+                    continue;
+                }
+                rootTasks.add(rootTask);
+            }
         });
+        for (int i = rootTasks.size() - 1; i >= 0; --i) {
+            mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
+        }
     }
 
     void removeRootTasksWithActivityTypes(int... activityTypes) {
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            taskDisplayArea.removeRootTasksWithActivityTypes(activityTypes);
+        if (activityTypes == null || activityTypes.length == 0) {
+            return;
+        }
+
+        // Collect the root tasks that are necessary to be removed instead of performing the removal
+        // by looping the children, so that we don't miss any root tasks after the children size
+        // changed or reordered.
+        final ArrayList<Task> rootTasks = new ArrayList<>();
+        forAllRootTasks(rootTask -> {
+            for (int activityType : activityTypes) {
+                // Collect the root tasks that are currently being organized.
+                if (rootTask.mCreatedByOrganizer) {
+                    for (int k = rootTask.getChildCount() - 1; k >= 0; --k) {
+                        final Task task = (Task) rootTask.getChildAt(k);
+                        if (task.getActivityType() == activityType) {
+                            rootTasks.add(task);
+                        }
+                    }
+                } else if (rootTask.getActivityType() == activityType) {
+                    rootTasks.add(rootTask);
+                }
+            }
         });
+        for (int i = rootTasks.size() - 1; i >= 0; --i) {
+            mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
+        }
     }
 
     ActivityRecord topRunningActivity() {
@@ -5354,20 +5478,13 @@
             return;
         }
 
-        // Check if all task display areas have only the empty home stacks left.
-        boolean hasNonEmptyHomeStack = forAllTaskDisplayAreas(taskDisplayArea -> {
-            if (taskDisplayArea.getRootTaskCount() != 1) {
-                return true;
-            }
-            final Task stack = taskDisplayArea.getRootTaskAt(0);
-            return !stack.isActivityTypeHome() || stack.hasChild();
-        });
-        if (!hasNonEmptyHomeStack) {
-            // Release this display if only empty home stack(s) are left. This display will be
-            // released along with the stack(s) removal.
-            forAllTaskDisplayAreas(taskDisplayArea -> {
-                taskDisplayArea.getRootTaskAt(0).removeIfPossible();
-            });
+        // Check if all task display areas have only the empty home root tasks left.
+        boolean hasNonEmptyHomeRootTask = forAllRootTasks(rootTask ->
+                !rootTask.isActivityTypeHome() || rootTask.hasChild());
+        if (!hasNonEmptyHomeRootTask && getRootTaskCount() > 0) {
+            // Release this display if only empty home root task(s) are left. This display will be
+            // released along with the root task(s) removal.
+            forAllRootTasks(Task::removeIfPossible);
         } else if (getTopRootTask() == null) {
             removeIfPossible();
             mRootWindowContainer.mTaskSupervisor
@@ -5407,12 +5524,14 @@
             return;
         }
         mInEnsureActivitiesVisible = true;
+        mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
         try {
-            forAllTaskDisplayAreas(taskDisplayArea -> {
-                taskDisplayArea.ensureActivitiesVisible(starting, configChanges,
-                        preserveWindows, notifyClients, userLeaving);
+            forAllRootTasks(rootTask -> {
+                rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+                        notifyClients, userLeaving);
             });
         } finally {
+            mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
             mInEnsureActivitiesVisible = false;
         }
     }
@@ -5546,7 +5665,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/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 91106ef..17c3b20 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -19,10 +19,14 @@
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
+import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.ImeInsetsSourceProviderProto.IME_TARGET_FROM_IME;
 import static com.android.server.wm.ImeInsetsSourceProviderProto.INSETS_SOURCE_PROVIDER;
 import static com.android.server.wm.ImeInsetsSourceProviderProto.IS_IME_LAYOUT_DRAWN;
 
+import android.annotation.NonNull;
 import android.os.Trace;
 import android.util.proto.ProtoOutputStream;
 import android.view.InsetsSource;
@@ -37,9 +41,9 @@
  * Controller for IME inset source on the server. It's called provider as it provides the
  * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
  */
-class ImeInsetsSourceProvider extends InsetsSourceProvider {
+final class ImeInsetsSourceProvider extends InsetsSourceProvider {
 
-    private InsetsControlTarget mImeTargetFromIme;
+    private InsetsControlTarget mImeRequester;
     private Runnable mShowImeRunner;
     private boolean mIsImeLayoutDrawn;
     private boolean mImeShowing;
@@ -56,12 +60,8 @@
      * @param imeTarget imeTarget on which IME request is coming from.
      */
     void scheduleShowImePostLayout(InsetsControlTarget imeTarget) {
-        boolean targetChanged = mImeTargetFromIme != imeTarget
-                && mImeTargetFromIme != null && imeTarget != null && mShowImeRunner != null
-                && imeTarget.getWindow() != null && mImeTargetFromIme.getWindow() != null
-                && mImeTargetFromIme.getWindow().mActivityRecord
-                        == imeTarget.getWindow().mActivityRecord;
-        mImeTargetFromIme = imeTarget;
+        boolean targetChanged = isTargetChangedWithinActivity(imeTarget);
+        mImeRequester = imeTarget;
         if (targetChanged) {
             // target changed, check if new target can show IME.
             ProtoLog.d(WM_DEBUG_IME, "IME target changed within ActivityRecord");
@@ -72,24 +72,24 @@
             return;
         }
 
-        ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeTargetFromIme.getWindow() == null
-                ? mImeTargetFromIme : mImeTargetFromIme.getWindow().getName());
+        ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeRequester.getWindow() == null
+                ? mImeRequester : mImeRequester.getWindow().getName());
         mShowImeRunner = () -> {
             ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner");
             // Target should still be the same.
-            if (isImeTargetFromDisplayContentAndImeSame()) {
-                final InsetsControlTarget target = mDisplayContent.mInputMethodControlTarget;
+            if (isReadyToShowIme()) {
+                final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
 
                 ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s",
                         target.getWindow() != null ? target.getWindow().getName() : "");
                 setImeShowing(true);
                 target.showInsets(WindowInsets.Type.ime(), true /* fromIme */);
                 Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0);
-                if (target != mImeTargetFromIme && mImeTargetFromIme != null) {
+                if (target != mImeRequester && mImeRequester != null) {
                     ProtoLog.w(WM_DEBUG_IME,
                             "showInsets(ime) was requested by different window: %s ",
-                            (mImeTargetFromIme.getWindow() != null
-                                    ? mImeTargetFromIme.getWindow().getName() : ""));
+                            (mImeRequester.getWindow() != null
+                                    ? mImeRequester.getWindow().getName() : ""));
                 }
             }
             abortShowImePostLayout();
@@ -100,8 +100,7 @@
     void checkShowImePostLayout() {
         // check if IME is drawn
         if (mIsImeLayoutDrawn
-                || (mImeTargetFromIme != null
-                && isImeTargetFromDisplayContentAndImeSame()
+                || (isReadyToShowIme()
                 && mWin != null
                 && mWin.isDrawn()
                 && !mWin.mGivenInsetsPending)) {
@@ -118,13 +117,13 @@
      */
     void abortShowImePostLayout() {
         ProtoLog.d(WM_DEBUG_IME, "abortShowImePostLayout");
-        mImeTargetFromIme = null;
+        mImeRequester = null;
         mIsImeLayoutDrawn = false;
         mShowImeRunner = null;
     }
 
     @VisibleForTesting
-    boolean isImeTargetFromDisplayContentAndImeSame() {
+    boolean isReadyToShowIme() {
         // IMMS#mLastImeTargetWindow always considers focused window as
         // IME target, however DisplayContent#computeImeTarget() can compute
         // a different IME target.
@@ -134,35 +133,75 @@
         // Also, if imeTarget is closing, it would be considered as outdated target.
         // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
         //  actual IME target.
-        final WindowState dcTarget = mDisplayContent.mInputMethodTarget;
-        final InsetsControlTarget controlTarget = mDisplayContent.mInputMethodControlTarget;
-        if (dcTarget == null || mImeTargetFromIme == null) {
+        final InsetsControlTarget dcTarget = mDisplayContent.getImeTarget(IME_TARGET_LAYERING);
+        if (dcTarget == null || mImeRequester == null) {
             return false;
         }
-        ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeTargetFromIme: %s",
-                dcTarget.getName(), mImeTargetFromIme.getWindow() == null
-                        ? mImeTargetFromIme : mImeTargetFromIme.getWindow().getName());
+        ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeRequester: %s",
+                dcTarget.getWindow().getName(), mImeRequester.getWindow() == null
+                        ? mImeRequester : mImeRequester.getWindow().getName());
 
-        return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget)
-                || (mImeTargetFromIme != null && mImeTargetFromIme.getWindow() != null
-                        && dcTarget.getParentWindow() == mImeTargetFromIme
-                        && dcTarget.mSubLayer > mImeTargetFromIme.getWindow().mSubLayer)
-                || mImeTargetFromIme == mDisplayContent.getImeFallback()
-                || mImeTargetFromIme == mDisplayContent.mInputMethodInputTarget
-                || controlTarget == mImeTargetFromIme
-                        && (mImeTargetFromIme.getWindow() == null
-                                || !mImeTargetFromIme.getWindow().isClosing());
+        return isImeLayeringTarget(mImeRequester, dcTarget)
+                || isAboveImeLayeringTarget(mImeRequester, dcTarget)
+                || isImeFallbackTarget(mImeRequester)
+                || isImeInputTarget(mImeRequester)
+                || sameAsImeControlTarget();
     }
 
+    // ---------------------------------------------------------------------------------------
+    // Methods for checking IME insets target changing state.
+    //
+    private static boolean isImeLayeringTarget(@NonNull InsetsControlTarget target,
+            @NonNull InsetsControlTarget dcTarget) {
+        return !dcTarget.getWindow().isClosing() && target == dcTarget;
+    }
+
+    private static boolean isAboveImeLayeringTarget(@NonNull InsetsControlTarget target,
+            @NonNull InsetsControlTarget dcTarget) {
+        return target.getWindow() != null
+                && dcTarget.getWindow().getParentWindow() == target
+                && dcTarget.getWindow().mSubLayer > target.getWindow().mSubLayer;
+    }
+
+    private boolean isImeFallbackTarget(InsetsControlTarget target) {
+        return target == mDisplayContent.getImeFallback();
+    }
+
+    private boolean isImeInputTarget(InsetsControlTarget target) {
+        return target == mDisplayContent.getImeTarget(IME_TARGET_INPUT);
+    }
+
+    private boolean sameAsImeControlTarget() {
+        final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
+        return target == mImeRequester
+                && (mImeRequester.getWindow() == null
+                || !mImeRequester.getWindow().isClosing());
+    }
+
+    private boolean isTargetChangedWithinActivity(InsetsControlTarget target) {
+        // We don't consider the target out of the activity.
+        if (target == null || target.getWindow() == null) {
+            return false;
+        }
+        return mImeRequester != target
+                && mImeRequester != null && mShowImeRunner != null
+                && mImeRequester.getWindow() != null
+                && mImeRequester.getWindow().mActivityRecord
+                == target.getWindow().mActivityRecord;
+    }
+    // ---------------------------------------------------------------------------------------
+
     @Override
     public void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
         pw.print(prefix);
         pw.print("mImeShowing=");
         pw.print(mImeShowing);
-        if (mImeTargetFromIme != null) {
-            pw.print(" showImePostLayout pending for mImeTargetFromIme=");
-            pw.print(mImeTargetFromIme);
+        if (mImeRequester != null) {
+            pw.print(prefix);
+            pw.print("showImePostLayout pending for mImeRequester=");
+            pw.print(mImeRequester);
+            pw.println();
         }
         pw.println();
     }
@@ -171,8 +210,8 @@
     void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) {
         final long token = proto.start(fieldId);
         super.dumpDebug(proto, INSETS_SOURCE_PROVIDER, logLevel);
-        if (mImeTargetFromIme != null) {
-            mImeTargetFromIme.getWindow().dumpDebug(proto, IME_TARGET_FROM_IME, logLevel);
+        if (mImeRequester != null) {
+            mImeRequester.getWindow().dumpDebug(proto, IME_TARGET_FROM_IME, logLevel);
         }
         proto.write(IS_IME_LAYOUT_DRAWN, mIsImeLayoutDrawn);
         proto.end(token);
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 35f5615..6e89581 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -26,9 +26,7 @@
 import android.annotation.NonNull;
 import android.os.Debug;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.util.Slog;
-import android.view.IWindow;
 import android.view.InputApplicationHandle;
 import android.view.KeyEvent;
 import android.view.WindowManager;
@@ -37,7 +35,6 @@
 import com.android.server.input.InputManagerService;
 
 import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicReference;
 
 final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM;
@@ -60,13 +57,6 @@
     // which point the ActivityManager will enable dispatching.
     private boolean mInputDispatchEnabled;
 
-    // TODO(b/141749603)) investigate if this can be part of client focus change dispatch
-    // Tracks the currently focused window used to update pointer capture state in clients
-    private AtomicReference<IWindow> mFocusedWindow = new AtomicReference<>();
-
-    // Tracks focused window pointer capture state
-    private boolean mFocusedWindowHasCapture;
-
     public InputManagerCallback(WindowManagerService service) {
         mService = service;
     }
@@ -234,59 +224,9 @@
     }
 
     @Override
-    public boolean notifyFocusChanged(IBinder oldToken, IBinder newToken) {
-        boolean requestRefreshConfiguration = false;
-        final IWindow newFocusedWindow;
-        final WindowState win;
-
-        // TODO(b/141749603) investigate if this can be part of client focus change dispatch
-        synchronized (mService.mGlobalLock) {
-            win = mService.mInputToWindowMap.get(newToken);
-        }
-        newFocusedWindow = (win != null) ? win.mClient : null;
-
-        final IWindow focusedWindow = mFocusedWindow.get();
-        if (focusedWindow != null) {
-            if (newFocusedWindow != null
-                    && newFocusedWindow.asBinder() == focusedWindow.asBinder()) {
-                Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow="
-                        + focusedWindow);
-                return false;
-            }
-            requestRefreshConfiguration = dispatchPointerCaptureChanged(focusedWindow, false);
-        }
-        mFocusedWindow.set(newFocusedWindow);
-        mService.mH.sendMessage(PooledLambda.obtainMessage(mService::reportFocusChanged,
-                oldToken, newToken));
-        return requestRefreshConfiguration;
-    }
-
-    @Override
-    public boolean requestPointerCapture(IBinder windowToken, boolean enabled) {
-        final IWindow focusedWindow = mFocusedWindow.get();
-        if (focusedWindow == null || focusedWindow.asBinder() != windowToken) {
-            Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
-                    + windowToken);
-            return false;
-        }
-        if (mFocusedWindowHasCapture == enabled) {
-            Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
-            return false;
-        }
-        return dispatchPointerCaptureChanged(focusedWindow, enabled);
-    }
-
-    private boolean dispatchPointerCaptureChanged(IWindow focusedWindow, boolean enabled) {
-        if (mFocusedWindowHasCapture != enabled) {
-            mFocusedWindowHasCapture = enabled;
-            try {
-                focusedWindow.dispatchPointerCaptureChanged(enabled);
-            } catch (RemoteException ex) {
-                /* ignore */
-            }
-            return true;
-        }
-        return false;
+    public void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
+        mService.mH.sendMessage(PooledLambda.obtainMessage(
+                mService::reportFocusChanged, oldToken, newToken));
     }
 
     /** Waits until the built-in input devices have been configured. */
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index e45310a..57f2638 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -594,16 +594,8 @@
          */
         @Nullable
         private Task getRootTaskForControllingOccluding(DisplayContent display) {
-            return display.getItemFromTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task task = taskDisplayArea.getRootTaskAt(sNdx);
-                    if (task != null && task.isFocusableAndVisible()
-                            && !task.inPinnedWindowingMode()) {
-                        return task;
-                    }
-                }
-                return null;
-            });
+            return display.getRootTask(task ->
+                    task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode());
         }
 
         void dumpStatus(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 8745e95..35653f9 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -73,11 +73,12 @@
      * @param activity  The {@link ActivityRecord} currently being positioned.
      * @param source    The {@link ActivityRecord} from which activity was started from.
      * @param options   The {@link ActivityOptions} specified for the activity.
-     * @param result    The resulting params.
      * @param request   The optional request from the activity starter.
+     * @param phase     The {@link LaunchParamsModifier.Phase} that the resolution should finish.
+     * @param result    The resulting params.
      */
     void calculate(Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source,
-            ActivityOptions options, int phase, LaunchParams result, @Nullable Request request) {
+            ActivityOptions options, @Nullable Request request, int phase, LaunchParams result) {
         result.reset();
 
         if (task != null || activity != null) {
@@ -92,8 +93,8 @@
             mTmpResult.reset();
             final LaunchParamsModifier modifier = mModifiers.get(i);
 
-            switch(modifier.onCalculate(task, layout, activity, source, options, phase, mTmpCurrent,
-                    mTmpResult, request)) {
+            switch(modifier.onCalculate(task, layout, activity, source, options, request, phase,
+                    mTmpCurrent, mTmpResult)) {
                 case RESULT_SKIP:
                     // Do not apply any results when we are told to skip
                     continue;
@@ -130,8 +131,8 @@
 
     boolean layoutTask(Task task, WindowLayout layout, ActivityRecord activity,
             ActivityRecord source, ActivityOptions options) {
-        calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams,
-                null /* request */);
+        calculate(task, layout, activity, source, options, null /* request */, PHASE_BOUNDS,
+                mTmpParams);
 
         // No changes, return.
         if (mTmpParams.isEmpty()) {
@@ -308,17 +309,17 @@
          *                      launched should have this be non-null.
          * @param source        the Activity that launched a new task. Could be {@code null}.
          * @param options       {@link ActivityOptions} used to start the activity with.
+         * @param request       Optional data to give more context on the launch
          * @param phase         the calculation phase, see {@link Phase}
          * @param currentParams launching params after the process of last {@link
          *                      LaunchParamsModifier}.
          * @param outParams     the result params to be set.
-         * @param request       Optional data to give more context on the launch
          * @return see {@link LaunchParamsModifier.Result}
          */
         @Result
-        int onCalculate(@Nullable Task task, WindowLayout layout, ActivityRecord activity,
-                ActivityRecord source, ActivityOptions options, @Phase int phase,
-                LaunchParams currentParams, LaunchParams outParams,
-                @Nullable Request request);
+        int onCalculate(@Nullable Task task, @Nullable WindowLayout layout,
+                @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+                @Nullable ActivityOptions options, @Nullable Request request,
+                @Phase int phase, LaunchParams currentParams, LaunchParams outParams);
     }
 }
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index fd42b24..8fe2481 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -127,7 +127,6 @@
         try {
             listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
             mPinnedStackListener = listener;
-            notifyDisplayInfoChanged(mDisplayInfo);
             notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
             notifyMovementBoundsChanged(false /* fromImeAdjustment */);
             notifyActionsChanged(mActions);
@@ -171,23 +170,6 @@
         }
     }
 
-    private void setDisplayInfo(DisplayInfo displayInfo) {
-        mDisplayInfo.copyFrom(displayInfo);
-        notifyDisplayInfoChanged(mDisplayInfo);
-    }
-
-    /**
-     * In the case where the display rotation is changed but there is no stack, we can't depend on
-     * onTaskStackBoundsChanged() to be called.  But we still should update our known display info
-     * with the new state so that we can update SystemUI.
-     */
-    void onDisplayInfoChanged(DisplayInfo displayInfo) {
-        synchronized (mService.mGlobalLock) {
-            setDisplayInfo(displayInfo);
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
-        }
-    }
-
     /**
      * Sets the Ime state and height.
      */
@@ -288,18 +270,6 @@
         }
     }
 
-    /**
-     * Notifies listeners that the PIP animation is about to happen.
-     */
-    private void notifyDisplayInfoChanged(DisplayInfo displayInfo) {
-        if (mPinnedStackListener == null) return;
-        try {
-            mPinnedStackListener.onDisplayInfoChanged(displayInfo);
-        } catch (RemoteException e) {
-            Slog.e(TAG_WM, "Error delivering DisplayInfo changed event.", e);
-        }
-    }
-
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 067c772..5bcb287 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -413,9 +413,10 @@
 
     @Override
     public void onRootTaskOrderChanged(Task rootTask) {
-        ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", rootTask);
-        if (mDefaultTaskDisplayArea.getIndexOf(rootTask) == -1 || !rootTask.shouldBeVisible(null)) {
-            // The stack is not visible, so ignore this change
+        ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onRootTaskOrderChanged(): rootTask=%s", rootTask);
+        if (mDefaultTaskDisplayArea.getRootTask(t -> t == rootTask) == null
+                || !rootTask.shouldBeVisible(null)) {
+            // The root task is not visible, so ignore this change
             return;
         }
         final RecentsAnimationController controller =
@@ -468,14 +469,8 @@
      * @return The top stack that is not always-on-top.
      */
     private Task getTopNonAlwaysOnTopStack() {
-        for (int i = mDefaultTaskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) {
-            final Task s = mDefaultTaskDisplayArea.getRootTaskAt(i);
-            if (s.getWindowConfiguration().isAlwaysOnTop()) {
-                continue;
-            }
-            return s;
-        }
-        return null;
+        return mDefaultTaskDisplayArea.getRootTask(task ->
+                !task.getWindowConfiguration().isAlwaysOnTop());
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 16c7226..388577c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -33,7 +33,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.app.WindowConfiguration;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -57,7 +57,9 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.LatencyTracker;
 import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledFunction;
 import com.android.internal.util.function.pooled.PooledLambda;
@@ -84,6 +86,11 @@
 public class RecentsAnimationController implements DeathRecipient {
     private static final String TAG = RecentsAnimationController.class.getSimpleName();
     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.
+     */
+    private static final long LATENCY_TRACKER_LOG_DELAY_MS = 300;
 
     public static final int REORDER_KEEP_IN_PLACE = 0;
     public static final int REORDER_MOVE_TO_TOP = 1;
@@ -123,7 +130,7 @@
     private boolean mPendingStart = true;
 
     // Set when the animation has been canceled
-    private boolean mCanceled;
+    private volatile boolean mCanceled;
 
     // Whether or not the input consumer is enabled. The input consumer must be both registered and
     // enabled for it to start intercepting touch events.
@@ -364,6 +371,9 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void detachNavigationBarFromApp() {}
     };
 
     /**
@@ -592,6 +602,15 @@
         return adapter.createRemoteAnimationTarget();
     }
 
+    void logRecentsAnimationStartTime(int durationMs) {
+        BackgroundThread.getHandler().postDelayed(() -> {
+            if (!mCanceled) {
+                mService.mLatencyTracker.logAction(LatencyTracker.ACTION_START_RECENTS_ANIMATION,
+                        durationMs);
+            }
+        }, LATENCY_TRACKER_LOG_DELAY_MS);
+    }
+
     private boolean removeTaskInternal(int taskId) {
         boolean result = false;
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
@@ -763,7 +782,7 @@
                 taskAdapter.mTask.dontAnimateDimExit();
             }
             removeAnimation(taskAdapter);
-            taskAdapter.maybeApplyFinishBounds();
+            taskAdapter.onCleanup();
         }
 
         for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
@@ -987,14 +1006,19 @@
             return mTarget;
         }
 
-        void maybeApplyFinishBounds() {
+        void onCleanup() {
             if (!mFinishBounds.isEmpty()) {
+                // Apply any pending bounds changes
                 final SurfaceControl taskSurface = mTask.getSurfaceControl();
                 mTask.getPendingTransaction()
                         .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
                         .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height())
                         .apply();
                 mFinishBounds.setEmpty();
+            } else if (!mTask.isAttached()) {
+                // Apply the task's pending transaction in case it is detached and its transaction
+                // is not reachable.
+                mTask.getPendingTransaction().apply();
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java
index 393055e..505af05 100644
--- a/services/core/java/com/android/server/wm/RootDisplayArea.java
+++ b/services/core/java/com/android/server/wm/RootDisplayArea.java
@@ -115,15 +115,11 @@
     @Nullable
     DisplayArea.Tokens findAreaForToken(int windowType, boolean ownerCanManageAppTokens,
             boolean roundedCornerOverlay) {
-        // TODO(b/159767464): cover TYPE_INPUT_METHOD(_DIALOG) case here. mAreaForLayer doesn't
-        // contain IME container.
         int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
-                ownerCanManageAppTokens);
+                ownerCanManageAppTokens, roundedCornerOverlay);
         if (windowLayerFromType == APPLICATION_LAYER) {
             throw new IllegalArgumentException(
                     "There shouldn't be WindowToken on APPLICATION_LAYER");
-        } else if (roundedCornerOverlay) {
-            windowLayerFromType = mAreaForLayer.length - 1;
         }
         return mAreaForLayer[windowLayerFromType];
     }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 497087a..d926a36 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -778,7 +778,9 @@
                 if (surfaceController != null) {
                     ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
                             "SURFACE RECOVER DESTROY: %s", winAnimator.mWin);
-                    winAnimator.destroySurface();
+                    SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
+                    winAnimator.destroySurface(t);
+                    t.apply();
                     if (winAnimator.mWin.mActivityRecord != null) {
                         winAnimator.mWin.mActivityRecord.removeStartingWindow();
                     }
@@ -926,7 +928,7 @@
                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                 }
                 win.destroySurfaceUnchecked();
-                win.mWinAnimator.destroyPreservedSurfaceLocked();
+                win.mWinAnimator.destroyPreservedSurfaceLocked(win.getSyncTransaction());
             } while (i > 0);
             mWmService.mDestroySurface.clear();
         }
@@ -1826,26 +1828,22 @@
     }
 
     /**
-     * @return a list of activities which are the top ones in each visible stack. The first
+     * @return a list of activities which are the top ones in each visible root task. The first
      * entry will be the focused activity.
      */
     List<IBinder> getTopVisibleActivities() {
         final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
-        final Task topFocusedStack = getTopDisplayFocusedRootTask();
+        final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
         // Traverse all displays.
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            // Traverse all stacks on a display area.
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                // Get top activity from a visible stack and add it to the list.
-                if (stack.shouldBeVisible(null /* starting */)) {
-                    final ActivityRecord top = stack.getTopNonFinishingActivity();
-                    if (top != null) {
-                        if (stack == topFocusedStack) {
-                            topActivityTokens.add(0, top.appToken);
-                        } else {
-                            topActivityTokens.add(top.appToken);
-                        }
+        forAllRootTasks(rootTask -> {
+            // Get top activity from a visible root task and add it to the list.
+            if (rootTask.shouldBeVisible(null /* starting */)) {
+                final ActivityRecord top = rootTask.getTopNonFinishingActivity();
+                if (top != null) {
+                    if (rootTask == topFocusedRootTask) {
+                        topActivityTokens.add(0, top.appToken);
+                    } else {
+                        topActivityTokens.add(top.appToken);
                     }
                 }
             }
@@ -1856,9 +1854,9 @@
     @Nullable
     Task getTopDisplayFocusedRootTask() {
         for (int i = getChildCount() - 1; i >= 0; --i) {
-            final Task focusedStack = getChildAt(i).getFocusedRootTask();
-            if (focusedStack != null) {
-                return focusedStack;
+            final Task focusedRootTask = getChildAt(i).getFocusedRootTask();
+            if (focusedRootTask != null) {
+                return focusedRootTask;
             }
         }
         return null;
@@ -1866,15 +1864,15 @@
 
     @Nullable
     ActivityRecord getTopResumedActivity() {
-        final Task focusedStack = getTopDisplayFocusedRootTask();
-        if (focusedStack == null) {
+        final Task focusedRootTask = getTopDisplayFocusedRootTask();
+        if (focusedRootTask == null) {
             return null;
         }
-        final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+        final ActivityRecord resumedActivity = focusedRootTask.getResumedActivity();
         if (resumedActivity != null && resumedActivity.app != null) {
             return resumedActivity;
         }
-        // The top focused stack might not have a resumed activity yet - look on all displays in
+        // The top focused root task might not have a resumed activity yet - look on all displays in
         // focus order.
         return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
     }
@@ -1890,21 +1888,17 @@
         // First, found out what is currently the foreground app, so that we don't blow away the
         // previous app if this activity is being hosted by the process that is actually still the
         // foreground.
-        WindowProcessController fgApp = reduceOnAllTaskDisplayAreas((taskDisplayArea, app) -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                if (isTopDisplayFocusedRootTask(stack)) {
-                    final ActivityRecord resumedActivity = stack.getResumedActivity();
-                    if (resumedActivity != null) {
-                        app = resumedActivity.app;
-                    } else if (stack.mPausingActivity != null) {
-                        app = stack.mPausingActivity.app;
-                    }
-                    break;
+        WindowProcessController fgApp = getItemFromRootTasks(rootTask -> {
+            if (isTopDisplayFocusedRootTask(rootTask)) {
+                final ActivityRecord resumedActivity = rootTask.getResumedActivity();
+                if (resumedActivity != null) {
+                    return resumedActivity.app;
+                } else if (rootTask.getPausingActivity() != null) {
+                    return rootTask.getPausingActivity().app;
                 }
             }
-            return app;
-        }, null /* initValue */);
+            return null;
+        });
 
         // Now set this one as the previous process, only if that really makes sense to.
         if (r.hasProcess() && fgApp != null && r.app != fgApp
@@ -1921,27 +1915,21 @@
             mTmpRemoteException = null;
             mTmpBoolean = false; // Set to true if an activity was started.
             final DisplayContent display = getChildAt(displayNdx);
-            display.forAllTaskDisplayAreas(displayArea -> {
+            display.forAllRootTasks(rootTask -> {
                 if (mTmpRemoteException != null) {
                     return;
                 }
 
-                for (int taskNdx = displayArea.getRootTaskCount() - 1; taskNdx >= 0; --taskNdx) {
-                    final Task rootTask = displayArea.getRootTaskAt(taskNdx);
-                    if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) {
-                        break;
-                    }
-
-                    final PooledFunction c = PooledLambda.obtainFunction(
-                            RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
-                            PooledLambda.__(ActivityRecord.class), app,
-                            rootTask.topRunningActivity());
-                    rootTask.forAllActivities(c);
-                    c.recycle();
-                    if (mTmpRemoteException != null) {
-                        return;
-                    }
+                if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) {
+                    return;
                 }
+
+                final PooledFunction c = PooledLambda.obtainFunction(
+                        RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
+                        PooledLambda.__(ActivityRecord.class), app,
+                        rootTask.topRunningActivity());
+                rootTask.forAllActivities(c);
+                c.recycle();
             });
             if (mTmpRemoteException != null) {
                 throw mTmpRemoteException;
@@ -2009,39 +1997,36 @@
     }
 
     boolean switchUser(int userId, UserState uss) {
-        final Task topFocusedStack = getTopDisplayFocusedRootTask();
-        final int focusStackId = topFocusedStack != null
-                ? topFocusedStack.getRootTaskId() : INVALID_TASK_ID;
-        // We dismiss the docked stack whenever we switch users.
+        final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
+        final int focusRootTaskId = topFocusedRootTask != null
+                ? topFocusedRootTask.getRootTaskId() : INVALID_TASK_ID;
+        // We dismiss the docked root task whenever we switch users.
         if (getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
             getDefaultTaskDisplayArea().onSplitScreenModeDismissed();
         }
-        // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
-        // also cause all tasks to be moved to the fullscreen stack at a position that is
+        // Also dismiss the pinned root task whenever we switch users. Removing the pinned root task
+        // will also cause all tasks to be moved to the fullscreen root task at a position that is
         // appropriate.
         removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
 
-        mUserRootTaskInFront.put(mCurrentUser, focusStackId);
+        mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
         mCurrentUser = userId;
 
         mTaskSupervisor.mStartingUsers.add(uss);
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                stack.switchUser(userId);
-            }
+        forAllRootTasks(rootTask -> {
+            rootTask.switchUser(userId);
         });
 
-        final int restoreStackId = mUserRootTaskInFront.get(userId);
-        Task stack = getRootTask(restoreStackId);
-        if (stack == null) {
-            stack = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
+        final int restoreRootTaskId = mUserRootTaskInFront.get(userId);
+        Task rootTask = getRootTask(restoreRootTaskId);
+        if (rootTask == null) {
+            rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
         }
-        final boolean homeInFront = stack.isActivityTypeHome();
-        if (stack.isOnHomeDisplay()) {
-            stack.moveToFront("switchUserOnHomeDisplay");
+        final boolean homeInFront = rootTask.isActivityTypeHome();
+        if (rootTask.isOnHomeDisplay()) {
+            rootTask.moveToFront("switchUserOnHomeDisplay");
         } else {
-            // Stack was moved to another display while user was swapped out.
+            // Root task was moved to another display while user was swapped out.
             resumeHomeActivity(null, "switchUserOnOtherDisplay", getDefaultTaskDisplayArea());
         }
         return homeInFront;
@@ -2292,20 +2277,14 @@
      */
     int finishTopCrashedActivities(WindowProcessController app, String reason) {
         Task focusedStack = getTopDisplayFocusedRootTask();
-        Task finishedTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, task) -> {
-            // It is possible that request to finish activity might also remove its task and
-            // stack, so we need to be careful with indexes in the loop and check child count
-            // every time.
-            for (int stackNdx = 0; stackNdx < taskDisplayArea.getRootTaskCount(); ++stackNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(stackNdx);
-                final Task t = stack.finishTopCrashedActivityLocked(app, reason);
-                if (stack == focusedStack || task == null) {
-                    task = t;
-                }
+        final Task[] finishedTask = new Task[1];
+        forAllTasks(stack -> {
+            final Task t = stack.finishTopCrashedActivityLocked(app, reason);
+            if (stack == focusedStack || finishedTask[0] == null) {
+                finishedTask[0] = t;
             }
-            return task;
-        }, null /* initValue */);
-        return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID;
+        });
+        return finishedTask[0] != null ? finishedTask[0].mTaskId : INVALID_TASK_ID;
     }
 
     boolean resumeFocusedTasksTopActivities() {
@@ -2328,36 +2307,32 @@
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
             final boolean curResult = result;
-            boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas(
-                    (taskDisplayArea, resumed) -> {
-                        for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                            final Task rootTask = taskDisplayArea.getRootTaskAt(sNdx);
-                            final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
-                            if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
-                                continue;
-                            }
-                            if (rootTask == targetRootTask) {
-                                // Simply update the result for targetStack because the targetStack
-                                // had already resumed in above. We don't want to resume it again,
-                                // especially in some cases, it would cause a second launch failure
-                                // if app process was dead.
-                                resumed |= curResult;
-                                continue;
-                            }
-                            if (taskDisplayArea.isTopRootTask(rootTask)
-                                    && topRunningActivity.isState(RESUMED)) {
-                                // Kick off any lingering app transitions form the MoveTaskToFront
-                                // operation, but only consider the top task and stack on that
-                                // display.
-                                rootTask.executeAppTransition(targetOptions);
-                            } else {
-                                resumed |= topRunningActivity.makeActiveIfNeeded(target);
-                            }
-                        }
-                        return resumed;
-                    }, false /* initValue */);
-            result |= resumedOnDisplay;
-            if (!resumedOnDisplay) {
+            boolean[] resumedOnDisplay = new boolean[1];
+            display.forAllRootTasks(rootTask -> {
+                final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
+                if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
+                    return;
+                }
+                if (rootTask == targetRootTask) {
+                    // Simply update the result for targetStack because the targetStack
+                    // had already resumed in above. We don't want to resume it again,
+                    // especially in some cases, it would cause a second launch failure
+                    // if app process was dead.
+                    resumedOnDisplay[0] |= curResult;
+                    return;
+                }
+                if (rootTask.getDisplayArea().isTopRootTask(rootTask)
+                        && topRunningActivity.isState(RESUMED)) {
+                    // Kick off any lingering app transitions form the MoveTaskToFront
+                    // operation, but only consider the top task and stack on that
+                    // display.
+                    rootTask.executeAppTransition(targetOptions);
+                } else {
+                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
+                }
+            });
+            result |= resumedOnDisplay[0];
+            if (!resumedOnDisplay[0]) {
                 // In cases when there are no valid activities (e.g. device just booted or launcher
                 // crashed) it's possible that nothing was resumed on a display. Requesting resume
                 // of top activity in focused stack explicitly will make sure that at least home
@@ -2375,7 +2350,7 @@
         return result;
     }
 
-    void applySleepTokens(boolean applyToStacks) {
+    void applySleepTokens(boolean applyToRootTasks) {
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             // Set the sleeping state of the display.
             final DisplayContent display = getChildAt(displayNdx);
@@ -2385,35 +2360,32 @@
             }
             display.setIsSleeping(displayShouldSleep);
 
-            if (!applyToStacks) {
+            if (!applyToRootTasks) {
                 continue;
             }
 
-            // Set the sleeping state of the stacks on the display.
-            display.forAllTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                    if (displayShouldSleep) {
-                        stack.goToSleepIfPossible(false /* shuttingDown */);
-                    } else {
-                        stack.awakeFromSleepingLocked();
-                        if (stack.isFocusedStackOnDisplay()
-                                && !mTaskSupervisor.getKeyguardController()
-                                .isKeyguardOrAodShowing(display.mDisplayId)) {
-                            // If the keyguard is unlocked - resume immediately.
-                            // It is possible that the display will not be awake at the time we
-                            // process the keyguard going away, which can happen before the sleep
-                            // token is released. As a result, it is important we resume the
-                            // activity here.
-                            stack.resumeTopActivityUncheckedLocked(null, null);
-                        }
-                        // The visibility update must not be called before resuming the top, so the
-                        // display orientation can be updated first if needed. Otherwise there may
-                        // have redundant configuration changes due to apply outdated display
-                        // orientation (from keyguard) to activity.
-                        stack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
-                                false /* preserveWindows */);
+            // Set the sleeping state of the root tasks on the display.
+            display.forAllRootTasks(rootTask -> {
+                if (displayShouldSleep) {
+                    rootTask.goToSleepIfPossible(false /* shuttingDown */);
+                } else {
+                    rootTask.awakeFromSleepingLocked();
+                    if (rootTask.isFocusedStackOnDisplay()
+                            && !mTaskSupervisor.getKeyguardController()
+                            .isKeyguardOrAodShowing(display.mDisplayId)) {
+                        // If the keyguard is unlocked - resume immediately.
+                        // It is possible that the display will not be awake at the time we
+                        // process the keyguard going away, which can happen before the sleep
+                        // token is released. As a result, it is important we resume the
+                        // activity here.
+                        rootTask.resumeTopActivityUncheckedLocked(null, null);
                     }
+                    // The visibility update must not be called before resuming the top, so the
+                    // display orientation can be updated first if needed. Otherwise there may
+                    // have redundant configuration changes due to apply outdated display
+                    // orientation (from keyguard) to activity.
+                    rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                            false /* preserveWindows */);
                 }
             });
         }
@@ -2455,7 +2427,7 @@
         task.fillTaskInfo(info);
 
         // A task might be not attached to a display.
-        info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(task) : 0;
+        info.position = taskDisplayArea != null ? taskDisplayArea.getTaskIndexOf(task) : 0;
         info.visible = task.shouldBeVisible(null);
         task.getBounds(info.bounds);
 
@@ -2499,24 +2471,21 @@
     }
 
     RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
-        final Task stack = getRootTask(windowingMode, activityType);
-        return (stack != null) ? getRootTaskInfo(stack) : null;
+        final Task rootTask = getRootTask(windowingMode, activityType);
+        return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
     }
 
     RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) {
-        final Task stack = getRootTask(windowingMode, activityType, displayId);
-        return (stack != null) ? getRootTaskInfo(stack) : null;
+        final Task rootTask = getRootTask(windowingMode, activityType, displayId);
+        return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
     }
 
     /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */
     ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) {
-        ArrayList<RootTaskInfo> list = new ArrayList<>();
+        final ArrayList<RootTaskInfo> list = new ArrayList<>();
         if (displayId == INVALID_DISPLAY) {
-            forAllTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                    list.add(getRootTaskInfo(stack));
-                }
+            forAllRootTasks(rootTask -> {
+                list.add(getRootTaskInfo(rootTask));
             });
             return list;
         }
@@ -2524,11 +2493,8 @@
         if (display == null) {
             return list;
         }
-        display.forAllTaskDisplayAreas(taskDisplayArea -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                list.add(getRootTaskInfo(stack));
-            }
+        display.forAllRootTasks(rootTask -> {
+            list.add(getRootTaskInfo(rootTask));
         });
         return list;
     }
@@ -2601,10 +2567,17 @@
     Task findRootTaskBehind(Task rootTask) {
         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
         if (taskDisplayArea != null) {
-            for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) {
-                if (taskDisplayArea.getRootTaskAt(i) == rootTask && i > 0) {
-                    return taskDisplayArea.getRootTaskAt(i - 1);
+            final boolean[] hasFound = new boolean[1];
+            // TODO(b/175136051): should this be only the direct child root task?
+            final Task rootTaskBehind = taskDisplayArea.getRootTask(task -> {
+                if (hasFound[0]) {
+                    return true;
                 }
+                hasFound[0] = task == rootTask;
+                return false;
+            });
+            if (rootTaskBehind != null) {
+                return rootTaskBehind;
             }
         }
         throw new IllegalStateException("Failed to find a root task behind root task =" + rootTask
@@ -2736,8 +2709,9 @@
 
         if (DEBUG_SWITCH) {
             Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
-                    + " resumed=" + r.getStack().mResumedActivity + " pausing="
-                    + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
+                    + " resumed=" + r.getTask().getResumedActivity() + " pausing="
+                    + r.getTask().getPausingActivity() + " for reason "
+                    + mDestroyAllActivitiesReason);
         }
 
         r.destroyImmediately(mDestroyAllActivitiesReason);
@@ -2746,24 +2720,16 @@
     // Tries to put all activity tasks to sleep. Returns true if all tasks were
     // successfully put to sleep.
     boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) {
-        return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                // Stacks and activities could be removed while putting activities to sleep if
-                // the app process was gone. This prevents us getting exception by accessing an
-                // invalid stack index.
-                if (sNdx >= taskDisplayArea.getRootTaskCount()) {
-                    continue;
-                }
-                final Task task = taskDisplayArea.getRootTaskAt(sNdx);
-                if (allowDelay) {
-                    result &= task.goToSleepIfPossible(shuttingDown);
-                } else {
-                    task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
-                            !PRESERVE_WINDOWS);
-                }
+        final boolean[] result = {true};
+        forAllRootTasks(task -> {
+            if (allowDelay) {
+                result[0] &= task.goToSleepIfPossible(shuttingDown);
+            } else {
+                task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+                        !PRESERVE_WINDOWS);
             }
-            return result;
-        }, true /* initValue */);
+        });
+        return result[0];
     }
 
     void handleAppCrash(WindowProcessController app) {
@@ -2989,8 +2955,8 @@
         }
 
         // If {@code r} is already in target display area and its task is the same as the candidate
-        // task, the intention should be getting a launch stack for the reusable activity, so we can
-        // use the existing stack.
+        // task, the intention should be getting a launch root task for the reusable activity, so we
+        // can use the existing root task.
         if (candidateTask != null) {
             final TaskDisplayArea attachedTaskDisplayArea = candidateTask.getDisplayArea();
             if (attachedTaskDisplayArea == null || attachedTaskDisplayArea == taskDisplayArea) {
@@ -2999,9 +2965,9 @@
             // Or the candidate task is already a root task that can be reused by reparenting
             // it to the target display.
             if (candidateTask.isRootTask()) {
-                final Task stack = candidateTask.getRootTask();
-                stack.reparent(taskDisplayArea, true /* onTop */);
-                return stack;
+                final Task rootTask = candidateTask.getRootTask();
+                rootTask.reparent(taskDisplayArea, true /* onTop */);
+                return rootTask;
             }
         }
 
@@ -3018,16 +2984,16 @@
         windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, r, candidateTask,
                 r.getActivityType());
 
-        // Return the topmost valid stack on the display.
-        for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; --i) {
-            final Task stack = taskDisplayArea.getRootTaskAt(i);
-            if (isValidLaunchRootTask(stack, r, windowingMode)) {
-                return stack;
-            }
+        // Return the topmost valid root task on the display.
+        final int targetWindowingMode = windowingMode;
+        final Task topmostValidRootTask = taskDisplayArea.getRootTask(rootTask ->
+                isValidLaunchRootTask(rootTask, r, targetWindowingMode));
+        if (topmostValidRootTask != null) {
+            return topmostValidRootTask;
         }
 
-        // If there is no valid stack on the secondary display area - check if new dynamic stack
-        // will do.
+        // If there is no valid root task on the secondary display area - check if new dynamic root
+        // task will do.
         if (taskDisplayArea != getDisplayContent(taskDisplayArea.getDisplayId())
                 .getDefaultTaskDisplayArea()) {
             final int activityType =
@@ -3258,12 +3224,8 @@
     }
 
     void finishVoiceTask(IVoiceInteractionSession session) {
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            final int numStacks = taskDisplayArea.getRootTaskCount();
-            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(stackNdx);
-                stack.finishVoiceTask(session);
-            }
+        forAllRootTasks(rootTask -> {
+            rootTask.finishVoiceTask(session);
         });
     }
 
@@ -3322,20 +3284,16 @@
 
     boolean allResumedActivitiesVisible() {
         boolean[] foundResumed = {false};
-        final boolean foundInvisibleResumedActivity = forAllTaskDisplayAreas(
-                taskDisplayArea -> {
-                    for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                        final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                        final ActivityRecord r = stack.getResumedActivity();
-                        if (r != null) {
-                            if (!r.nowVisible) {
-                                return true;
-                            }
-                            foundResumed[0] = true;
-                        }
-                    }
-                    return false;
-                });
+        final boolean foundInvisibleResumedActivity = forAllRootTasks(rootTask -> {
+            final ActivityRecord r = rootTask.getResumedActivity();
+            if (r != null) {
+                if (!r.nowVisible) {
+                    return true;
+                }
+                foundResumed[0] = true;
+            }
+            return false;
+        });
         if (foundInvisibleResumedActivity) {
             return false;
         }
@@ -3344,23 +3302,19 @@
 
     boolean allPausedActivitiesComplete() {
         boolean[] pausing = {true};
-        final boolean hasActivityNotCompleted = forAllTaskDisplayAreas(
-                taskDisplayArea -> {
-                    for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                        final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                        final ActivityRecord r = stack.mPausingActivity;
-                        if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) {
-                            ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: "
-                                    + "r=%s state=%s", r, r.getState());
-                            if (WM_DEBUG_STATES.isEnabled()) {
-                                pausing[0] = false;
-                            } else {
-                                return true;
-                            }
-                        }
-                    }
-                    return false;
-                });
+        final boolean hasActivityNotCompleted = forAllLeafTasks(task -> {
+            final ActivityRecord r = task.getPausingActivity();
+            if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) {
+                ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: "
+                        + "r=%s state=%s", r, r.getState());
+                if (WM_DEBUG_STATES.isEnabled()) {
+                    pausing[0] = false;
+                } else {
+                    return true;
+                }
+            }
+            return false;
+        });
         if (hasActivityNotCompleted) {
             return false;
         }
@@ -3411,13 +3365,10 @@
     }
 
     void cancelInitializingActivities() {
-        forAllTaskDisplayAreas(taskDisplayArea -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                // We don't want to clear starting window for activities that aren't occluded
-                // as we need to display their starting window until they are done initializing.
-                taskDisplayArea.getRootTaskAt(sNdx).forAllOccludedActivities(
-                        ActivityRecord::cancelInitializing);
-            }
+        forAllRootTasks(task -> {
+            // We don't want to clear starting window for activities that aren't occluded
+            // as we need to display their starting window until they are done initializing.
+            task.forAllOccludedActivities(ActivityRecord::cancelInitializing);
         });
     }
 
@@ -3577,13 +3528,10 @@
                 return new ArrayList<>();
             }
         } else {
-            ArrayList<ActivityRecord> activities = new ArrayList<>();
-            forAllTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                    if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
-                        activities.addAll(stack.getDumpActivitiesLocked(name));
-                    }
+            final ArrayList<ActivityRecord> activities = new ArrayList<>();
+            forAllRootTasks(rootTask -> {
+                if (!dumpVisibleStacksOnly || rootTask.shouldBeVisible(null)) {
+                    activities.addAll(rootTask.getDumpActivitiesLocked(name));
                 }
             });
             return activities;
@@ -3633,15 +3581,12 @@
             pw.print("Display #");
             pw.print(displayContent.mDisplayId);
             pw.println(" (activities from top to bottom):");
-            displayContent.forAllTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                    if (needSep[0]) {
-                        pw.println();
-                    }
-                    needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
-                    printed[0] |= needSep[0];
+            displayContent.forAllRootTasks(rootTask -> {
+                if (needSep[0]) {
+                    pw.println();
                 }
+                needSep[0] = rootTask.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+                printed[0] |= needSep[0];
             });
             displayContent.forAllTaskDisplayAreas(taskDisplayArea -> {
                 printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(),
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index c414c64..57d48c6 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.DEVICE_POWER;
 import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
@@ -124,7 +125,9 @@
         mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
                 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
         mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
-                HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
+                HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED
+                || service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS)
+                == PERMISSION_GRANTED;
         mOverlaysCanBeHidden = !mCanAddInternalSystemWindow
                 && !mService.mAtmInternal.isCallerRecents(mUid);
         mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index 3764122..2124ed6 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 
 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
 
@@ -28,14 +28,15 @@
     private final WindowManagerService mService;
     private final TaskSnapshot mSnapshot;
 
-    SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
-        super(service);
+    SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot, int typeParams) {
+        super(service, typeParams);
         mService = service;
         mSnapshot = snapshot;
     }
 
     @Override
     StartingSurface createStartingSurface(ActivityRecord activity) {
-        return mService.mTaskSnapshotController.createStartingSurface(activity, mSnapshot);
+        return mService.mStartingSurfaceController.createTaskSnapshotSurface(activity,
+                mSnapshot);
     }
 }
diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
index 50a101d..185a317 100644
--- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java
+++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
@@ -38,8 +38,8 @@
 
     SplashScreenStartingData(WindowManagerService service, String pkg, int theme,
             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
-            int logo, int windowFlags, Configuration mergedOverrideConfiguration) {
-        super(service);
+            int logo, int windowFlags, Configuration mergedOverrideConfiguration, int typeParams) {
+        super(service, typeParams);
         mPkg = pkg;
         mTheme = theme;
         mCompatInfo = compatInfo;
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index 2e6e777..a5bd797 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -24,9 +24,11 @@
 public abstract class StartingData {
 
     protected final WindowManagerService mService;
+    protected final int mTypeParams;
 
-    protected StartingData(WindowManagerService service) {
+    protected StartingData(WindowManagerService service, int typeParams) {
         mService = service;
+        mTypeParams = typeParams;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index 6d7ddf6..94e14dd 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -16,9 +16,20 @@
 
 package com.android.server.wm;
 
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.os.SystemProperties;
+import android.util.Slog;
+import android.window.TaskSnapshot;
 
 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
 
@@ -26,7 +37,8 @@
  * Managing to create and release a starting window surface.
  */
 public class StartingSurfaceController {
-
+    private static final String TAG = TAG_WITH_CLASS_NAME
+            ? StartingSurfaceController.class.getSimpleName() : TAG_WM;
     /** Set to {@code true} to enable shell starting surface drawer. */
     private static final boolean DEBUG_ENABLE_SHELL_DRAWER =
             SystemProperties.getBoolean("persist.debug.shell_starting_surface", false);
@@ -49,15 +61,79 @@
         final Task task = activity.getTask();
         if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(task,
                 activity.token)) {
-            return new SplashScreenContainerSurface(task);
+            return new ShellStartingSurface(task);
         }
         return null;
     }
 
-    private final class SplashScreenContainerSurface implements StartingSurface {
+    int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
+            boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated) {
+        int parameter = 0;
+        if (newTask) {
+            parameter |= TYPE_PARAMETER_NEW_TASK;
+        }
+        if (taskSwitch) {
+            parameter |= TYPE_PARAMETER_TASK_SWITCH;
+        }
+        if (processRunning) {
+            parameter |= TYPE_PARAMETER_PROCESS_RUNNING;
+        }
+        if (allowTaskSnapshot) {
+            parameter |= TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+        }
+        if (activityCreated) {
+            parameter |= TYPE_PARAMETER_ACTIVITY_CREATED;
+        }
+        return parameter;
+    }
+
+    StartingSurface createTaskSnapshotSurface(ActivityRecord activity, TaskSnapshot taskSnapshot) {
+        final WindowState topFullscreenOpaqueWindow;
+        final Task task;
+        synchronized (mService.mGlobalLock) {
+            final WindowState mainWindow = activity.findMainWindow();
+            task = activity.getTask();
+            if (task == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
+                        + activity);
+                return null;
+            }
+            final ActivityRecord topFullscreenActivity =
+                    activity.getTask().getTopFullscreenActivity();
+            if (topFullscreenActivity == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+                        + task);
+                return null;
+            }
+            topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
+            if (mainWindow == null || topFullscreenOpaqueWindow == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+                        + activity);
+                return null;
+            }
+            if (topFullscreenActivity.getWindowConfiguration().getRotation()
+                    != taskSnapshot.getRotation()) {
+                // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
+                // that the activity will be updated to the same rotation as the snapshot. Since
+                // the transition is not started yet, fixed rotation transform needs to be applied
+                // earlier to make the snapshot show in a rotated container.
+                activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
+                        topFullscreenActivity, false /* checkOpening */);
+            }
+        }
+        if (!DEBUG_ENABLE_SHELL_DRAWER) {
+            return mService.mTaskSnapshotController
+                    .createStartingSurface(activity, taskSnapshot);
+        }
+        mService.mAtmService.mTaskOrganizerController.addStartingWindow(task, activity.token);
+        return new ShellStartingSurface(task);
+    }
+
+
+    private final class ShellStartingSurface implements StartingSurface {
         private final Task mTask;
 
-        SplashScreenContainerSurface(Task task) {
+        ShellStartingSurface(Task task) {
             mTask = task;
         }
 
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 34d084a..92e2ee6 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -259,6 +259,7 @@
 
     private void applyTransaction() {
         mFrameTransaction.setAnimationTransaction();
+        mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
         mFrameTransaction.apply();
         mApplyScheduled = false;
     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 00f545c..79a32e4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -59,7 +59,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
-import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
@@ -156,7 +156,6 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
@@ -207,6 +206,8 @@
 import android.view.WindowManager;
 import android.view.WindowManager.TransitionOldType;
 import android.window.ITaskOrganizer;
+import android.window.StartingWindowInfo;
+import android.window.TaskSnapshot;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -514,11 +515,6 @@
     // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
     boolean mSupportsPictureInPicture;
 
-    // Activity bounds if this task or its top activity is presented in letterbox mode and
-    // {@code null} otherwise.
-    @Nullable
-    private Rect mLetterboxActivityBounds;
-
     // Whether the task is currently being drag-resized
     private boolean mDragResizing;
     private int mDragResizeMode;
@@ -548,8 +544,11 @@
     /**
      * When we are in the process of pausing an activity, before starting the
      * next one, this variable holds the activity that is currently being paused.
+     *
+     * Only set at leaf tasks.
      */
-    ActivityRecord mPausingActivity = null;
+    @Nullable
+    private ActivityRecord mPausingActivity = null;
 
     /**
      * This is the last activity that we put into the paused state.  This is
@@ -565,8 +564,12 @@
      */
     ActivityRecord mLastNoHistoryActivity = null;
 
-    /** Current activity that is resumed, or null if there is none. */
-    ActivityRecord mResumedActivity = null;
+    /**
+     * Current activity that is resumed, or null if there is none.
+     * Only set at leaf tasks.
+     */
+    @Nullable
+    private ActivityRecord mResumedActivity = null;
 
     /** Last activity that is used to compute the Task bounds. */
     @Nullable
@@ -1106,14 +1109,6 @@
             return false;
         }
 
-        final boolean toTopOfStack = position == MAX_VALUE;
-        if (toTopOfStack && toStack.getResumedActivity() != null
-                && toStack.topRunningActivity() != null) {
-            // Pause the resumed activity on the target stack while re-parenting task on top of it.
-            toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
-                    null /* resuming */, "reparent");
-        }
-
         final int toStackWindowingMode = toStack.getWindowingMode();
         final ActivityRecord topActivity = getTopNonFinishingActivity();
 
@@ -1137,8 +1132,6 @@
             final ActivityRecord r = topRunningActivityLocked();
             final boolean wasFocused = r != null && root.isTopDisplayFocusedRootTask(sourceStack)
                     && (topRunningActivityLocked() == r);
-            final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
-            final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
 
             // In some cases the focused stack isn't the front stack. E.g. pinned stack.
             // Whenever we are moving the top activity from the front stack we want to make sure to
@@ -1159,9 +1152,15 @@
 
             // If the task had focus before (or we're requested to move focus), move focus to the
             // new stack by moving the stack to the front.
-            if (r != null) {
-                toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
-                        wasPaused, reason);
+            if (r != null && moveStackToFront) {
+                // Move the stack in which we are placing the activity to the front.
+                toStack.moveToFront(reason);
+
+                // If the original state is resumed, there is no state change to update focused app.
+                // So here makes sure the activity focus is set if it is the top.
+                if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) {
+                    mAtmService.setResumedActivityUncheckLocked(r, reason);
+                }
             }
             if (!animate) {
                 mTaskSupervisor.mNoAnimActivities.add(topActivity);
@@ -1457,15 +1456,6 @@
         }
 
         if (newParent != null) {
-            final Task newParentTask = ((WindowContainer) newParent).asTask();
-            if (newParentTask != null) {
-                final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
-                        false /* includeOverlays */);
-                if (top != null && top.isState(RESUMED)) {
-                    newParentTask.setResumedActivity(top, "addedToTask");
-                }
-            }
-
             // TODO: Ensure that this is actually necessary here
             // Notify the voice session if required
             if (voiceSession != null) {
@@ -1502,6 +1492,15 @@
             mLastTaskBoundsComputeActivity = null;
         }
 
+        // mPausingActivity is set at leaf task
+        if (mPausingActivity != null && mPausingActivity == r) {
+            mPausingActivity = null;
+        }
+
+        if (mResumedActivity != null && mResumedActivity == r) {
+            setResumedActivity(null, "cleanUpActivityReferences");
+        }
+
         final WindowContainer parent = getParent();
         if (parent != null && parent.asTask() != null) {
             parent.asTask().cleanUpActivityReferences(r);
@@ -1509,21 +1508,38 @@
         }
         r.removeTimeouts();
         mExitingActivities.remove(r);
-
-        if (mResumedActivity != null && mResumedActivity == r) {
-            setResumedActivity(null, "cleanUpActivityReferences");
-        }
-        if (mPausingActivity != null && mPausingActivity == r) {
-            mPausingActivity = null;
-        }
     }
 
     /** @return the currently resumed activity. */
     ActivityRecord getResumedActivity() {
-        return mResumedActivity;
+        if (isLeafTask()) {
+            return mResumedActivity;
+        }
+
+        final Task task = getTask(t -> t.mResumedActivity != null, true /* traverseTopToBottom */);
+        return task != null ? task.mResumedActivity : null;
+    }
+
+    @VisibleForTesting
+    void setPausingActivity(ActivityRecord pausing) {
+        mPausingActivity = pausing;
+    }
+
+    /**
+     * @return the currently pausing activity of this task or the topmost pausing activity of the
+     * child tasks
+     */
+    ActivityRecord getPausingActivity() {
+        if (isLeafTask()) {
+            return mPausingActivity;
+        }
+
+        final Task task = getTask(t -> t.mPausingActivity != null, true /* traverseTopToBottom */);
+        return task != null ? task.mPausingActivity : null;
     }
 
     void setResumedActivity(ActivityRecord r, String reason) {
+        warnForNonLeafTask("setResumedActivity");
         if (mResumedActivity == r) {
             return;
         }
@@ -2163,17 +2179,7 @@
      * @param reason The reason for the change.
      */
     void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
-        final Task parentTask = getParent().asTask();
-        if (parentTask != null) {
-            parentTask.onActivityStateChanged(record, state, reason);
-            // We still want to update the resumed activity if the parent task is created by
-            // organizer in order to keep the information synced once got reparented out from the
-            // organized task.
-            if (!parentTask.mCreatedByOrganizer) {
-                return;
-            }
-        }
-
+        warnForNonLeafTask("onActivityStateChanged");
         if (record == mResumedActivity && state != RESUMED) {
             setResumedActivity(null, reason + " - onActivityStateChanged");
         }
@@ -2351,7 +2357,7 @@
      * Initializes a change transition. See {@link SurfaceFreezer} for more information.
      */
     private void initializeChangeTransition(Rect startBounds) {
-        mDisplayContent.prepareAppTransition(TRANSIT_CHANGE_WINDOWING_MODE);
+        mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
         mDisplayContent.mChangingContainers.add(this);
 
         mSurfaceFreezer.freeze(getPendingTransaction(), startBounds);
@@ -2435,8 +2441,7 @@
 
     @Override
     public SurfaceControl getFreezeSnapshotTarget() {
-        if (!mDisplayContent.mAppTransition.containsTransitRequest(
-                TRANSIT_CHANGE_WINDOWING_MODE)) {
+        if (!mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)) {
             return null;
         }
         // Skip creating snapshot if this transition is controlled by a remote animator which
@@ -3130,12 +3135,12 @@
         // and focused application if needed.
         focusableTask.moveToFront(myReason);
         // Top display focused stack is changed, update top resumed activity if needed.
-        if (rootTask.mResumedActivity != null) {
+        if (rootTask.getResumedActivity() != null) {
             mTaskSupervisor.updateTopResumedActivityIfNeeded();
             // Set focused app directly because if the next focused activity is already resumed
             // (e.g. the next top activity is on a different display), there won't have activity
             // state change to update it.
-            mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason);
+            mAtmService.setResumedActivityUncheckLocked(rootTask.getResumedActivity(), reason);
         }
         return rootTask;
     }
@@ -3808,7 +3813,7 @@
         mTaskDescription = taskDescription;
     }
 
-    void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+    void onSnapshotChanged(TaskSnapshot snapshot) {
         mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
                 mTaskId, snapshot);
     }
@@ -3874,6 +3879,13 @@
     }
 
     @Override
+    void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
+        if (isRootTask()) {
+            callback.accept(this);
+        }
+    }
+
+    @Override
     boolean forAllTasks(Function<Task, Boolean> callback) {
         if (super.forAllTasks(callback)) return true;
         return callback.apply(this);
@@ -3898,12 +3910,29 @@
     }
 
     @Override
+    boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) {
+        return isRootTask() ? callback.apply(this) : false;
+    }
+
+    @Override
     Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
         final Task t = super.getTask(callback, traverseTopToBottom);
         if (t != null) return t;
         return callback.test(this) ? this : null;
     }
 
+    @Nullable
+    @Override
+    Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) {
+        return isRootTask() && callback.test(this) ? this : null;
+    }
+
+    @Nullable
+    @Override
+    <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) {
+        return isRootTask() ? callback.apply(this) : null;
+    }
+
     /**
      * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
      *                               flags. See {@link WindowState#canAffectSystemUiFlags()}.
@@ -4078,15 +4107,10 @@
         info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
         info.topActivityType = top.getActivityType();
         info.isResizeable = isResizeable();
-        // Don't query getTopNonFinishingActivity().getBounds() directly because when fillTaskInfo
-        // is triggered for the first time after activities change, getBounds() may return non final
-        // bounds, e.g. fullscreen bounds instead of letterboxed bounds. To work around this,
-        // assigning bounds from ActivityRecord#layoutLetterbox when they are ready.
-        info.letterboxActivityBounds = Rect.copyOrNull(mLetterboxActivityBounds);
-        info.positionInParent = getRelativePosition();
-        info.parentBounds = getParentBounds();
 
-        info.pictureInPictureParams = getPictureInPictureParams();
+        info.positionInParent = getRelativePosition();
+
+        info.pictureInPictureParams = getPictureInPictureParams(top);
         info.topActivityInfo = mReuseActivitiesReport.top != null
                 ? mReuseActivitiesReport.top.info
                 : null;
@@ -4103,32 +4127,16 @@
     }
 
     @Nullable PictureInPictureParams getPictureInPictureParams() {
-        final Task top = getTopMostTask();
+        return getPictureInPictureParams(getTopMostTask());
+    }
+
+    private @Nullable PictureInPictureParams getPictureInPictureParams(Task top) {
         if (top == null) return null;
         final ActivityRecord rootActivity = top.getRootActivity();
         return (rootActivity == null || rootActivity.pictureInPictureArgs.empty())
                 ? null : new PictureInPictureParams(rootActivity.pictureInPictureArgs);
     }
 
-    void maybeUpdateLetterboxBounds(
-                ActivityRecord activityRecord, @Nullable Rect letterboxActivityBounds) {
-        if (isOrganized()
-                && mReuseActivitiesReport.top == activityRecord
-                // Want to force update only if letterbox bounds have changed.
-                && !Objects.equals(
-                    mLetterboxActivityBounds,
-                    letterboxActivityBounds)) {
-            mLetterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds);
-            // Forcing update to reduce visual jank during the transition.
-            dispatchTaskInfoChangedIfNeeded(true /* force */);
-        }
-    }
-
-    private Rect getParentBounds() {
-        final WindowContainer parent = getParent();
-        return parent != null ? new Rect(parent.getBounds()) : new Rect();
-    }
-
     /**
      * Returns a {@link TaskInfo} with information from this task.
      */
@@ -4138,6 +4146,34 @@
         return info;
     }
 
+    StartingWindowInfo getStartingWindowInfo() {
+        final StartingWindowInfo info = new StartingWindowInfo();
+        info.taskInfo = getTaskInfo();
+
+        final ActivityRecord topActivity = getTopMostActivity();
+        if (topActivity != null) {
+            info.startingWindowTypeParameter =
+                    topActivity.mStartingData != null
+                            ? topActivity.mStartingData.mTypeParams
+                            : 0;
+            final WindowState mainWindow = topActivity.findMainWindow();
+            if (mainWindow != null) {
+                info.mainWindowLayoutParams = mainWindow.getAttrs();
+            }
+        }
+        final ActivityRecord topFullscreenActivity = getTopFullscreenActivity();
+        if (topFullscreenActivity != null) {
+            final WindowState topFullscreenOpaqueWindow =
+                    topFullscreenActivity.getTopFullscreenOpaqueWindow();
+            if (topFullscreenOpaqueWindow != null) {
+                info.topOpaqueWindowInsetsState =
+                        topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride();
+                info.topOpaqueWindowLayoutParams = topFullscreenOpaqueWindow.getAttrs();
+            }
+        }
+        return info;
+    }
+
     boolean isTaskId(int taskId) {
         return mTaskId == taskId;
     }
@@ -5313,20 +5349,19 @@
         final TaskDisplayArea taskDisplayArea = getDisplayArea();
 
         if (inSplitScreenSecondaryWindowingMode()) {
-            // If the stack is in split-screen secondary mode, we need to make sure we move the
-            // primary split-screen stack forward in the case it is currently behind a fullscreen
-            // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't
-            // cutting between them.
+            // If the root task is in split-screen secondary mode, we need to make sure we move the
+            // primary split-screen root task forward in the case it is currently behind a
+            // fullscreen root task so both halves of the split-screen appear on-top and the
+            // fullscreen root task isn't cutting between them.
             // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
-            final Task topFullScreenStack =
+            final Task topFullScreenRootTask =
                     taskDisplayArea.getTopRootTaskInWindowingMode(WINDOWING_MODE_FULLSCREEN);
-            if (topFullScreenStack != null) {
-                final Task primarySplitScreenStack =
+            if (topFullScreenRootTask != null) {
+                final Task primarySplitScreenRootTask =
                         taskDisplayArea.getRootSplitScreenPrimaryTask();
-                if (primarySplitScreenStack != null
-                        && taskDisplayArea.getIndexOf(topFullScreenStack)
-                        > taskDisplayArea.getIndexOf(primarySplitScreenStack)) {
-                    primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
+                if (primarySplitScreenRootTask != null
+                        && topFullScreenRootTask.compareTo(primarySplitScreenRootTask) > 0) {
+                    primarySplitScreenRootTask.moveToFront(reason + " splitScreenToTop");
                 }
             }
         }
@@ -5414,6 +5449,12 @@
     }
 
     void awakeFromSleepingLocked() {
+        if (!isLeafTask()) {
+            forAllLeafTasks((task) -> task.awakeFromSleepingLocked(),
+                    true /* traverseTopToBottom */);
+            return;
+        }
+
         if (mPausingActivity != null) {
             Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
             mPausingActivity.activityPaused(true);
@@ -5438,8 +5479,17 @@
      * process of going to sleep (checkReadyForSleep will be called when that process finishes).
      */
     boolean goToSleepIfPossible(boolean shuttingDown) {
-        boolean shouldSleep = true;
+        if (!isLeafTask()) {
+            final int[] sleepInProgress = {0};
+            forAllLeafTasks((t) -> {
+                if (!t.goToSleepIfPossible(shuttingDown)) {
+                    sleepInProgress[0]++;
+                }
+            }, true);
+            return sleepInProgress[0] == 0;
+        }
 
+        boolean shouldSleep = true;
         if (mResumedActivity != null) {
             // Still have something resumed; can't sleep until it is paused.
             ProtoLog.v(WM_DEBUG_STATES, "Sleep needs to pause %s", mResumedActivity);
@@ -5499,6 +5549,16 @@
      */
     final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
             ActivityRecord resuming, String reason) {
+        if (!isLeafTask()) {
+            final int[] pausing = {0};
+            forAllLeafTasks((t) -> {
+                if (t.startPausingLocked(userLeaving, uiSleeping, resuming, reason)) {
+                    pausing[0]++;
+                }
+            }, true /* traverseTopToBottom */);
+            return pausing[0] > 0;
+        }
+
         if (mPausingActivity != null) {
             Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                     + " state=" + mPausingActivity.getState());
@@ -5629,6 +5689,10 @@
 
     @VisibleForTesting
     void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
+        // Complete the pausing process of a pausing activity, so it doesn't make sense to
+        // operate on non-leaf tasks.
+        warnForNonLeafTask("completePauseLocked");
+
         ActivityRecord prev = mPausingActivity;
         ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
 
@@ -5712,7 +5776,7 @@
     }
 
     /**
-     * @return {@code true} if this is the focused stack on its current display, {@code false}
+     * @return {@code true} if this is the focused root task on its current display, {@code false}
      * otherwise.
      */
     boolean isFocusedStackOnDisplay() {
@@ -5888,24 +5952,34 @@
             return false;
         }
 
-        boolean result = false;
+        boolean someActivityResumed = false;
         try {
             // Protect against recursion.
             mInResumeTopActivity = true;
 
-            // TODO(b/172885410): Allow the top activities of all visible leaf tasks to be resumed
-            if (mCreatedByOrganizer && !isLeafTask()
-                    && getConfiguration().windowConfiguration.getWindowingMode()
-                            == WINDOWING_MODE_FULLSCREEN) {
-                for (int i = mChildren.size() - 1; i >= 0; i--) {
-                    final Task child = (Task) getChildAt(i);
-                    if (!child.shouldBeVisible(null /* starting */)) {
+            if (isLeafTask()) {
+                someActivityResumed = resumeTopActivityInnerLocked(prev, options);
+            } else {
+                int idx = mChildren.size() - 1;
+                while (idx >= 0) {
+                    final Task child = (Task) getChildAt(idx--);
+                    if (!child.isFocusableAndVisible()) {
                         break;
                     }
-                    result |= child.resumeTopActivityUncheckedLocked(prev, options);
+
+                    // Only allow one activity to be resumed among sibling tasks in split-screen.
+                    if (inSplitScreenWindowingMode() && someActivityResumed) {
+                        break;
+                    }
+
+                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options);
+                    // Doing so in order to prevent IndexOOB since hierarchy might changes while
+                    // resuming activities, for example dismissing split-screen while starting
+                    // non-resizeable activity.
+                    if (idx >= mChildren.size()) {
+                        idx = mChildren.size() - 1;
+                    }
                 }
-            } else {
-                result = resumeTopActivityInnerLocked(prev, options);
             }
 
             // When resuming the top activity, it may be necessary to pause the top activity (for
@@ -5923,7 +5997,7 @@
             mInResumeTopActivity = false;
         }
 
-        return result;
+        return someActivityResumed;
     }
 
     @GuardedBy("mService")
@@ -6037,7 +6111,7 @@
             // So, why aren't we using prev here??? See the param comment on the method. prev
             // doesn't represent the last resumed activity. However, the last focus stack does if
             // it isn't null.
-            lastResumed = lastFocusedStack.mResumedActivity;
+            lastResumed = lastFocusedStack.getResumedActivity();
             if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
                 // The user isn't leaving if this stack is the multi-window mode and the last
                 // focused stack should still be visible.
@@ -6206,7 +6280,7 @@
             next.startLaunchTickingLocked();
 
             ActivityRecord lastResumedActivity =
-                    lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
+                    lastFocusedStack == null ? null : lastFocusedStack.getResumedActivity();
             final ActivityState lastState = next.getState();
 
             mAtmService.updateCpuStats();
@@ -6654,18 +6728,21 @@
         });
     }
 
-    /** @return true if the stack behind this one is a standard activity type. */
-    private boolean inFrontOfStandardStack() {
+    /** @return true if the root task behind this one is a standard activity type. */
+    private boolean inFrontOfStandardRootTask() {
         final TaskDisplayArea taskDisplayArea = getDisplayArea();
         if (taskDisplayArea == null) {
             return false;
         }
-        final int index = taskDisplayArea.getIndexOf(this);
+        final int index = taskDisplayArea.getTaskIndexOf(this);
         if (index == 0) {
             return false;
         }
-        final Task stackBehind = taskDisplayArea.getChildAt(index - 1);
-        return stackBehind.isActivityTypeStandard();
+        final int[] indexCount = new int[1];
+        final Task rootTaskBehind = taskDisplayArea.getRootTask(
+                // From bottom to top, find the one behind this Task.
+                task -> ++indexCount[0] == index, false /* traverseTopToBottom */);
+        return rootTaskBehind.isActivityTypeStandard();
     }
 
     boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
@@ -6686,7 +6763,7 @@
         if (srec.isRootOfTask() && task.getBaseIntent() != null
                 && task.getBaseIntent().isDocument()) {
             // Okay, this activity is at the root of its task.  What to do, what to do...
-            if (!inFrontOfStandardStack()) {
+            if (!inFrontOfStandardRootTask()) {
                 // Finishing won't return to an application, so we need to recreate.
                 return true;
             }
@@ -7060,6 +7137,7 @@
      * @return {@code true} if the process of the pausing activity is died.
      */
     boolean handleAppDied(WindowProcessController app) {
+        warnForNonLeafTask("handleAppDied");
         boolean isPausingDied = false;
         if (mPausingActivity != null && mPausingActivity.app == app) {
             ProtoLog.v(WM_DEBUG_STATES, "App died while pausing: %s",
@@ -7097,7 +7175,7 @@
             printed = true;
         }
 
-        printed |= printThisActivity(pw, mPausingActivity, dumpPackage, false,
+        printed |= printThisActivity(pw, getPausingActivity(), dumpPackage, false,
                 "    mPausingActivity: ", null);
         printed |= printThisActivity(pw, getResumedActivity(), dumpPackage, false,
                 "    mResumedActivity: ", null);
@@ -7276,7 +7354,7 @@
         task.updateOverrideConfigurationForStack(this);
 
         final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
-        final boolean wasResumed = topRunningActivity == task.getRootTask().mResumedActivity;
+        final boolean wasResumed = topRunningActivity == task.mResumedActivity;
 
         boolean toTop = position >= getChildCount();
         boolean includingParents = toTop || getDisplayArea().getNextFocusableRootTask(this,
@@ -7299,7 +7377,7 @@
         if (wasResumed) {
             if (mResumedActivity != null) {
                 Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from"
-                        + " other stack to this stack mResumedActivity=" + mResumedActivity
+                        + " other stack to this task mResumedActivity=" + mResumedActivity
                         + " other mResumedActivity=" + topRunningActivity);
             }
             topRunningActivity.setState(RESUMED, "positionChildAt");
@@ -7325,34 +7403,6 @@
         taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */);
     }
 
-    /** NOTE: Should only be called from {@link Task#reparent}. */
-    void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
-            boolean setPause, String reason) {
-        if (!moveToFront) {
-            return;
-        }
-
-        final ActivityState origState = r.getState();
-        // If the activity owns the last resumed activity, transfer that together,
-        // so that we don't resume the same activity again in the new stack.
-        // Apps may depend on onResume()/onPause() being called in pairs.
-        if (setResume) {
-            r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
-        }
-        // If the activity was previously pausing, then ensure we transfer that as well
-        if (setPause) {
-            mPausingActivity = r;
-            r.schedulePauseTimeout();
-        }
-        // Move the stack in which we are placing the activity to the front.
-        moveToFront(reason);
-        // If the original state is resumed, there is no state change to update focused app.
-        // So here makes sure the activity focus is set if it is the top.
-        if (origState == RESUMED && r == mRootWindowContainer.getTopResumedActivity()) {
-            mAtmService.setResumedActivityUncheckLocked(r, reason);
-        }
-    }
-
     void dismissPip() {
         if (!isActivityTypeStandardOrUndefined()) {
             throw new IllegalArgumentException(
@@ -7502,6 +7552,15 @@
     }
 
     /**
+     * Simply check and give warning logs if this is not operated on leaf task.
+     */
+    private void warnForNonLeafTask(String func) {
+        if (!isLeafTask()) {
+            Slog.w(TAG, func + " on non-leaf task " + this);
+        }
+    }
+
+    /**
      * Sets the current picture-in-picture aspect ratio.
      */
     void setPictureInPictureAspectRatio(float aspectRatio) {
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index b4d069c..28ebe01 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -18,7 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.app.ITaskStackListener;
 import android.app.TaskInfo;
 import android.content.ComponentName;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 9425602..866abbd 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -33,7 +33,6 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
@@ -72,8 +71,10 @@
 
 /**
  * {@link DisplayArea} that represents a section of a screen that contains app window containers.
+ *
+ * The children can be either {@link Task} or {@link TaskDisplayArea}.
  */
-final class TaskDisplayArea extends DisplayArea<Task> {
+final class TaskDisplayArea extends DisplayArea<WindowContainer> {
 
     DisplayContent mDisplayContent;
 
@@ -107,9 +108,9 @@
     // TODO(b/159029784): Remove when getStack() behavior is cleaned-up
     private Task mRootRecentsTask;
 
-    private final ArrayList<Task> mTmpAlwaysOnTopRootTasks = new ArrayList<>();
-    private final ArrayList<Task> mTmpNormalRootTasks = new ArrayList<>();
-    private final ArrayList<Task> mTmpHomeRootTasks = new ArrayList<>();
+    private final ArrayList<WindowContainer> mTmpAlwaysOnTopChildren = new ArrayList<>();
+    private final ArrayList<WindowContainer> mTmpNormalChildren = new ArrayList<>();
+    private final ArrayList<WindowContainer> mTmpHomeChildren = new ArrayList<>();
     private final IntArray mTmpNeedsZBoostIndexes = new IntArray();
     private int mTmpLayerForSplitScreenDividerAnchor;
     private int mTmpLayerForAnimationLayer;
@@ -180,9 +181,10 @@
     }
 
     /**
-     * Returns the topmost stack on the display that is compatible with the input windowing mode
-     * and activity type. Null is no compatible stack on the display.
+     * Returns the topmost root task on the display that is compatible with the input windowing mode
+     * and activity type. Null is no compatible root task on the display.
      */
+    @Nullable
     Task getRootTask(int windowingMode, int activityType) {
         if (activityType == ACTIVITY_TYPE_HOME) {
             return mRootHomeTask;
@@ -194,30 +196,48 @@
         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
             return mRootSplitScreenPrimaryTask;
         }
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final Task stack = getChildAt(i);
+        return getRootTask(rootTask -> {
             if (activityType == ACTIVITY_TYPE_UNDEFINED
-                    && windowingMode == stack.getWindowingMode()) {
-                // Passing in undefined type means we want to match the topmost stack with the
+                    && windowingMode == rootTask.getWindowingMode()) {
+                // Passing in undefined type means we want to match the topmost root task with the
                 // windowing mode.
-                return stack;
+                return true;
             }
-            if (stack.isCompatible(windowingMode, activityType)) {
-                return stack;
-            }
-        }
-        return null;
+            return rootTask.isCompatible(windowingMode, activityType);
+        });
     }
 
     @VisibleForTesting
     Task getTopRootTask() {
-        final int count = getChildCount();
-        return count > 0 ? getChildAt(count - 1) : null;
+        return getRootTask(t -> true);
     }
 
-    // TODO: Figure-out a way to remove since it might be a source of confusion.
-    int getIndexOf(Task task) {
-        return mChildren.indexOf(task);
+    // TODO(b/175832855): Figure-out a way to remove since it might be a source of confusion.
+    /**
+     * Gets the order of the given {@link Task} as its z-order in the hierarchy below this TDA.
+     * The Task can be a direct child of a child TaskDisplayArea. {@code -1} if not found.
+     */
+    int getTaskIndexOf(Task task) {
+        int index = 0;
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final WindowContainer wc = getChildAt(i);
+            if (wc.asTask() != null) {
+                if (wc.asTask() == task) {
+                    return index;
+                }
+                index++;
+            } else {
+                final TaskDisplayArea tda = wc.asTaskDisplayArea();
+                final int subIndex = tda.getTaskIndexOf(task);
+                if (subIndex > -1) {
+                    return index + subIndex;
+                } else {
+                    index += tda.getRootTaskCount();
+                }
+            }
+        }
+        return -1;
     }
 
     @Nullable
@@ -239,9 +259,11 @@
     }
 
     Task getRootSplitScreenSecondaryTask() {
+        // Only check the direct child Task for now, since the primary is also a direct child Task.
         for (int i = mChildren.size() - 1; i >= 0; --i) {
-            if (mChildren.get(i).inSplitScreenSecondaryWindowingMode()) {
-                return mChildren.get(i);
+            final Task task = mChildren.get(i).asTask();
+            if (task != null && task.inSplitScreenSecondaryWindowingMode()) {
+                return task;
             }
         }
         return null;
@@ -324,7 +346,22 @@
     }
 
     @Override
-    void addChild(Task task, int position) {
+    void addChild(WindowContainer child, int position) {
+        if (child.asTaskDisplayArea() != null) {
+            if (DEBUG_ROOT_TASK) {
+                Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);
+            }
+            super.addChild(child, position);
+        } else if (child.asTask() != null) {
+            addChildTask(child.asTask(), position);
+        } else {
+            throw new IllegalArgumentException(
+                    "TaskDisplayArea can only add Task and TaskDisplayArea, but found "
+                            + child);
+        }
+    }
+
+    private void addChildTask(Task task, int position) {
         if (DEBUG_ROOT_TASK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);
 
         addRootTaskReferenceIfNeeded(task);
@@ -336,11 +373,23 @@
     }
 
     @Override
-    protected void removeChild(Task stack) {
-        super.removeChild(stack);
-        onRootTaskRemoved(stack);
+    protected void removeChild(WindowContainer child) {
+        if (child.asTaskDisplayArea() != null) {
+            super.removeChild(child);
+        } else if (child.asTask() != null) {
+            removeChildTask(child.asTask());
+        } else {
+            throw new IllegalArgumentException(
+                    "TaskDisplayArea can only remove Task and TaskDisplayArea, but found "
+                            + child);
+        }
+    }
+
+    private void removeChildTask(Task task) {
+        super.removeChild(task);
+        onRootTaskRemoved(task);
         mAtmService.updateSleepIfNeededLocked();
-        removeRootTaskReferenceIfNeeded(stack);
+        removeRootTaskReferenceIfNeeded(task);
     }
 
     @Override
@@ -350,21 +399,33 @@
     }
 
     @Override
-    void positionChildAt(int position, Task child, boolean includingParents) {
+    void positionChildAt(int position, WindowContainer child, boolean includingParents) {
+        if (child.asTaskDisplayArea() != null) {
+            super.positionChildAt(position, child, includingParents);
+        } else if (child.asTask() != null) {
+            positionChildTaskAt(position, child.asTask(), includingParents);
+        } else {
+            throw new IllegalArgumentException(
+                    "TaskDisplayArea can only position Task and TaskDisplayArea, but found "
+                            + child);
+        }
+    }
+
+    private void positionChildTaskAt(int position, Task child, boolean includingParents) {
         final boolean moveToTop = position >= getChildCount() - 1;
         final boolean moveToBottom = position <= 0;
 
         final int oldPosition = mChildren.indexOf(child);
         if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
-            // This stack is always-on-top, override the default behavior.
-            Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
+            // This root task is always-on-top, override the default behavior.
+            Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom");
 
             // Moving to its current position, as we must call super but we don't want to
             // perform any meaningful action.
             super.positionChildAt(oldPosition, child, false /* includingParents */);
             return;
         }
-        // We don't allow untrusted display to top when task stack moves to top,
+        // We don't allow untrusted display to top when root task moves to top,
         // until user tapping this display to change display position as top intentionally.
         if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) {
             includingParents = false;
@@ -433,48 +494,85 @@
     @Override
     boolean forAllTaskDisplayAreas(Function<TaskDisplayArea, Boolean> callback,
             boolean traverseTopToBottom) {
-        return callback.apply(this);
+        // Apply the callback to all TDAs at or below this container. If the callback returns true,
+        // stop early.
+        if (traverseTopToBottom) {
+            // When it is top to bottom, run on child TDA first as they are on top of the parent.
+            return super.forAllTaskDisplayAreas(callback, traverseTopToBottom)
+                    || callback.apply(this);
+        }
+        return callback.apply(this) || super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
     }
 
     @Override
     void forAllTaskDisplayAreas(Consumer<TaskDisplayArea> callback, boolean traverseTopToBottom) {
-        callback.accept(this);
+        if (traverseTopToBottom) {
+            super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
+            callback.accept(this);
+        } else {
+            callback.accept(this);
+            super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
+        }
     }
 
     @Nullable
     @Override
     <R> R reduceOnAllTaskDisplayAreas(BiFunction<TaskDisplayArea, R, R> accumulator,
             @Nullable R initValue, boolean traverseTopToBottom) {
-        return accumulator.apply(this, initValue);
+        if (traverseTopToBottom) {
+            final R result =
+                    super.reduceOnAllTaskDisplayAreas(accumulator, initValue, traverseTopToBottom);
+            return accumulator.apply(this, result);
+        } else {
+            final R result = accumulator.apply(this, initValue);
+            return super.reduceOnAllTaskDisplayAreas(accumulator, result, traverseTopToBottom);
+
+        }
     }
 
     @Nullable
     @Override
     <R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback,
             boolean traverseTopToBottom) {
-        return callback.apply(this);
+        if (traverseTopToBottom) {
+            final R item = super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
+            return item != null ? item : callback.apply(this);
+        } else {
+            final R item = callback.apply(this);
+            return item != null
+                    ? item
+                    : super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
+        }
     }
 
     /**
-     * Assigns a priority number to stack types. This priority defines an order between the types
-     * of stacks that are added to the task display area.
+     * Assigns a priority number to root task types. This priority defines an order between the
+     * types of root task that are added to the task display area.
      *
-     * Higher priority number indicates that the stack should have a higher z-order.
+     * Higher priority number indicates that the root task should have a higher z-order.
      *
-     * @return the priority of the stack
+     * For child {@link TaskDisplayArea}, it will be the priority of its top child.
+     *
+     * @return the priority of the root task
      */
-    private int getPriority(Task stack) {
-        if (mWmService.mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
-        if (stack.isActivityTypeDream()) return 3;
-        if (stack.inPinnedWindowingMode()) return 2;
-        if (stack.isAlwaysOnTop()) return 1;
+    private int getPriority(WindowContainer child) {
+        final TaskDisplayArea tda = child.asTaskDisplayArea();
+        if (tda != null) {
+            // Use the top child priority as the TaskDisplayArea priority.
+            return tda.getPriority(tda.getTopChild());
+        }
+        final Task rootTask = child.asTask();
+        if (mWmService.mAssistantOnTopOfDream && rootTask.isActivityTypeAssistant()) return 4;
+        if (rootTask.isActivityTypeDream()) return 3;
+        if (rootTask.inPinnedWindowingMode()) return 2;
+        if (rootTask.isAlwaysOnTop()) return 1;
         return 0;
     }
 
     private int findMinPositionForRootTask(Task rootTask) {
         int minPosition = POSITION_BOTTOM;
         for (int i = 0; i < mChildren.size(); ++i) {
-            if (getPriority(getRootTaskAt(i)) < getPriority(rootTask)) {
+            if (getPriority(mChildren.get(i)) < getPriority(rootTask)) {
                 minPosition = i;
             } else {
                 break;
@@ -482,10 +580,12 @@
         }
 
         if (rootTask.isAlwaysOnTop()) {
-            // Since a stack could be repositioned while still being one of the children, we check
-            // if this always-on-top stack already exists and if so, set the minPosition to its
-            // previous position.
-            final int currentIndex = getIndexOf(rootTask);
+            // Since a root task could be repositioned while still being one of the children, we
+            // check if this always-on-top root task already exists and if so, set the minPosition
+            // to its previous position.
+            // Use mChildren.indexOf instead of getTaskIndexOf because we need to place the rootTask
+            // as a direct child.
+            final int currentIndex = mChildren.indexOf(rootTask);
             if (currentIndex > minPosition) {
                 minPosition = currentIndex;
             }
@@ -495,9 +595,9 @@
 
     private int findMaxPositionForRootTask(Task rootTask) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final Task curr = getRootTaskAt(i);
-            // Since a stack could be repositioned while still being one of the children, we check
-            // if 'curr' is the same stack and skip it if so
+            final WindowContainer curr = mChildren.get(i);
+            // Since a root task could be repositioned while still being one of the children, we
+            // check if 'curr' is the same root task and skip it if so
             final boolean sameRootTask = curr == rootTask;
             if (getPriority(curr) <= getPriority(rootTask) && !sameRootTask) {
                 return i;
@@ -507,29 +607,29 @@
     }
 
     /**
-     * When stack is added or repositioned, find a proper position for it.
+     * When root task is added or repositioned, find a proper position for it.
      *
      * The order is defined as:
      * - Dream is on top of everything
      * - PiP is directly below the Dream
-     * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
-     * existing ones
-     * - other non-always-on-top stacks come directly below always-on-top stacks; new
-     * non-always-on-top stacks are added directly below always-on-top stacks and above existing
-     * non-always-on-top stacks
+     * - always-on-top root tasks are directly below PiP; new always-on-top root tasks are added
+     * above existing ones
+     * - other non-always-on-top root tasks come directly below always-on-top root tasks; new
+     * non-always-on-top root tasks are added directly below always-on-top root tasks and above
+     * existing non-always-on-top root tasks
      * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
-     * (including the Dream); otherwise, it is a normal non-always-on-top stack
+     * (including the Dream); otherwise, it is a normal non-always-on-top root task
      *
      * @param requestedPosition Position requested by caller.
      * @param rootTask          Root task to be added or positioned.
-     * @param adding            Flag indicates whether we're adding a new stack or positioning an
-     *                          existing.
-     * @return The proper position for the stack.
+     * @param adding            Flag indicates whether we're adding a new root task or positioning
+     *                          an existing.
+     * @return The proper position for the root task.
      */
     private int findPositionForRootTask(int requestedPosition, Task rootTask, boolean adding) {
-        // The max possible position we can insert the stack at.
+        // The max possible position we can insert the root task at.
         int maxPosition = findMaxPositionForRootTask(rootTask);
-        // The min possible position we can insert the stack at.
+        // The min possible position we can insert the root task at.
         int minPosition = findMinPositionForRootTask(rootTask);
 
         // Cap the requested position to something reasonable for the previous position check
@@ -548,8 +648,8 @@
         // The positions we calculated above (maxPosition, minPosition) do not take into
         // consideration the following edge cases.
         // 1) We need to adjust the position depending on the value "adding".
-        // 2) When we are moving a stack to another position, we also need to adjust the
-        //    position depending on whether the stack is moving to a higher or lower position.
+        // 2) When we are moving a root task to another position, we also need to adjust the
+        //    position depending on whether the root task is moving to a higher or lower position.
         if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
             targetPosition++;
         }
@@ -580,13 +680,19 @@
 
     private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
             boolean traverseTopToBottom) {
-        // For legacy reasons we process the TaskStack.mExitingActivities first here before the
+        // For legacy reasons we process the RootTask.mExitingActivities first here before the
         // app tokens.
         // TODO: Investigate if we need to continue to do this or if we can just process them
         // in-order.
         if (traverseTopToBottom) {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                // Only run on those of direct Task child, because child TaskDisplayArea has run on
+                // its child in #forAllWindows()
+                if (mChildren.get(i).asTask() == null) {
+                    continue;
+                }
+                final List<ActivityRecord> activities =
+                        mChildren.get(i).asTask().mExitingActivities;
                 for (int j = activities.size() - 1; j >= 0; --j) {
                     if (activities.get(j).forAllWindowsUnchecked(callback,
                             traverseTopToBottom)) {
@@ -597,7 +703,13 @@
         } else {
             final int count = mChildren.size();
             for (int i = 0; i < count; ++i) {
-                final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                // Only run on those of direct Task child, because child TaskDisplayArea has run on
+                // its child in #forAllWindows()
+                if (mChildren.get(i).asTask() == null) {
+                    continue;
+                }
+                final List<ActivityRecord> activities =
+                        mChildren.get(i).asTask().mExitingActivities;
                 final int appTokensCount = activities.size();
                 for (int j = 0; j < appTokensCount; j++) {
                     if (activities.get(j).forAllWindowsUnchecked(callback,
@@ -610,40 +722,21 @@
         return false;
     }
 
-    void setExitingTokensHasVisible(boolean hasVisible) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-            for (int j = activities.size() - 1; j >= 0; --j) {
-                activities.get(j).hasVisible = hasVisible;
-            }
-        }
-    }
-
-    void removeExistingAppTokensIfPossible() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-            for (int j = activities.size() - 1; j >= 0; --j) {
-                final ActivityRecord activity = activities.get(j);
-                if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
-                        && (!activity.mIsExiting || activity.isEmpty())) {
-                    // Make sure there is no animation running on this activity, so any windows
-                    // associated with it will be removed as soon as their animations are
-                    // complete.
-                    cancelAnimation();
-                    ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                            "performLayout: Activity exiting now removed %s", activity);
-                    activity.removeIfPossible();
-                }
-            }
-        }
-    }
-
     @Override
     int getOrientation(int candidate) {
         mLastOrientationSource = null;
-        if (!canSpecifyOrientation()) {
+        if (mIgnoreOrientationRequest) {
             return SCREEN_ORIENTATION_UNSET;
         }
+        if (!canSpecifyOrientation()) {
+            // We only respect orientation of the focused TDA, which can be a child of this TDA.
+            return reduceOnAllTaskDisplayAreas((taskDisplayArea, orientation) -> {
+                if (taskDisplayArea == this || orientation != SCREEN_ORIENTATION_UNSET) {
+                    return orientation;
+                }
+                return taskDisplayArea.getOrientation(candidate);
+            }, SCREEN_ORIENTATION_UNSET);
+        }
 
         if (isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
             // Apps and their containers are not allowed to specify an orientation while using
@@ -700,8 +793,7 @@
         assignRootTaskOrdering(t);
 
         for (int i = 0; i < mChildren.size(); i++) {
-            final Task s = mChildren.get(i);
-            s.assignChildLayers(t);
+            mChildren.get(i).assignChildLayers(t);
         }
     }
 
@@ -709,33 +801,49 @@
         if (getParent() == null) {
             return;
         }
-        mTmpAlwaysOnTopRootTasks.clear();
-        mTmpHomeRootTasks.clear();
-        mTmpNormalRootTasks.clear();
+        mTmpAlwaysOnTopChildren.clear();
+        mTmpHomeChildren.clear();
+        mTmpNormalChildren.clear();
         for (int i = 0; i < mChildren.size(); ++i) {
-            final Task s = mChildren.get(i);
-            if (s.isAlwaysOnTop()) {
-                mTmpAlwaysOnTopRootTasks.add(s);
-            } else if (s.isActivityTypeHome()) {
-                mTmpHomeRootTasks.add(s);
+            final WindowContainer child = mChildren.get(i);
+            final TaskDisplayArea childTda = child.asTaskDisplayArea();
+            if (childTda != null) {
+                final Task childTdaTopRootTask = childTda.getTopRootTask();
+                if (childTdaTopRootTask == null) {
+                    mTmpNormalChildren.add(childTda);
+                } else if (childTdaTopRootTask.isAlwaysOnTop()) {
+                    mTmpAlwaysOnTopChildren.add(childTda);
+                } else if (childTdaTopRootTask.isActivityTypeHome()) {
+                    mTmpHomeChildren.add(childTda);
+                } else {
+                    mTmpNormalChildren.add(childTda);
+                }
+                continue;
+            }
+
+            final Task childTask = child.asTask();
+            if (childTask.isAlwaysOnTop()) {
+                mTmpAlwaysOnTopChildren.add(childTask);
+            } else if (childTask.isActivityTypeHome()) {
+                mTmpHomeChildren.add(childTask);
             } else {
-                mTmpNormalRootTasks.add(s);
+                mTmpNormalChildren.add(childTask);
             }
         }
 
         int layer = 0;
         // Place home stacks to the bottom.
-        layer = adjustRootTaskLayer(t, mTmpHomeRootTasks, layer, false /* normalStacks */);
+        layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer, false /* normalRootTasks */);
         // The home animation layer is between the home stacks and the normal stacks.
         final int layerForHomeAnimationLayer = layer++;
         mTmpLayerForSplitScreenDividerAnchor = layer++;
         mTmpLayerForAnimationLayer = layer++;
-        layer = adjustRootTaskLayer(t, mTmpNormalRootTasks, layer, true /* normalStacks */);
+        layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer, true /* normalRootTasks */);
 
         // The boosted animation layer is between the normal stacks and the always on top
         // stacks.
         final int layerForBoostedAnimationLayer = layer++;
-        adjustRootTaskLayer(t, mTmpAlwaysOnTopRootTasks, layer, false /* normalStacks */);
+        adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer, false /* normalRootTasks */);
 
         t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
         t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer);
@@ -743,13 +851,14 @@
         t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
     }
 
-    private int adjustNormalRootTaskLayer(Task s, int layer) {
-        if (s.inSplitScreenWindowingMode()) {
+    private int adjustNormalRootTaskLayer(WindowContainer child, int layer) {
+        if (child.asTask() != null && child.inSplitScreenWindowingMode()) {
             // The split screen divider anchor is located above the split screen window.
             mTmpLayerForSplitScreenDividerAnchor = layer++;
         }
-        if (s.isAnimatingByRecents() || s.isAppTransitioning()) {
-            // The animation layer is located above the highest animating stack and no
+        if ((child.asTask() != null && child.asTask().isAnimatingByRecents())
+                || child.isAppTransitioning()) {
+            // The animation layer is located above the highest animating root task and no
             // higher.
             mTmpLayerForAnimationLayer = layer++;
         }
@@ -757,23 +866,30 @@
     }
 
     /**
-     * Adjusts the layer of the stack which belongs to the same group.
-     * Note that there are three stack groups: home stacks, always on top stacks, and normal stacks.
+     * Adjusts the layer of the root task which belongs to the same group.
+     * Note that there are three root task groups: home rootTasks, always on top rootTasks, and
+     * normal rootTasks.
      *
-     * @param startLayer   The beginning layer of this group of stacks.
-     * @param normalStacks Set {@code true} if this group is neither home nor always on top.
+     * @param startLayer   The beginning layer of this group of rootTasks.
+     * @param normalRootTasks Set {@code true} if this group is neither home nor always on top.
      * @return The adjusted layer value.
      */
-    private int adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<Task> stacks,
-            int startLayer, boolean normalStacks) {
+    private int adjustRootTaskLayer(SurfaceControl.Transaction t,
+            ArrayList<WindowContainer> children, int startLayer, boolean normalRootTasks) {
         mTmpNeedsZBoostIndexes.clear();
-        final int stackSize = stacks.size();
-        for (int i = 0; i < stackSize; i++) {
-            final Task stack = stacks.get(i);
-            if (!stack.needsZBoost()) {
-                stack.assignLayer(t, startLayer++);
-                if (normalStacks) {
-                    startLayer = adjustNormalRootTaskLayer(stack, startLayer);
+        final int childCount = children.size();
+        for (int i = 0; i < childCount; i++) {
+            final WindowContainer child = children.get(i);
+            final TaskDisplayArea childTda = child.asTaskDisplayArea();
+
+            boolean childNeedsZBoost = childTda != null
+                    ? childTda.childrenNeedZBoost()
+                    : child.needsZBoost();
+
+            if (!childNeedsZBoost) {
+                child.assignLayer(t, startLayer++);
+                if (normalRootTasks) {
+                    startLayer = adjustNormalRootTaskLayer(child, startLayer);
                 }
             } else {
                 mTmpNeedsZBoostIndexes.add(i);
@@ -782,15 +898,23 @@
 
         final int zBoostSize = mTmpNeedsZBoostIndexes.size();
         for (int i = 0; i < zBoostSize; i++) {
-            final Task stack = stacks.get(mTmpNeedsZBoostIndexes.get(i));
-            stack.assignLayer(t, startLayer++);
-            if (normalStacks) {
-                startLayer = adjustNormalRootTaskLayer(stack, startLayer);
+            final WindowContainer child = children.get(mTmpNeedsZBoostIndexes.get(i));
+            child.assignLayer(t, startLayer++);
+            if (normalRootTasks) {
+                startLayer = adjustNormalRootTaskLayer(child, startLayer);
             }
         }
         return startLayer;
     }
 
+    private boolean childrenNeedZBoost() {
+        final boolean[] needsZBoost = new boolean[1];
+        forAllRootTasks(task -> {
+            needsZBoost[0] |= task.needsZBoost();
+        });
+        return needsZBoost[0];
+    }
+
     @Override
     SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
         switch (animationLayer) {
@@ -894,16 +1018,6 @@
         }
     }
 
-    Task getRootTask(int rootTaskId) {
-        for (int i = getRootTaskCount() - 1; i >= 0; --i) {
-            final Task stack = getRootTaskAt(i);
-            if (stack.getRootTaskId() == rootTaskId) {
-                return stack;
-            }
-        }
-        return null;
-    }
-
     /**
      * Returns an existing stack compatible with the windowing mode and activity type or creates one
      * if a compatible stack doesn't exist.
@@ -1065,16 +1179,26 @@
             // Only split-screen windowing modes can do this currently...
             return null;
         }
-        for (int i = getRootTaskCount() - 1; i >= 0; --i) {
-            final Task t = getRootTaskAt(i);
-            if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            if (child.asTaskDisplayArea() != null) {
+                final Task t = child.asTaskDisplayArea().updateLaunchRootTask(windowingMode);
+                if (t != null) {
+                    return t;
+                }
+                continue;
+            }
+
+            final Task t = mChildren.get(i).asTask();
+            if (t == null || !t.mCreatedByOrganizer
+                    || t.getRequestedOverrideWindowingMode() != windowingMode) {
                 continue;
             }
             // If not already set, pick a launch root which is not the one we are launching into.
             if (mLaunchRootTask == null) {
-                for (int j = 0, n = getRootTaskCount(); j < n; ++j) {
-                    final Task tt = getRootTaskAt(j);
-                    if (tt.mCreatedByOrganizer && tt != t) {
+                for (int j = 0, n = mChildren.size(); j < n; ++j) {
+                    final Task tt = mChildren.get(j).asTask();
+                    if (tt != null && tt.mCreatedByOrganizer && tt != t) {
                         mLaunchRootTask = tt;
                         break;
                     }
@@ -1120,18 +1244,27 @@
     }
 
     /**
-     * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
-     * focusable and visible stack from the top of stacks in this display.
+     * Get the preferred focusable root task in priority. If the preferred root task does not exist,
+     * find a focusable and visible root task from the top of root tasks in this display.
      */
     Task getFocusedRootTask() {
         if (mPreferredTopFocusableRootTask != null) {
             return mPreferredTopFocusableRootTask;
         }
 
-        for (int i = getRootTaskCount() - 1; i >= 0; --i) {
-            final Task stack = getRootTaskAt(i);
-            if (stack.isFocusableAndVisible()) {
-                return stack;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            if (child.asTaskDisplayArea() != null) {
+                final Task rootTask = child.asTaskDisplayArea().getFocusedRootTask();
+                if (rootTask != null) {
+                    return rootTask;
+                }
+                continue;
+            }
+
+            final Task rootTask = mChildren.get(i).asTask();
+            if (rootTask.isFocusableAndVisible()) {
+                return rootTask;
             }
         }
 
@@ -1143,8 +1276,18 @@
                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
 
         Task candidate = null;
-        for (int i = getRootTaskCount() - 1; i >= 0; --i) {
-            final Task rootTask = getRootTaskAt(i);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            if (child.asTaskDisplayArea() != null) {
+                final Task rootTask = child.asTaskDisplayArea()
+                        .getNextFocusableRootTask(currentFocus, ignoreCurrent);
+                if (rootTask != null) {
+                    return rootTask;
+                }
+                continue;
+            }
+
+            final Task rootTask = mChildren.get(i).asTask();
             if (ignoreCurrent && rootTask == currentFocus) {
                 continue;
             }
@@ -1154,18 +1297,19 @@
 
             if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                     && candidate == null && rootTask.inSplitScreenPrimaryWindowingMode()) {
-                // If the currently focused stack is in split-screen secondary we save off the
-                // top primary split-screen stack as a candidate for focus because we might
-                // prefer focus to move to an other stack to avoid primary split-screen stack
-                // overlapping with a fullscreen stack when a fullscreen stack is higher in z
-                // than the next split-screen stack. Assistant stack, I am looking at you...
-                // We only move the focus to the primary-split screen stack if there isn't a
+                // If the currently focused root task is in split-screen secondary we save off the
+                // top primary split-screen root task as a candidate for focus because we might
+                // prefer focus to move to an other root task to avoid primary split-screen root
+                // task overlapping with a fullscreen root task when a fullscreen root task is
+                // higher in z than the next split-screen root task. Assistant root task, I am
+                // looking at you...
+                // We only move the focus to the primary-split screen root task if there isn't a
                 // better alternative.
                 candidate = rootTask;
                 continue;
             }
             if (candidate != null && rootTask.inSplitScreenSecondaryWindowingMode()) {
-                // Use the candidate stack since we are now at the secondary split-screen.
+                // Use the candidate root task since we are now at the secondary split-screen.
                 return candidate;
             }
             return rootTask;
@@ -1174,21 +1318,21 @@
     }
 
     ActivityRecord getFocusedActivity() {
-        final Task focusedStack = getFocusedRootTask();
-        if (focusedStack == null) {
+        final Task focusedRootTask = getFocusedRootTask();
+        if (focusedRootTask == null) {
             return null;
         }
         // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
-        // Check if the focused stack has the resumed activity
-        ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+        // Check if the focused root task has the resumed activity
+        ActivityRecord resumedActivity = focusedRootTask.getResumedActivity();
         if (resumedActivity == null || resumedActivity.app == null) {
-            // If there is no registered resumed activity in the stack or it is not running -
+            // If there is no registered resumed activity in the root task or it is not running -
             // try to use previously resumed one.
-            resumedActivity = focusedStack.mPausingActivity;
+            resumedActivity = focusedRootTask.getPausingActivity();
             if (resumedActivity == null || resumedActivity.app == null) {
                 // If previously resumed activity doesn't work either - find the topmost running
                 // activity that can be focused.
-                resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
+                resumedActivity = focusedRootTask.topRunningActivity(true /* focusableOnly */);
             }
         }
         return resumedActivity;
@@ -1223,47 +1367,56 @@
     }
 
     boolean allResumedActivitiesComplete() {
-        for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityRecord r = getRootTaskAt(stackNdx).getResumedActivity();
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            if (child.asTaskDisplayArea() != null) {
+                if (!child.asTaskDisplayArea().allResumedActivitiesComplete()) {
+                    return false;
+                }
+                continue;
+            }
+
+            final ActivityRecord r = mChildren.get(i).asTask().getResumedActivity();
             if (r != null && !r.isState(RESUMED)) {
                 return false;
             }
         }
-        final Task currentFocusedStack = getFocusedRootTask();
+        final Task currentFocusedRootTask = getFocusedRootTask();
         if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
-            Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
-                    + mLastFocusedRootTask + " to=" + currentFocusedStack);
+            Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: currentFocusedRootTask "
+                    + "changing from=" + mLastFocusedRootTask + " to=" + currentFocusedRootTask);
         }
-        mLastFocusedRootTask = currentFocusedStack;
+        mLastFocusedRootTask = currentFocusedRootTask;
         return true;
     }
 
     /**
-     * Pause all activities in either all of the stacks or just the back stacks. This is done before
-     * resuming a new activity and to make sure that previously active activities are
-     * paused in stacks that are no longer visible or in pinned windowing mode. This does not
-     * pause activities in visible stacks, so if an activity is launched within the same stack/task,
-     * then we should explicitly pause that stack's top activity.
+     * Pause all activities in either all of the root tasks or just the back root tasks. This is
+     * done before resuming a new activity and to make sure that previously active activities are
+     * paused in root tasks that are no longer visible or in pinned windowing mode. This does not
+     * pause activities in visible root tasks, so if an activity is launched within the same root
+     * task, hen we should explicitly pause that root task's top activity.
      *
      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
      * @param resuming    The resuming activity.
      * @return {@code true} if any activity was paused as a result of this call.
      */
     boolean pauseBackTasks(boolean userLeaving, ActivityRecord resuming) {
-        boolean someActivityPaused = false;
-        for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) {
-            final Task stack = getRootTaskAt(stackNdx);
-            final ActivityRecord resumedActivity = stack.getResumedActivity();
+        final int[] someActivityPaused = {0};
+        forAllLeafTasks((task) -> {
+            final ActivityRecord resumedActivity = task.getResumedActivity();
             if (resumedActivity != null
-                    && (stack.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE
-                    || !stack.isTopActivityFocusable())) {
-                ProtoLog.d(WM_DEBUG_STATES, "pauseBackStacks: stack=%s "
-                        + "mResumedActivity=%s", stack, resumedActivity);
-                someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
-                        resuming, "pauseBackStacks");
+                    && (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE
+                    || !task.isTopActivityFocusable())) {
+                ProtoLog.d(WM_DEBUG_STATES, "pauseBackTasks: task=%s "
+                        + "mResumedActivity=%s", task, resumedActivity);
+                if (task.startPausingLocked(userLeaving, false /* uiSleeping*/,
+                        resuming, "pauseBackTasks")) {
+                    someActivityPaused[0]++;
+                }
             }
-        }
-        return someActivityPaused;
+        }, true /* traverseTopToBottom */);
+        return someActivityPaused[0] > 0;
     }
 
     /**
@@ -1272,18 +1425,21 @@
     void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
             RootWindowContainer.FindTaskResult result) {
         mTmpFindTaskResult.clear();
-        for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) {
-            final Task stack = getRootTaskAt(stackNdx);
-            if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
-                ProtoLog.d(WM_DEBUG_TASKS, "Skipping stack: (mismatch activity/stack) "
-                        + "%s", stack);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final Task rootTask = mChildren.get(i).asTask();
+            if (rootTask == null) {
+                continue;
+            }
+            if (!r.hasCompatibleActivityType(rootTask) && rootTask.isLeafTask()) {
+                ProtoLog.d(WM_DEBUG_TASKS, "Skipping rootTask: (mismatch activity/rootTask) "
+                        + "%s", rootTask);
                 continue;
             }
 
-            mTmpFindTaskResult.process(r, stack);
-            // It is possible to have tasks in multiple stacks with the same root affinity, so
+            mTmpFindTaskResult.process(r, rootTask);
+            // It is possible to have tasks in multiple root tasks with the same root affinity, so
             // we should keep looking after finding an affinity match to see if there is a
-            // better match in another stack. Also, task affinity isn't a good enough reason
+            // better match in another root task. Also, task affinity isn't a good enough reason
             // to target a display which isn't the source of the intent, so skip any affinity
             // matches not on the specified display.
             if (mTmpFindTaskResult.mRecord != null) {
@@ -1291,78 +1447,15 @@
                     result.setTo(mTmpFindTaskResult);
                     return;
                 } else if (isPreferredDisplayArea) {
-                    // Note: since the traversing through the stacks is top down, the floating
+                    // Note: since the traversing through the root tasks is top down, the floating
                     // tasks should always have lower priority than any affinity-matching tasks
-                    // in the fullscreen stacks
+                    // in the fullscreen root tasks
                     result.setTo(mTmpFindTaskResult);
                 }
             }
         }
     }
 
-    /**
-     * Removes root tasks in the input windowing modes from the system if they are of activity type
-     * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
-     */
-    void removeRootTasksInWindowingModes(int... windowingModes) {
-        if (windowingModes == null || windowingModes.length == 0) {
-            return;
-        }
-
-        // Collect the root tasks that are necessary to be removed instead of performing the removal
-        // by looping the children, so that we don't miss any root tasks after the children size
-        // changed or reordered.
-        final ArrayList<Task> rootTasks = new ArrayList<>();
-        for (int j = windowingModes.length - 1; j >= 0; --j) {
-            final int windowingMode = windowingModes[j];
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final Task rootTask = mChildren.get(i);
-                if (rootTask.mCreatedByOrganizer
-                        || !rootTask.isActivityTypeStandardOrUndefined()
-                        || rootTask.getWindowingMode() != windowingMode) {
-                    continue;
-                }
-                rootTasks.add(rootTask);
-            }
-        }
-
-        for (int i = rootTasks.size() - 1; i >= 0; --i) {
-            mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
-        }
-    }
-
-    void removeRootTasksWithActivityTypes(int... activityTypes) {
-        if (activityTypes == null || activityTypes.length == 0) {
-            return;
-        }
-
-        // Collect the root tasks that are necessary to be removed instead of performing the removal
-        // by looping the children, so that we don't miss any root tasks after the children size
-        // changed or reordered.
-        final ArrayList<Task> rootTasks = new ArrayList<>();
-        for (int j = activityTypes.length - 1; j >= 0; --j) {
-            final int activityType = activityTypes[j];
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final Task rootTask = mChildren.get(i);
-                // Collect the root tasks that are currently being organized.
-                if (rootTask.mCreatedByOrganizer) {
-                    for (int k = rootTask.getChildCount() - 1; k >= 0; --k) {
-                        final Task task = (Task) rootTask.getChildAt(k);
-                        if (task.getActivityType() == activityType) {
-                            rootTasks.add(task);
-                        }
-                    }
-                } else if (rootTask.getActivityType() == activityType) {
-                    rootTasks.add(rootTask);
-                }
-            }
-        }
-
-        for (int i = rootTasks.size() - 1; i >= 0; --i) {
-            mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
-        }
-    }
-
     void onSplitScreenModeDismissed() {
         // The focused task could be a non-resizeable fullscreen root task that is on top of the
         // other split-screen tasks, therefore had to dismiss split-screen, make sure the current
@@ -1575,20 +1668,29 @@
      */
     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
         ActivityRecord topRunning = null;
-        final Task focusedStack = getFocusedRootTask();
-        if (focusedStack != null) {
-            topRunning = focusedStack.topRunningActivity();
+        final Task focusedRootTask = getFocusedRootTask();
+        if (focusedRootTask != null) {
+            topRunning = focusedRootTask.topRunningActivity();
         }
 
-        // Look in other focusable stacks.
+        // Look in other focusable root tasks.
         if (topRunning == null) {
-            for (int i = getRootTaskCount() - 1; i >= 0; --i) {
-                final Task stack = getRootTaskAt(i);
-                // Only consider focusable stacks other than the current focused one.
-                if (stack == focusedStack || !stack.isTopActivityFocusable()) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final WindowContainer child = mChildren.get(i);
+                if (child.asTaskDisplayArea() != null) {
+                    topRunning =
+                            child.asTaskDisplayArea().topRunningActivity(considerKeyguardState);
+                    if (topRunning != null) {
+                        break;
+                    }
                     continue;
                 }
-                topRunning = stack.topRunningActivity();
+                final Task rootTask = mChildren.get(i).asTask();
+                // Only consider focusable root tasks other than the current focused one.
+                if (rootTask == focusedRootTask || !rootTask.isTopActivityFocusable()) {
+                    continue;
+                }
+                topRunning = rootTask.topRunningActivity();
                 if (topRunning != null) {
                     break;
                 }
@@ -1608,11 +1710,11 @@
     }
 
     protected int getRootTaskCount() {
-        return mChildren.size();
-    }
-
-    protected Task getRootTaskAt(int index) {
-        return mChildren.get(index);
+        final int[] count = new int[1];
+        forAllRootTasks(task -> {
+            count[0]++;
+        });
+        return count[0];
     }
 
     @Nullable
@@ -1694,35 +1796,44 @@
     }
 
     /**
-     * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
+     * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary.
      * Generally used in conjunction with {@link #moveRootTaskBehindRootTask}.
      */
     // TODO(b/151575894): Remove special stack movement methods.
     void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) {
         if (rootTask.shouldBeVisible(null)) {
-            // Skip if the stack is already visible
+            // Skip if the root task is already visible
             return;
         }
 
-        // Move the stack to the bottom to not affect the following visibility checks
+        // Move the root task to the bottom to not affect the following visibility checks
         rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask,
                 false /* includingParents */);
 
-        // Find the next position where the stack should be placed
+        // Find the next position where the root task should be placed
         final boolean isRootTask = rootTask.isRootTask();
         final int numRootTasks =
-                isRootTask ? getRootTaskCount() : rootTask.getParent().getChildCount();
+                isRootTask ? mChildren.size() : rootTask.getParent().getChildCount();
         for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) {
-            final Task s = isRootTask ? getRootTaskAt(rootTaskNdx)
-                    : (Task) rootTask.getParent().getChildAt(rootTaskNdx);
-            if (s == rootTask) {
+            Task s;
+            if (isRootTask) {
+                final WindowContainer child = mChildren.get(rootTaskNdx);
+                if (child.asTaskDisplayArea() != null) {
+                    s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask);
+                } else {
+                    s = child.asTask();
+                }
+            } else {
+                s = rootTask.getParent().getChildAt(rootTaskNdx).asTask();
+            }
+            if (s == rootTask || s == null) {
                 continue;
             }
             final int winMode = s.getWindowingMode();
             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
                     || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
             if (s.shouldBeVisible(null) && isValidWindowingMode) {
-                // Move the provided stack to behind this stack
+                // Move the provided root task to behind this root task
                 final int position = Math.max(0, rootTaskNdx - 1);
                 rootTask.getParent().positionChildAt(position, rootTask,
                         false /*includingParents */);
@@ -1731,6 +1842,16 @@
         }
     }
 
+    @Nullable
+    private Task getBottomMostVisibleRootTask(Task excludeRootTask) {
+        return getRootTask(task -> {
+            final int winMode = task.getWindowingMode();
+            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
+                    || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+            return task.shouldBeVisible(null) && isValidWindowingMode;
+        }, false /* traverseTopToBottom */);
+    }
+
     /**
      * Moves the {@param stack} behind the given {@param behindStack} if possible. If
      * {@param behindStack} is not currently in the display, then then the stack is moved to the
@@ -1836,84 +1957,82 @@
             boolean preserveWindows, boolean notifyClients, boolean userLeaving) {
         mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
         try {
-            for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) {
-                final Task stack = getRootTaskAt(stackNdx);
-                stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+            forAllRootTasks(rootTask -> {
+                rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                         notifyClients, userLeaving);
-            }
+            });
         } finally {
             mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
         }
     }
 
-    void prepareFreezingTaskBounds() {
-        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final Task stack = getChildAt(stackNdx);
-            stack.prepareFreezingTaskBounds();
-        }
-    }
-
     /**
-     * Removes the stacks in the node applying the content removal node from the display.
+     * Removes the root tasks in the node applying the content removal node from the display.
      *
-     * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
+     * @return last reparented root task, or {@code null} if the root tasks had to be destroyed.
      */
     Task remove() {
         mPreferredTopFocusableRootTask = null;
         // TODO(b/153090332): Allow setting content removal mode per task display area
         final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
         final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        Task lastReparentedStack = null;
+        Task lastReparentedRootTask = null;
 
-        // Stacks could be reparented from the removed display area to other display area. After
-        // reparenting the last stack of the removed display area, the display area becomes ready to
-        // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
-        // related WindowContainer will also be removed. So, we set display area as removed after
-        // reparenting stack finished.
+        // Root tasks could be reparented from the removed display area to other display area. After
+        // reparenting the last root task of the removed display area, the display area becomes
+        // ready to be released (no more ActivityStack-s). But, we cannot release it at that moment
+        // or the related WindowContainer will also be removed. So, we set display area as removed
+        // after reparenting root task finished.
         // Keep the order from bottom to top.
-        int numStacks = getRootTaskCount();
+        int numRootTasks = mChildren.size();
 
         final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated();
-        final Task rootStack = splitScreenActivated ? toDisplayArea
+        final Task splitScreenRoot = splitScreenActivated ? toDisplayArea
                 .getTopRootTaskInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null;
-        for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
-            final Task stack = getRootTaskAt(stackNdx);
-            // Always finish non-standard type stacks and stacks created by a organizer.
+        for (int i = 0; i < numRootTasks; i++) {
+            final WindowContainer child = mChildren.get(i);
+            if (child.asTaskDisplayArea() != null) {
+                lastReparentedRootTask = child.asTaskDisplayArea().remove();
+                continue;
+            }
+            final Task task = mChildren.get(i).asTask();
+            // Always finish non-standard type root tasks and root tasks created by a organizer.
             // TODO: For stacks created by organizer, consider reparenting children tasks if the use
             //       case arises in the future.
             if (destroyContentOnRemoval
-                    || !stack.isActivityTypeStandardOrUndefined()
-                    || stack.mCreatedByOrganizer) {
-                stack.finishAllActivitiesImmediately();
+                    || !task.isActivityTypeStandardOrUndefined()
+                    || task.mCreatedByOrganizer) {
+                task.finishAllActivitiesImmediately();
             } else {
-                // Reparent the stack to the root task of secondary-split-screen or display area.
-                stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null
-                        ? rootStack : toDisplayArea, POSITION_TOP);
+                // Reparent the root task to the root task of secondary-split-screen or display
+                // area.
+                task.reparent(task.supportsSplitScreenWindowingMode() && splitScreenRoot != null
+                        ? splitScreenRoot : toDisplayArea, POSITION_TOP);
 
-                // Set the windowing mode to undefined by default to let the stack inherited the
+                // Set the windowing mode to undefined by default to let the root task inherited the
                 // windowing mode.
-                stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
-                lastReparentedStack = stack;
+                task.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+                lastReparentedRootTask = task;
             }
-            // Stacks may be removed from this display. Ensure each stack will be processed
+            // Root task may be removed from this display. Ensure each root task will be processed
             // and the loop will end.
-            stackNdx -= numStacks - getRootTaskCount();
-            numStacks = getRootTaskCount();
+            i -= numRootTasks - mChildren.size();
+            numRootTasks = mChildren.size();
         }
-        if (lastReparentedStack != null && splitScreenActivated) {
-            if (!lastReparentedStack.supportsSplitScreenWindowingMode()) {
+        if (lastReparentedRootTask != null && splitScreenActivated) {
+            if (!lastReparentedRootTask.supportsSplitScreenWindowingMode()) {
                 mAtmService.getTaskChangeNotificationController()
                         .notifyActivityDismissingDockedStack();
-                toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack);
-            } else if (rootStack != null) {
+                toDisplayArea.onSplitScreenModeDismissed(lastReparentedRootTask);
+            } else if (splitScreenRoot != null) {
                 // update focus
-                rootStack.moveToFront("display-removed");
+                splitScreenRoot.moveToFront("display-removed");
             }
         }
 
         mRemoved = true;
 
-        return lastReparentedStack;
+        return lastReparentedRootTask;
     }
 
     /** Whether this task display area can request orientation. */
@@ -1950,8 +2069,13 @@
         }
         final String triplePrefix = doublePrefix + "  ";
         pw.println(doublePrefix + "Application tokens in top down Z order:");
-        for (int rootTaskNdx = getChildCount() - 1; rootTaskNdx >= 0; --rootTaskNdx) {
-            final Task rootTask = getChildAt(rootTaskNdx);
+        for (int index = getChildCount() - 1; index >= 0; --index) {
+            final WindowContainer child = getChildAt(index);
+            if (child.asTaskDisplayArea() != null) {
+                child.dump(pw, doublePrefix, dumpAll);
+                continue;
+            }
+            final Task rootTask = child.asTask();
             pw.println(doublePrefix + "* " + rootTask);
             rootTask.dump(pw, triplePrefix, dumpAll);
         }
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 9d36b84..12f8611 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -95,30 +95,22 @@
         mSupervisor = supervisor;
     }
 
-    @VisibleForTesting
-    int onCalculate(Task task, ActivityInfo.WindowLayout layout, ActivityRecord activity,
-            ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
-            LaunchParams outParams) {
-        return onCalculate(task, layout, activity, source, options, PHASE_BOUNDS, currentParams,
-                outParams, null);
-    }
-
     @Override
-    public int onCalculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout,
-            @NonNull ActivityRecord activity, @Nullable ActivityRecord source,
-            ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams,
-            @Nullable Request request) {
+    public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
+            @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+            @Nullable ActivityOptions options, @Nullable Request request, int phase,
+            LaunchParams currentParams, LaunchParams outParams) {
         initLogBuilder(task, activity);
-        final int result = calculate(task, layout, activity, source, options, phase, currentParams,
-                outParams, request);
+        final int result = calculate(task, layout, activity, source, options, request, phase,
+                currentParams, outParams);
         outputLog();
         return result;
     }
 
-    private int calculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout,
-            @NonNull ActivityRecord activity, @Nullable ActivityRecord source,
-            ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams,
-            @Nullable Request request) {
+    private int calculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
+            @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+            @Nullable ActivityOptions options, @Nullable Request request, int phase,
+            LaunchParams currentParams, LaunchParams outParams) {
         final ActivityRecord root;
         if (task != null) {
             root = task.getRootActivity() == null ? activity : task.getRootActivity();
@@ -126,10 +118,6 @@
             root = activity;
         }
 
-        // TODO: Investigate whether we can safely ignore all cases where we don't have root
-        // activity available. Note we can't know if the bounds are valid if we're not sure of the
-        // requested orientation of the root activity. Therefore if we found such a case we may need
-        // to pass the activity into this modifier in that case.
         if (root == null) {
             // There is a case that can lead us here. The caller is moving the top activity that is
             // in a task that has multiple activities to PIP mode. For that the caller is creating a
@@ -795,17 +783,13 @@
     private void adjustBoundsToAvoidConflictInDisplay(@NonNull DisplayContent display,
             @NonNull Rect inOutBounds) {
         final List<Rect> taskBoundsToCheck = new ArrayList<>();
-        display.forAllTaskDisplayAreas(taskDisplayArea -> {
-            int numStacks = taskDisplayArea.getRootTaskCount();
-            for (int sNdx = 0; sNdx < numStacks; ++sNdx) {
-                final Task task = taskDisplayArea.getRootTaskAt(sNdx);
-                if (!task.inFreeformWindowingMode()) {
-                    continue;
-                }
+        display.forAllRootTasks(task -> {
+            if (!task.inFreeformWindowingMode()) {
+                return;
+            }
 
-                for (int j = 0; j < task.getChildCount(); ++j) {
-                    taskBoundsToCheck.add(task.getChildAt(j).getBounds());
-                }
+            for (int j = 0; j < task.getChildCount(); ++j) {
+                taskBoundsToCheck.add(task.getChildAt(j).getBounds());
             }
         }, false /* traverseTopToBottom */);
         adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index e635219..929d7bf 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
 import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
 
@@ -38,6 +39,7 @@
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
+import android.window.StartingWindowInfo;
 import android.window.TaskAppearedInfo;
 import android.window.WindowContainerToken;
 
@@ -115,10 +117,10 @@
         }
 
         void addStartingWindow(Task task, IBinder appToken) {
-            final RunningTaskInfo taskInfo = task.getTaskInfo();
+            final StartingWindowInfo info = task.getStartingWindowInfo();
             mDeferTaskOrgCallbacksConsumer.accept(() -> {
                 try {
-                    mTaskOrganizer.addStartingWindow(taskInfo, appToken);
+                    mTaskOrganizer.addStartingWindow(info, appToken);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Exception sending onTaskStart callback", e);
                 }
@@ -126,10 +128,9 @@
         }
 
         void removeStartingWindow(Task task) {
-            final RunningTaskInfo taskInfo = task.getTaskInfo();
             mDeferTaskOrgCallbacksConsumer.accept(() -> {
                 try {
-                    mTaskOrganizer.removeStartingWindow(taskInfo);
+                    mTaskOrganizer.removeStartingWindow(task.mTaskId);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Exception sending onStartTaskFinished callback", e);
                 }
@@ -272,7 +273,9 @@
 
         void removeTask(Task t) {
             if (t.mTaskAppearedSent) {
-                t.migrateToNewSurfaceControl();
+                if (t.getSurfaceControl() != null) {
+                    t.migrateToNewSurfaceControl();
+                }
                 t.mTaskAppearedSent = false;
                 mOrganizer.onTaskVanished(t);
             }
@@ -288,8 +291,7 @@
             // possible.
             while (!mOrganizedTasks.isEmpty()) {
                 final Task t = mOrganizedTasks.get(0);
-                t.updateTaskOrganizerState(true /* forceUpdate */);
-                if (mOrganizedTasks.contains(t)) {
+                if (!t.updateTaskOrganizerState(true /* forceUpdate */)) {
                     removeTask(t);
                 }
             }
@@ -579,11 +581,11 @@
             synchronized (mGlobalLock) {
                 DisplayContent dc = mService.mWindowManager.mRoot
                         .getDisplayContent(displayId);
-                if (dc == null || dc.mInputMethodTarget == null) {
+                if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) {
                     return null;
                 }
                 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task.
-                final Task task = dc.mInputMethodTarget.getTask();
+                final Task task = dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getTask();
                 if (task == null) {
                     return null;
                 }
@@ -686,16 +688,13 @@
                 if (dc == null) {
                     throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
                 }
-                ArrayList<RunningTaskInfo> out = new ArrayList<>();
-                dc.forAllTaskDisplayAreas(taskDisplayArea -> {
-                    for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                        final Task task = taskDisplayArea.getRootTaskAt(sNdx);
-                        if (activityTypes != null
-                                && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
-                            continue;
-                        }
-                        out.add(task.getTaskInfo());
+                final ArrayList<RunningTaskInfo> out = new ArrayList<>();
+                dc.forAllRootTasks(task -> {
+                    if (activityTypes != null
+                            && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
+                        return;
                     }
+                    out.add(task.getTaskInfo());
                 });
                 return out;
             }
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 3def091..1779d2a 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -60,7 +60,7 @@
             surface.attachAndQueueBufferWithColorSpace(buffer, screenshotBuffer.getColorSpace());
             surface.release();
             final float scale = 1.0f * mTask.getBounds().width() / mWidth;
-            mSurfaceControl.setMatrix(scale, 0, 0, scale);
+            getPendingTransaction().setMatrix(mSurfaceControl, scale, 0, 0, scale);
         }
         getPendingTransaction().show(mSurfaceControl);
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 0edfaa8..3c437ba 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.util.ArrayMap;
 
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 616a789..de9fb6a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -24,7 +24,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.PixelFormat;
@@ -219,7 +219,8 @@
      * Retrieves a snapshot. If {@param restoreFromDisk} equals {@code true}, DO NOT HOLD THE WINDOW
      * MANAGER LOCK WHEN CALLING THIS METHOD!
      */
-    @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk,
+    @Nullable
+    TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk,
             boolean isLowResolution) {
         return mCache.getSnapshot(taskId, userId, restoreFromDisk, isLowResolution
                 && mPersister.enableLowResSnapshots());
@@ -369,7 +370,8 @@
         SurfaceControl[] excludeLayers;
         final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
         // Exclude IME window snapshot when IME isn't proper to attach to app.
-        if (imeWindow != null && !task.getDisplayContent().isImeAttachedToApp()) {
+        if (imeWindow != null && imeWindow.getSurfaceControl() != null
+                && !task.getDisplayContent().isImeAttachedToApp()) {
             excludeLayers = new SurfaceControl[1];
             excludeLayers[0] = imeWindow.getSurfaceControl();
         } else {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 9717e7e..cfdb6b3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -20,7 +20,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.ComponentName;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 6dfcb41..60c4766 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -23,7 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.os.Process;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index d2cd1a1..8c458a2 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -49,7 +49,6 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -78,6 +77,7 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.window.ClientWindowFrames;
+import android.window.TaskSnapshot;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -100,7 +100,7 @@
      * with a window with the exact same dimensions etc. However, these flags are not used in layout
      * and might cause other side effects so we exclude them.
      */
-    private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+    static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
             | FLAG_NOT_TOUCHABLE
             | FLAG_NOT_TOUCH_MODAL
             | FLAG_ALT_FOCUSABLE_IM
@@ -180,34 +180,10 @@
         synchronized (service.mGlobalLock) {
             final WindowState mainWindow = activity.findMainWindow();
             final Task task = activity.getTask();
-            if (task == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
-                        + activity);
-                return null;
-            }
             final ActivityRecord topFullscreenActivity =
                     activity.getTask().getTopFullscreenActivity();
-            if (topFullscreenActivity == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
-                        + task);
-                return null;
-            }
+            // Already check the nullity in StartingSurfaceController#createTaskSnapshotSurface
             topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
-            if (mainWindow == null || topFullscreenOpaqueWindow == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
-                        + activity);
-                return null;
-            }
-            if (topFullscreenActivity.getWindowConfiguration().getRotation()
-                    != snapshot.getRotation()) {
-                // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
-                // that the activity will be updated to the same rotation as the snapshot. Since
-                // the transition is not started yet, fixed rotation transform needs to be applied
-                // earlier to make the snapshot show in a rotated container.
-                activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
-                        topFullscreenActivity, false /* checkOpening */);
-            }
-
             WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
             appearance = attrs.insetsFlags.appearance;
             windowFlags = attrs.flags;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 0cdd055..14504d8 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -18,11 +18,18 @@
 
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -282,9 +289,13 @@
         mState = STATE_PLAYING;
         mController.moveToPlaying(this);
 
+        if (mController.mAtm.mTaskSupervisor.getKeyguardController().isKeyguardLocked()) {
+            mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
+        }
+
         // Resolve the animating targets from the participants
         mTargets = calculateTargets(mParticipants, mChanges);
-        final TransitionInfo info = calculateTransitionInfo(mType, mTargets, mChanges);
+        final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, mChanges);
         mRootLeash = info.getRootLeash();
 
         handleNonAppWindowsInTransition(displayId, mType, mFlags);
@@ -337,6 +348,9 @@
             mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation(
                     SystemClock.uptimeMillis(), 0 /* duration */);
         }
+        if ((flags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) {
+            mController.mAtm.mWindowManager.mPolicy.applyKeyguardOcclusionChange();
+        }
     }
 
     @Override
@@ -389,7 +403,7 @@
                     parent == null ? "no parent" : ("parent can't be target " + parent));
             return false;
         }
-        @TransitionInfo.TransitionMode int mode = TransitionInfo.TRANSIT_NONE;
+        @TransitionInfo.TransitionMode int mode = TRANSIT_NONE;
         // Go through all siblings of this target to see if any of them would prevent
         // the target from promoting.
         siblingLoop:
@@ -403,11 +417,11 @@
                 if (depth < 0) continue;
                 if (depth == 0) {
                     final int siblingMode = sibling.isVisibleRequested()
-                            ? TransitionInfo.TRANSIT_OPEN : TransitionInfo.TRANSIT_CLOSE;
+                            ? TRANSIT_OPEN : TRANSIT_CLOSE;
                     ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                             "        sibling is a top target with mode %s",
                             TransitionInfo.modeToString(siblingMode));
-                    if (mode == TransitionInfo.TRANSIT_NONE) {
+                    if (mode == TRANSIT_NONE) {
                         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                                 "          no common mode yet, so set it");
                         mode = siblingMode;
@@ -587,9 +601,9 @@
      */
     @VisibleForTesting
     @NonNull
-    static TransitionInfo calculateTransitionInfo(int type, ArraySet<WindowContainer> targets,
-            ArrayMap<WindowContainer, ChangeInfo> changes) {
-        final TransitionInfo out = new TransitionInfo(type);
+    static TransitionInfo calculateTransitionInfo(int type, int flags,
+            ArraySet<WindowContainer> targets, ArrayMap<WindowContainer, ChangeInfo> changes) {
+        final TransitionInfo out = new TransitionInfo(type, flags);
         if (targets.isEmpty()) {
             out.setRootLeash(new SurfaceControl(), 0, 0);
             return out;
@@ -693,12 +707,12 @@
         int getTransitMode(@NonNull WindowContainer wc) {
             final boolean nowVisible = wc.isVisibleRequested();
             if (nowVisible == mVisible) {
-                return TransitionInfo.TRANSIT_CHANGE;
+                return TRANSIT_CHANGE;
             }
             if (mExistenceChanged) {
-                return nowVisible ? TransitionInfo.TRANSIT_OPEN : TransitionInfo.TRANSIT_CLOSE;
+                return nowVisible ? TRANSIT_OPEN : TRANSIT_CLOSE;
             } else {
-                return nowVisible ? TransitionInfo.TRANSIT_SHOW : TransitionInfo.TRANSIT_HIDE;
+                return nowVisible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK;
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index adc7a22..6e0fec1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1664,6 +1664,39 @@
     }
 
     /**
+     * For all root tasks at or below this container call the callback.
+     *
+     * @param callback Calls the {@link ToBooleanFunction#apply} method for each root task found and
+     *                 stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
+     */
+    boolean forAllRootTasks(Function<Task, Boolean> callback) {
+        return forAllRootTasks(callback, true /* traverseTopToBottom */);
+    }
+
+    boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) {
+        int count = mChildren.size();
+        if (traverseTopToBottom) {
+            for (int i = count - 1; i >= 0; --i) {
+                if (mChildren.get(i).forAllRootTasks(callback)) {
+                    return true;
+                }
+            }
+        } else {
+            for (int i = 0; i < count; i++) {
+                if (mChildren.get(i).forAllRootTasks(callback)) {
+                    return true;
+                }
+                // Root tasks may be removed from this display. Ensure each task will be processed
+                // and the loop will end.
+                int newCount = mChildren.size();
+                i -= count - newCount;
+                count = newCount;
+            }
+        }
+        return false;
+    }
+
+    /**
      * For all tasks at or below this container call the callback.
      *
      * @param callback Callback to be called for every task.
@@ -1698,6 +1731,33 @@
         }
     }
 
+    /**
+     * For all root tasks at or below this container call the callback.
+     *
+     * @param callback Callback to be called for every root task.
+     */
+    void forAllRootTasks(Consumer<Task> callback) {
+        forAllRootTasks(callback, true /* traverseTopToBottom */);
+    }
+
+    void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
+        int count = mChildren.size();
+        if (traverseTopToBottom) {
+            for (int i = count - 1; i >= 0; --i) {
+                mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom);
+            }
+        } else {
+            for (int i = 0; i < count; i++) {
+                mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom);
+                // Root tasks may be removed from this display. Ensure each task will be processed
+                // and the loop will end.
+                int newCount = mChildren.size();
+                i -= count - newCount;
+                count = newCount;
+            }
+        }
+    }
+
     Task getTaskAbove(Task t) {
         return getTask(
                 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
@@ -1780,6 +1840,44 @@
         return null;
     }
 
+    /**
+     * Gets a root task in a branch of the tree.
+     *
+     * @param callback called to test if this is the task that should be returned.
+     * @return The root task if found or null.
+     */
+    @Nullable
+    Task getRootTask(Predicate<Task> callback) {
+        return getRootTask(callback, true /*traverseTopToBottom*/);
+    }
+
+    @Nullable
+    Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) {
+        int count = mChildren.size();
+        if (traverseTopToBottom) {
+            for (int i = count - 1; i >= 0; --i) {
+                final Task t = mChildren.get(i).getRootTask(callback, traverseTopToBottom);
+                if (t != null) {
+                    return t;
+                }
+            }
+        } else {
+            for (int i = 0; i < count; i++) {
+                final Task t = mChildren.get(i).getRootTask(callback, traverseTopToBottom);
+                if (t != null) {
+                    return t;
+                }
+                // Root tasks may be removed from this display. Ensure each task will be processed
+                // and the loop will end.
+                int newCount = mChildren.size();
+                i -= count - newCount;
+                count = newCount;
+            }
+        }
+
+        return null;
+    }
+
     private Task processGetTaskWithBoundary(Predicate<Task> callback,
             WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
             boolean[] boundaryFound, WindowContainer wc) {
@@ -1973,6 +2071,47 @@
     }
 
     /**
+     * Finds the first non {@code null} return value from calling the callback on all root
+     * {@link Task} at or below this container.
+     * @param callback Applies on each root {@link Task} found and stops the search if it
+     *                 returns non {@code null}.
+     * @param traverseTopToBottom If {@code true}, traverses the hierarchy from top-to-bottom in
+     *                            terms of z-order, else from bottom-to-top.
+     * @return the first returned object that is not {@code null}. Returns {@code null} if not
+     *         found.
+     */
+    @Nullable
+    <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) {
+        int count = mChildren.size();
+        if (traverseTopToBottom) {
+            for (int i = count - 1; i >= 0; --i) {
+                R result = (R) mChildren.get(i).getItemFromRootTasks(callback, traverseTopToBottom);
+                if (result != null) {
+                    return result;
+                }
+            }
+        } else {
+            for (int i = 0; i < count; i++) {
+                R result = (R) mChildren.get(i).getItemFromRootTasks(callback, traverseTopToBottom);
+                if (result != null) {
+                    return result;
+                }
+                // Root tasks may be removed from this display. Ensure each task will be processed
+                // and the loop will end.
+                int newCount = mChildren.size();
+                i -= count - newCount;
+                count = newCount;
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    <R> R getItemFromRootTasks(Function<Task, R> callback) {
+        return getItemFromRootTasks(callback, true /* traverseTopToBottom */);
+    }
+
+    /**
      * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
      * the input container in terms of z-order.
      */
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8fd342c..1f3d15a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -48,6 +48,7 @@
 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.SurfaceControl.getGlobalTransaction;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -104,6 +105,9 @@
 import static com.android.server.LockGuard.INDEX_WINDOW;
 import static com.android.server.LockGuard.installLock;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
+import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -136,7 +140,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
@@ -1036,7 +1040,7 @@
 
     private WindowContentFrameStats mTempWindowRenderStats;
 
-    private final LatencyTracker mLatencyTracker;
+    final LatencyTracker mLatencyTracker;
 
     /**
      * Whether the UI is currently running in touch mode (not showing
@@ -1120,18 +1124,16 @@
             // While running a recents animation, this will get called early because we show the
             // recents animation target activity immediately when the animation starts. Defer the
             // mLaunchTaskBehind updates until recents animation finishes.
-            final boolean isRecentsAnimationTarget = getRecentsAnimationController() != null
-                    && getRecentsAnimationController().isTargetApp(atoken);
-            if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget) {
+            if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget(atoken)) {
                 mAtmService.mTaskSupervisor.scheduleLaunchTaskBehindComplete(atoken.token);
                 atoken.mLaunchTaskBehind = false;
             } else {
                 atoken.updateReportedVisibilityLocked();
                 // We should also defer sending the finished callback until the recents animation
                 // successfully finishes.
-                if (atoken.mEnteringAnimation && !isRecentsAnimationTarget) {
+                if (atoken.mEnteringAnimation && !isRecentsAnimationTarget(atoken)) {
                     atoken.mEnteringAnimation = false;
-                    if (atoken != null && atoken.attachedToProcess()) {
+                    if (atoken.attachedToProcess()) {
                         try {
                             atoken.app.getThread().scheduleEnterAnimationComplete(atoken.appToken);
                         } catch (RemoteException e) {
@@ -2557,7 +2559,7 @@
         // side child surfaces, so they will remain preserved in their current state
         // (rather than be cleaned up immediately by the app code).
         SurfaceControl.openTransaction();
-        winAnimator.detachChildren();
+        winAnimator.detachChildren(getGlobalTransaction());
         SurfaceControl.closeTransaction();
 
         return focusMayChange;
@@ -2968,6 +2970,10 @@
         }
     }
 
+    boolean isRecentsAnimationTarget(ActivityRecord r) {
+        return mRecentsAnimationController != null && mRecentsAnimationController.isTargetApp(r);
+    }
+
     void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
         final ActivityRecord wtoken = mRoot.getActivityRecord(token);
         if (wtoken != null) {
@@ -5349,7 +5355,7 @@
     void destroyPreservedSurfaceLocked() {
         for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
             final WindowState w = mDestroyPreservedSurface.get(i);
-            w.mWinAnimator.destroyPreservedSurfaceLocked();
+            w.mWinAnimator.destroyPreservedSurfaceLocked(w.getSyncTransaction());
         }
         mDestroyPreservedSurface.clear();
     }
@@ -6321,20 +6327,20 @@
         mRoot.dumpTopFocusedDisplayId(pw);
         mRoot.forAllDisplays(dc -> {
             final int displayId = dc.getDisplayId();
-            final WindowState inputMethodTarget = dc.mInputMethodTarget;
-            final WindowState inputMethodInputTarget = dc.mInputMethodInputTarget;
-            final InsetsControlTarget inputMethodControlTarget = dc.mInputMethodControlTarget;
-            if (inputMethodTarget != null) {
-                pw.print("  mInputMethodTarget in display# "); pw.print(displayId);
-                pw.print(' '); pw.println(inputMethodTarget);
+            final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING);
+            final InsetsControlTarget imeInputTarget = dc.getImeTarget(IME_TARGET_INPUT);
+            final InsetsControlTarget imeControlTarget = dc.getImeTarget(IME_TARGET_CONTROL);
+            if (imeLayeringTarget != null) {
+                pw.print("  imeLayeringTarget in display# "); pw.print(displayId);
+                pw.print(' '); pw.println(imeLayeringTarget);
             }
-            if (inputMethodInputTarget != null) {
-                pw.print("  mInputMethodInputTarget in display# "); pw.print(displayId);
-                pw.print(' '); pw.println(inputMethodInputTarget);
+            if (imeInputTarget != null) {
+                pw.print("  imeInputTarget in display# "); pw.print(displayId);
+                pw.print(' '); pw.println(imeInputTarget);
             }
-            if (inputMethodControlTarget != null) {
-                pw.print("  inputMethodControlTarget in display# "); pw.print(displayId);
-                pw.print(' '); pw.println(inputMethodControlTarget);
+            if (imeControlTarget != null) {
+                pw.print("  imeControlTarget in display# "); pw.print(displayId);
+                pw.print(' '); pw.println(imeControlTarget);
             }
         });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
@@ -7391,9 +7397,6 @@
                     throw new IllegalStateException("Magnification callbacks not set!");
                 }
             }
-            if (Binder.getCallingPid() != myPid()) {
-                spec.recycle();
-            }
         }
 
         @Override
@@ -7433,7 +7436,10 @@
                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
                     return null;
                 }
-                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
+                MagnificationSpec result = new MagnificationSpec();
+                if (spec != null) {
+                    result.setTo(spec);
+                }
                 spec.scale *= windowState.mGlobalScale;
                 return spec;
             }
@@ -7629,7 +7635,7 @@
             synchronized (mGlobalLock) {
                 final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
                 if (imeTarget != null) {
-                    imeTarget.getDisplayContent().setInputMethodInputTarget(imeTarget);
+                    imeTarget.getDisplayContent().updateImeInputAndControlTarget(imeTarget);
                 }
             }
         }
@@ -7772,10 +7778,10 @@
                     // requested to be hidden.
                     dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
                 }
-                if (dc != null && dc.mInputMethodControlTarget != null) {
+                if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) {
                     ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ",
-                            dc.mInputMethodControlTarget);
-                    dc.mInputMethodControlTarget.hideInsets(
+                            dc.getImeTarget(IME_TARGET_CONTROL));
+                    dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(
                             WindowInsets.Type.ime(), true /* fromIme */);
                 }
                 if (dc != null) {
@@ -7899,7 +7905,7 @@
                 if (dc == null) {
                     return null;
                 }
-                final InsetsControlTarget target = dc.mInputMethodControlTarget;
+                final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_CONTROL);
                 if (target == null) {
                     return null;
                 }
@@ -7912,10 +7918,10 @@
         public String getImeTargetNameForLogging(int displayId) {
             synchronized (mGlobalLock) {
                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
-                if (dc == null) {
+                if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) {
                     return null;
                 }
-                return dc.mInputMethodTarget != null ? dc.mInputMethodTarget.getName() : null;
+                return dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getName();
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 8f8fea3..835e803 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -463,6 +463,10 @@
         return mUsingWrapper;
     }
 
+    boolean hasEverLaunchedActivity() {
+        return mLastActivityLaunchTime > 0;
+    }
+
     void setLastActivityLaunchTime(long launchTime) {
         if (launchTime <= mLastActivityLaunchTime) {
             if (launchTime < mLastActivityLaunchTime) {
@@ -815,9 +819,9 @@
         if (canUpdate) {
             // Make sure the previous top activity in the process no longer be resumed.
             if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) {
-                final Task stack = mPreQTopResumedActivity.getRootTask();
-                if (stack != null) {
-                    stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
+                final Task task = mPreQTopResumedActivity.getTask();
+                if (task != null) {
+                    task.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
                             activity, "top-resumed-changed");
                 }
             }
@@ -1282,12 +1286,12 @@
                 hasVisibleActivities = true;
             }
 
-            final Task rootTask = r.getRootTask();
-            if (rootTask != null) {
+            final Task task = r.getTask();
+            if (task != null) {
                 // There may be a pausing activity that hasn't shown any window and was requested
                 // to be hidden. But pausing is also a visible state, it should be regarded as
                 // visible, so the caller can know the next activity should be resumed.
-                hasVisibleActivities |= rootTask.handleAppDied(this);
+                hasVisibleActivities |= task.handleAppDied(this);
             }
             r.handleAppDied();
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bc8699e..4301072 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -32,6 +32,7 @@
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.SurfaceControl.Transaction;
+import static android.view.SurfaceControl.getGlobalTransaction;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
@@ -118,6 +119,8 @@
 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
 import static com.android.server.wm.AnimationSpecProto.MOVE;
+import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
@@ -617,6 +620,8 @@
     private final Rect mTmpRect = new Rect();
     private final Point mTmpPoint = new Point();
 
+    private final Transaction mTmpTransaction;
+
     /**
      * If a window is on a display which has been re-parented to a view in another window,
      * use this offset to indicate the correct location.
@@ -861,6 +866,7 @@
             int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
             PowerManagerWrapper powerManagerWrapper) {
         super(service);
+        mTmpTransaction = service.mTransactionFactory.get();
         mSession = s;
         mClient = c;
         mAppOp = appOp;
@@ -1108,9 +1114,10 @@
         final int layoutXDiff;
         final int layoutYDiff;
         final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
+        final InsetsControlTarget imeTarget = dc.getImeTarget(IME_TARGET_LAYERING);
         final boolean isInputMethodAdjustTarget = windowsAreFloating
-                ? dc.mInputMethodTarget != null && task == dc.mInputMethodTarget.getTask()
-                : isInputMethodTarget();
+                ? imeTarget != null && task == imeTarget.getWindow().getTask()
+                : isImeLayeringTarget();
         final boolean isImeTarget =
                 imeWin != null && imeWin.isVisibleNow() && isInputMethodAdjustTarget;
         if (isFullscreenAndFillsDisplay || layoutInParentFrame()) {
@@ -1447,9 +1454,9 @@
     @Override
     void onDisplayChanged(DisplayContent dc) {
         if (dc != null && mDisplayContent != null && dc != mDisplayContent
-                && mDisplayContent.mInputMethodInputTarget == this) {
-            dc.setInputMethodInputTarget(mDisplayContent.mInputMethodInputTarget);
-            mDisplayContent.mInputMethodInputTarget = null;
+                && getImeInputTarget() == this) {
+            dc.updateImeInputAndControlTarget(getImeInputTarget());
+            mDisplayContent.setImeInputTarget(null);
         }
         super.onDisplayChanged(dc);
         // Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
@@ -2154,14 +2161,14 @@
         }
 
         final DisplayContent dc = getDisplayContent();
-        if (isInputMethodTarget()) {
-            // Make sure to set mInputMethodTarget as null when the removed window is the IME
-            // target, in case computeImeTarget may use the outdated target.
-            dc.mInputMethodTarget = null;
+        if (isImeLayeringTarget()) {
+            // Make sure to set mImeLayeringTarget as null when the removed window is the
+            // IME target, in case computeImeTarget may use the outdated target.
+            dc.setImeLayeringTarget(null);
             dc.computeImeTarget(true /* updateImeTarget */);
         }
-        if (dc.mInputMethodInputTarget == this) {
-            dc.setInputMethodInputTarget(null);
+        if (dc.getImeTarget(IME_TARGET_INPUT) == this) {
+            dc.updateImeInputAndControlTarget(null);
         }
 
         final int type = mAttrs.type;
@@ -2176,8 +2183,9 @@
 
         disposeInputChannel();
 
-        mWinAnimator.destroyDeferredSurfaceLocked();
-        mWinAnimator.destroySurfaceLocked();
+        mWinAnimator.destroyDeferredSurfaceLocked(mTmpTransaction);
+        mWinAnimator.destroySurfaceLocked(mTmpTransaction);
+        mTmpTransaction.apply();
         mSession.windowRemovedLocked();
         try {
             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
@@ -2645,7 +2653,7 @@
                 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
             }
             if (!isVisibleByPolicy()) {
-                mWinAnimator.hide("checkPolicyVisibilityChange");
+                mWinAnimator.hide(getGlobalTransaction(), "checkPolicyVisibilityChange");
                 if (isFocused()) {
                     ProtoLog.i(WM_DEBUG_FOCUS_LIGHT,
                             "setAnimationLocked: setting mFocusMayChange true");
@@ -3176,10 +3184,10 @@
             // detaching any surface control the client added from the client.
             for (int i = mChildren.size() - 1; i >= 0; --i) {
                 final WindowState c = mChildren.get(i);
-                c.mWinAnimator.detachChildren();
+                c.mWinAnimator.detachChildren(getGlobalTransaction());
             }
 
-            mWinAnimator.detachChildren();
+            mWinAnimator.detachChildren(getGlobalTransaction());
         }
 
         try {
@@ -3238,7 +3246,8 @@
         }
 
         if (appStopped || mWindowRemovalAllowed) {
-            mWinAnimator.destroyPreservedSurfaceLocked();
+            mWinAnimator.destroyPreservedSurfaceLocked(mTmpTransaction);
+            mTmpTransaction.apply();
         }
 
         if (mDestroying) {
@@ -3274,7 +3283,8 @@
     // various indicators of whether the client has released the surface.
     // This is in general unsafe, and most callers should use {@link #destroySurface}
     void destroySurfaceUnchecked() {
-        mWinAnimator.destroySurfaceLocked();
+        mWinAnimator.destroySurfaceLocked(mTmpTransaction);
+        mTmpTransaction.apply();
 
         // Clear animating flags now, since the surface is now gone. (Note this is true even
         // if the surface is saved, to outside world the surface is still NO_SURFACE.)
@@ -3833,7 +3843,8 @@
         if (task == null) {
             return false;
         }
-        if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) {
+        if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()
+                && !task.getRootTask().mCreatedByOrganizer) {
             return false;
         }
         // TODO(157912944): formalize drag-resizing so that exceptions aren't hardcoded like this
@@ -4608,7 +4619,7 @@
         // directly above it. The exception is if we are in split screen
         // in which case we process the IME at the DisplayContent level to
         // ensure it is above the docked divider.
-        if (isInputMethodTarget() && !inSplitScreenWindowingMode()) {
+        if (isImeLayeringTarget() && !inSplitScreenWindowingMode()) {
             if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
                 return true;
             }
@@ -4800,7 +4811,7 @@
             c.hideWallpaperWindow(wasDeferred, reason);
         }
         if (!mWinAnimator.mLastHidden || wasDeferred) {
-            mWinAnimator.hide(reason);
+            mWinAnimator.hide(getGlobalTransaction(), reason);
             getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null;
             dispatchWallpaperVisibility(false);
             final DisplayContent displayContent = getDisplayContent();
@@ -4942,7 +4953,7 @@
             // on the new one. This prevents blinking when we change elevation of freeform and
             // pinned windows.
             if (!mWinAnimator.tryChangeFormatInPlaceLocked()) {
-                mWinAnimator.preserveSurfaceLocked(getPendingTransaction());
+                mWinAnimator.preserveSurfaceLocked(getSyncTransaction());
                 result |= RELAYOUT_RES_SURFACE_CHANGED
                         | RELAYOUT_RES_FIRST_TIME;
                 scheduleAnimation();
@@ -4961,7 +4972,7 @@
             // to preserve and destroy windows which are attached to another, they
             // will keep their surface and its size may change over time.
             if (mHasSurface && !isChildWindow()) {
-                mWinAnimator.preserveSurfaceLocked(getPendingTransaction());
+                mWinAnimator.preserveSurfaceLocked(getSyncTransaction());
                 result |= RELAYOUT_RES_SURFACE_CHANGED |
                     RELAYOUT_RES_FIRST_TIME;
                 scheduleAnimation();
@@ -5204,9 +5215,9 @@
 
     @Override
     boolean needsZBoost() {
-        final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
-        if (mIsImWindow && inputMethodTarget != null) {
-            final ActivityRecord activity = inputMethodTarget.mActivityRecord;
+        final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING);
+        if (mIsImWindow && target != null) {
+            final ActivityRecord activity = target.getWindow().mActivityRecord;
             if (activity != null) {
                 return activity.needsZBoost();
             }
@@ -5218,14 +5229,17 @@
         if (!mAnimatingExit && mAppDied) {
             mIsDimming = true;
             getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
-        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
-            // Only show a dim behind when the following is satisfied:
-            // 1. The window has the flag FLAG_DIM_BEHIND
+        } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || mAttrs.backgroundBlurRadius != 0)
+                   && isVisibleNow() && !mHidden) {
+            // Only show the Dimmer when the following is satisfied:
+            // 1. The window has the flag FLAG_DIM_BEHIND or background blur is requested
             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
             // 3. The WS is considered visible according to the isVisible() method
             // 4. The WS is not hidden.
             mIsDimming = true;
-            getDimmer().dimBelow(getSyncTransaction(), this, mAttrs.dimAmount);
+            final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
+            getDimmer().dimBelow(
+                    getSyncTransaction(), this, mAttrs.dimAmount, mAttrs.backgroundBlurRadius);
         }
     }
 
@@ -5264,7 +5278,7 @@
         updateFrameRateSelectionPriorityIfNeeded();
         updateGlobalScaleIfNeeded();
 
-        mWinAnimator.prepareSurfaceLocked(SurfaceControl.getGlobalTransaction(), true);
+        mWinAnimator.prepareSurfaceLocked(getSyncTransaction());
         super.prepareSurfaces();
     }
 
@@ -5358,14 +5372,14 @@
 
         if (isChildWindow()) {
             // If we are a child of the input method target we need this promotion.
-            if (getParentWindow().isInputMethodTarget()) {
+            if (getParentWindow().isImeLayeringTarget()) {
                 return true;
             }
         } else if (mActivityRecord != null) {
             // Likewise if we share a token with the Input method target and are ordered
             // above it but not necessarily a child (e.g. a Dialog) then we also need
             // this promotion.
-            final WindowState imeTarget = getDisplayContent().mInputMethodTarget;
+            final WindowState imeTarget = getImeLayeringTarget();
             boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
                     && imeTarget.mToken == mToken
                     && mAttrs.type != TYPE_APPLICATION_STARTING
@@ -5492,8 +5506,18 @@
         return !mTapExcludeRegion.isEmpty();
     }
 
-    boolean isInputMethodTarget() {
-        return getDisplayContent().mInputMethodTarget == this;
+    boolean isImeLayeringTarget() {
+        return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this;
+    }
+
+    WindowState getImeLayeringTarget() {
+        final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING);
+        return target != null ? target.getWindow() : null;
+    }
+
+    WindowState getImeInputTarget() {
+        final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_INPUT);
+        return target != null ? target.getWindow() : null;
     }
 
     long getFrameNumber() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9cc72a2..585db1e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -57,7 +57,6 @@
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Debug;
@@ -130,10 +129,6 @@
     float mAlpha = 0;
     float mLastAlpha = 0;
 
-    Rect mTmpStackBounds = new Rect();
-    private Rect mTmpAnimatingBounds = new Rect();
-    private Rect mTmpSourceBounds = new Rect();
-
     /**
      * This is rectangle of the window's surface that is not covered by
      * system decorations.
@@ -154,8 +149,6 @@
      * window is first added or shown, cleared when the callback has been made. */
     boolean mEnteringAnimation;
 
-    private final SurfaceControl.Transaction mTmpTransaction;
-
     /** The pixel format of the underlying SurfaceControl */
     int mSurfaceFormat;
 
@@ -201,12 +194,6 @@
     // region.
     float mWallpaperScale = 1f;
 
-    /**
-     * A flag to determine if the WSA needs to offset its position to compensate for the stack's
-     * position update before the WSA surface has resized.
-     */
-    private boolean mOffsetPositionForStackResize;
-
     private final Rect mTmpSize = new Rect();
 
     /**
@@ -220,13 +207,10 @@
     private final SurfaceControl.Transaction mPostDrawTransaction =
             new SurfaceControl.Transaction();
 
-    private final Point mTmpPos = new Point();
-
     WindowStateAnimator(final WindowState win) {
         final WindowManagerService service = win.mWmService;
 
         mService = service;
-        mTmpTransaction = service.mTransactionFactory.get();
         mAnimator = service.mAnimator;
         mPolicy = service.mPolicy;
         mContext = service.mContext;
@@ -243,7 +227,7 @@
         if (DEBUG_ANIM) Slog.v(
                 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
                         + ", reportedVisible="
-                        + (mWin.mActivityRecord != null ? mWin.mActivityRecord.reportedVisible : false));
+                        + (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible));
 
         mWin.checkPolicyVisibilityChange();
         final DisplayContent displayContent = mWin.getDisplayContent();
@@ -284,11 +268,6 @@
         }
     }
 
-    void hide(String reason) {
-        hide(mTmpTransaction, reason);
-        SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
-    }
-
     boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) {
         final boolean startingWindow =
                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -362,7 +341,7 @@
                     mSurfaceController.mSurfaceControl,
                     mPendingDestroySurface.mSurfaceControl).apply();
             }
-            destroySurfaceLocked();
+            destroySurfaceLocked(t);
             mSurfaceDestroyDeferred = true;
             return;
         }
@@ -375,10 +354,10 @@
         }
         mDestroyPreservedSurfaceUponRedraw = true;
         mSurfaceDestroyDeferred = true;
-        destroySurfaceLocked();
+        destroySurfaceLocked(t);
     }
 
-    void destroyPreservedSurfaceLocked() {
+    void destroyPreservedSurfaceLocked(SurfaceControl.Transaction t) {
         if (!mDestroyPreservedSurfaceUponRedraw) {
             return;
         }
@@ -397,7 +376,7 @@
                     mSurfaceController.mSurfaceControl).apply();
         }
 
-        destroyDeferredSurfaceLocked();
+        destroyDeferredSurfaceLocked(t);
         mDestroyPreservedSurfaceUponRedraw = false;
     }
 
@@ -484,7 +463,6 @@
             mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
                     & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
 
-            setOffsetPositionForStackResize(false);
             mSurfaceFormat = format;
 
             w.setHasSurface(true);
@@ -529,7 +507,7 @@
         return mSurfaceController != null && mSurfaceController.hasSurface();
     }
 
-    void destroySurfaceLocked() {
+    void destroySurfaceLocked(SurfaceControl.Transaction t) {
         final ActivityRecord activity = mWin.mActivityRecord;
         if (activity != null) {
             if (mWin == activity.mStartingWindow) {
@@ -557,14 +535,14 @@
                     if (mPendingDestroySurface != null) {
                         ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s",
                                 mWin, new RuntimeException().fillInStackTrace());
-                        mPendingDestroySurface.destroyNotInTransaction();
+                        mPendingDestroySurface.destroy(t);
                     }
                     mPendingDestroySurface = mSurfaceController;
                 }
             } else {
                 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s",
                         mWin, new RuntimeException().fillInStackTrace());
-                destroySurface();
+                destroySurface(t);
             }
             // Don't hide wallpaper if we're deferring the surface destroy
             // because of a surface change.
@@ -587,12 +565,12 @@
         mDrawState = NO_SURFACE;
     }
 
-    void destroyDeferredSurfaceLocked() {
+    void destroyDeferredSurfaceLocked(SurfaceControl.Transaction t) {
         try {
             if (mPendingDestroySurface != null) {
                 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s",
                         mWin, new RuntimeException().fillInStackTrace());
-                mPendingDestroySurface.destroyNotInTransaction();
+                mPendingDestroySurface.destroy(t);
                 // Don't hide wallpaper if we're destroying a deferred surface
                 // after a surface mode change.
                 if (!mDestroyPreservedSurfaceUponRedraw) {
@@ -633,12 +611,11 @@
         mDsDy = 1;
     }
 
+    private boolean isInBlastSync() {
+        return mService.useBLASTSync() && mWin.useBLASTSync();
+    }
+
     private boolean shouldConsumeMainWindowSizeTransaction() {
-        // If we use BLASTSync we always consume the transaction when finishing
-        // the sync.
-        if (mService.useBLASTSync() && mWin.useBLASTSync()) {
-            return false;
-        }
         // We only consume the transaction when the client is calling relayout
         // because this is the only time we know the frameNumber will be valid
         // due to the client renderer being paused. Put otherwise, only when
@@ -655,93 +632,57 @@
         return true;
     }
 
-    void setSurfaceBoundariesLocked(SurfaceControl.Transaction t, final boolean recoveringMemory) {
+    void setSurfaceBoundariesLocked(SurfaceControl.Transaction t) {
         if (mSurfaceController == null) {
             return;
         }
 
         final WindowState w = mWin;
-        final LayoutParams attrs = mWin.getAttrs();
-        final Task task = w.getTask();
-
-        if (shouldConsumeMainWindowSizeTransaction()) {
-            t.deferTransactionUntil(task.getMainWindowSizeChangeTask().getSurfaceControl(),
-                mWin.getClientViewRootSurface(), mWin.getFrameNumber());
-            t.deferTransactionUntil(mSurfaceController.mSurfaceControl,
-                mWin.getClientViewRootSurface(), mWin.getFrameNumber());
-            t.merge(task.getMainWindowSizeChangeTransaction());
-            task.setMainWindowSizeChangeTransaction(null);
-        }
-
-        float surfaceWidth = mSurfaceController.getWidth();
-        float surfaceHeight = mSurfaceController.getHeight();
-
-        final Rect insets = attrs.surfaceInsets;
-
-        // getFrameNumber is only valid in the call-stack of relayoutWindow
-        // as this is the only-time we know the client renderer
-        // is paused.
-        final boolean relayout = !w.mRelayoutCalled || w.mInRelayout;
 
         if (!w.mSeamlesslyRotated) {
             // Used to offset the WSA when stack position changes before a resize.
             int xOffset = mXOffset;
             int yOffset = mYOffset;
-            if (mOffsetPositionForStackResize) {
-                if (relayout) {
-                    // Once a relayout is called, reset the offset back to 0 and defer
-                    // setting it until a new frame with the updated size. This ensures that
-                    // the WS position is reset (so the stack position is shown) at the same
-                    // time that the buffer size changes.
-                    setOffsetPositionForStackResize(false);
-                    t.deferTransactionUntil(mSurfaceController.mSurfaceControl,
-                        mWin.getClientViewRootSurface(), mWin.getFrameNumber());
-                } else {
-                    final Task stack = mWin.getRootTask();
-                    mTmpPos.x = 0;
-                    mTmpPos.y = 0;
-                    if (stack != null) {
-                        stack.getRelativePosition(mTmpPos);
-                    }
-                     xOffset = -mTmpPos.x;
-                    yOffset = -mTmpPos.y;
-                }
-            }
             if (!mIsWallpaper) {
-                mSurfaceController.setPosition(t, xOffset, yOffset, recoveringMemory);
-            } else {
-                setWallpaperPositionAndScale(t,
-                        xOffset, yOffset, mWallpaperScale, recoveringMemory);
-            }
-        }
-
-        if (!w.mSeamlesslyRotated) {
-            // Wallpaper is already updated above when calling setWallpaperPositionAndScale so
-            // we only need to consider the non-wallpaper case here.
-            if (!mIsWallpaper) {
+                mSurfaceController.setPosition(t, xOffset, yOffset);
+                // Wallpaper is already updated above when calling setWallpaperPositionAndScale so
+                // we only need to consider the non-wallpaper case here.
                 mSurfaceController.setMatrix(t,
-                    mDsDx * w.mHScale,
-                    mDtDx * w.mVScale,
-                    mDtDy * w.mHScale,
-                    mDsDy * w.mVScale, recoveringMemory);
+                        mDsDx * w.mHScale,
+                        mDtDx * w.mVScale,
+                        mDtDy * w.mHScale,
+                        mDsDy * w.mVScale);
+            } else {
+                setWallpaperPositionAndScale(t, xOffset, yOffset, mWallpaperScale);
             }
         }
-    }
 
-    /**
-     * Get rect of the task this window is currently in. If there is no task, rect will be set to
-     * empty.
-     */
-    void getContainerRect(Rect rect) {
-        final Task task = mWin.getTask();
-        if (task != null) {
-            task.getDimBounds(rect);
-        } else {
-            rect.left = rect.top = rect.right = rect.bottom = 0;
+        final Task task = w.getTask();
+        if (shouldConsumeMainWindowSizeTransaction()) {
+            if (isInBlastSync()) {
+                // If we're in a sync transaction, there's no need to call defer transaction.
+                // The sync transaction will contain the buffer so the bounds change transaction
+                // will only be applied with the buffer.
+                t.merge(task.getMainWindowSizeChangeTransaction());
+            } else {
+                // Use pending transaction here instead of the transaction passed in because we
+                // want to ensure the defer transaction is applied on the main transaction and
+                // not on the sync  transaction. This is because the sync transaction could
+                // contain the buffer and we'd defer the transaction that contains the buffer
+                // we're deferring on.
+                SurfaceControl.Transaction pendingTransaction = mWin.getPendingTransaction();
+                pendingTransaction.deferTransactionUntil(
+                        task.getMainWindowSizeChangeTask().getSurfaceControl(),
+                        mWin.getClientViewRootSurface(), mWin.getFrameNumber());
+                pendingTransaction.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+                        mWin.getClientViewRootSurface(), mWin.getFrameNumber());
+                pendingTransaction.merge(task.getMainWindowSizeChangeTransaction());
+            }
+            task.setMainWindowSizeChangeTransaction(null);
         }
     }
 
-    void prepareSurfaceLocked(SurfaceControl.Transaction t, final boolean recoveringMemory) {
+    void prepareSurfaceLocked(SurfaceControl.Transaction t) {
         final WindowState w = mWin;
         if (!hasSurface()) {
 
@@ -758,13 +699,13 @@
 
         computeShownFrameLocked();
 
-        setSurfaceBoundariesLocked(t, recoveringMemory);
+        setSurfaceBoundariesLocked(t);
 
         if (mIsWallpaper && !w.mWallpaperVisible) {
             // Wallpaper is no longer visible and there is no wp target => hide it.
-            hide("prepareSurfaceLocked");
+            hide(t, "prepareSurfaceLocked");
         } else if (w.isParentWindowHidden() || !w.isOnScreen()) {
-            hide("prepareSurfaceLocked");
+            hide(t, "prepareSurfaceLocked");
             mWallpaperControllerLocked.hideWallpapers(w);
 
             // If we are waiting for this window to handle an orientation change. If this window is
@@ -800,21 +741,20 @@
             boolean prepared = true;
 
             if (mIsWallpaper) {
-                setWallpaperPositionAndScale(t,
-                        mXOffset, mYOffset, mWallpaperScale, recoveringMemory);
+                setWallpaperPositionAndScale(t, mXOffset, mYOffset, mWallpaperScale);
             } else {
                 prepared =
-                    mSurfaceController.prepareToShowInTransaction(mShownAlpha,
+                    mSurfaceController.prepareToShowInTransaction(t, mShownAlpha,
                         mDsDx * w.mHScale,
                         mDtDx * w.mVScale,
                         mDtDy * w.mHScale,
-                        mDsDy * w.mVScale,
-                        recoveringMemory);
+                        mDsDy * w.mVScale
+                    );
             }
 
             if (prepared && mDrawState == HAS_DRAWN) {
                 if (mLastHidden) {
-                    if (showSurfaceRobustlyLocked()) {
+                    if (showSurfaceRobustlyLocked(t)) {
                         markPreservedSurfaceForDestroy();
                         mAnimator.requestRemovalOfReplacedWindows(w);
                         mLastHidden = false;
@@ -862,7 +802,6 @@
 
         if (displayed) {
             w.mToken.hasVisible = true;
-            mSurfaceController.setBackgroundBlurRadius(w.mAttrs.backgroundBlurRadius);
         }
     }
 
@@ -888,8 +827,7 @@
                     Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
                 }
                 mService.openSurfaceTransaction();
-                setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(),
-                    dx, dy, scale, false);
+                setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(), dx, dy, scale);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error positioning surface of " + mWin
                         + " pos=(" + dx + "," + dy + ")", e);
@@ -904,8 +842,8 @@
         return true;
     }
 
-    private void setWallpaperPositionAndScale(SurfaceControl.Transaction t,
-        int dx, int dy, float scale, boolean recoveringMemory) {
+    private void setWallpaperPositionAndScale(SurfaceControl.Transaction t, int dx, int dy,
+            float scale) {
         DisplayInfo displayInfo = mWin.getDisplayInfo();
         Matrix matrix = mWin.mTmpMatrix;
         matrix.setTranslate(dx, dy);
@@ -915,13 +853,12 @@
         matrix.reset();
 
         mSurfaceController.setPosition(t,mWin.mTmpMatrixArray[MTRANS_X],
-                mWin.mTmpMatrixArray[MTRANS_Y], recoveringMemory);
+                mWin.mTmpMatrixArray[MTRANS_Y]);
         mSurfaceController.setMatrix(t,
                 mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale,
                 mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale,
                 mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale,
-                mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale,
-                recoveringMemory);
+                mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale);
     }
 
     /**
@@ -974,8 +911,8 @@
      *
      * @return Returns true if the surface was successfully shown.
      */
-    private boolean showSurfaceRobustlyLocked() {
-        boolean shown = mSurfaceController.showRobustlyInTransaction();
+    private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
+        boolean shown = mSurfaceController.showRobustly(t);
         if (!shown)
             return false;
 
@@ -993,7 +930,7 @@
             }
         }
 
-        SurfaceControl.mergeToGlobalTransaction(mPostDrawTransaction);
+        t.merge(mPostDrawTransaction);
         return true;
     }
 
@@ -1163,10 +1100,6 @@
         return sb.toString();
     }
 
-    void reclaimSomeSurfaceMemory(String operation, boolean secure) {
-        mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure);
-    }
-
     boolean getShown() {
         if (mSurfaceController != null) {
             return mSurfaceController.getShown();
@@ -1174,10 +1107,10 @@
         return false;
     }
 
-    void destroySurface() {
+    void destroySurface(SurfaceControl.Transaction t) {
         try {
             if (mSurfaceController != null) {
-                mSurfaceController.destroyNotInTransaction();
+                mSurfaceController.destroy(t);
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception thrown when destroying surface " + this
@@ -1189,7 +1122,7 @@
         }
     }
 
-    void detachChildren() {
+    void detachChildren(SurfaceControl.Transaction t) {
 
         // Do not detach children of starting windows, as their lifecycle is well under control and
         // it may lead to issues in case we relaunch when we just added the starting window.
@@ -1197,14 +1130,10 @@
             return;
         }
         if (mSurfaceController != null) {
-            mSurfaceController.detachChildren();
+            mSurfaceController.detachChildren(t);
         }
     }
 
-    void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) {
-        mOffsetPositionForStackResize = offsetPositionForStackResize;
-    }
-
     SurfaceControl getSurfaceControl() {
         if (!hasSurface()) {
             return null;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index ec79c59..f59eba9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -20,6 +20,7 @@
 import static android.view.SurfaceControl.METADATA_OWNER_PID;
 import static android.view.SurfaceControl.METADATA_OWNER_UID;
 import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
+import static android.view.SurfaceControl.getGlobalTransaction;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
@@ -63,8 +64,6 @@
     private float mLastDsdy = 0;
     private float mLastDtdy = 1;
 
-    private int mLastBackgroundBlurRadius = 0;
-
     private float mSurfaceAlpha = 0;
 
     private int mSurfaceLayer = 0;
@@ -76,8 +75,6 @@
     private final int mWindowType;
     private final Session mWindowSession;
 
-    private final SurfaceControl.Transaction mTmpTransaction;
-
     // Used to track whether we have called detach children on the way to invisibility.
     boolean mChildrenDetached;
 
@@ -94,7 +91,6 @@
         final WindowState win = animator.mWin;
         mWindowType = windowType;
         mWindowSession = win.mSession;
-        mTmpTransaction = mService.mTransactionFactory.get();
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
         final SurfaceControl.Builder b = win.makeSurface()
@@ -120,18 +116,18 @@
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
-    void detachChildren() {
+    void detachChildren(SurfaceControl.Transaction t) {
         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SEVER CHILDREN");
         mChildrenDetached = true;
         if (mSurfaceControl != null) {
-            mSurfaceControl.detachChildren();
+            t.detachChildren(mSurfaceControl);
         }
     }
 
     void hide(SurfaceControl.Transaction transaction, String reason) {
         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title);
 
-        mAnimator.destroyPreservedSurfaceLocked();
+        mAnimator.destroyPreservedSurfaceLocked(transaction);
         if (mSurfaceShown) {
             hideSurface(transaction);
         }
@@ -149,12 +145,12 @@
         }
     }
 
-    void destroyNotInTransaction() {
+    void destroy(SurfaceControl.Transaction t) {
         ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
-                    "Destroying surface %s called by %s", this, Debug.getCallers(8));
+                "Destroying surface %s called by %s", this, Debug.getCallers(8));
         try {
             if (mSurfaceControl != null) {
-                mTmpTransaction.remove(mSurfaceControl).apply();
+                t.remove(mSurfaceControl);
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Error destroying surface in: " + this, e);
@@ -164,30 +160,22 @@
         }
     }
 
-    void setPosition(SurfaceControl.Transaction t, float left, float top,
-            boolean recoveringMemory) {
+    void setPosition(SurfaceControl.Transaction t, float left, float top) {
         final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
-        if (surfaceMoved) {
-            mSurfaceX = left;
-            mSurfaceY = top;
-
-            try {
-                ProtoLog.i(WM_SHOW_TRANSACTIONS,
-                        "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title);
-
-                t.setPosition(mSurfaceControl, left, top);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error positioning surface of " + this
-                        + " pos=(" + left + "," + top + ")", e);
-                if (!recoveringMemory) {
-                    mAnimator.reclaimSomeSurfaceMemory("position", true);
-                }
-            }
+        if (!surfaceMoved) {
+            return;
         }
+
+        mSurfaceX = left;
+        mSurfaceY = top;
+
+        ProtoLog.i(WM_SHOW_TRANSACTIONS,
+                "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title);
+
+        t.setPosition(mSurfaceControl, left, top);
     }
 
-    void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx,
-            float dtdy, float dsdy, boolean recoveringMemory) {
+    void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy) {
         final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx ||
                                       mLastDtdy != dtdy || mLastDsdy != dsdy;
         if (!matrixChanged) {
@@ -199,43 +187,24 @@
         mLastDtdy = dtdy;
         mLastDsdy = dsdy;
 
-        try {
-            ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s",
-                    dsdx, dtdx, dtdy, dsdy, title);
-            t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
-        } catch (RuntimeException e) {
-            // If something goes wrong with the surface (such
-            // as running out of memory), don't take down the
-            // entire system.
-            Slog.e(TAG, "Error setting matrix on surface surface" + title
-                    + " MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
-            if (!recoveringMemory) {
-                mAnimator.reclaimSomeSurfaceMemory("matrix", true);
-            }
-        }
+        ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s",
+                dsdx, dtdx, dtdy, dsdy, title);
+        t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
     }
 
-    boolean prepareToShowInTransaction(float alpha,
-            float dsdx, float dtdx, float dsdy,
-            float dtdy, boolean recoveringMemory) {
-        if (mSurfaceControl != null) {
-            try {
-                mSurfaceAlpha = alpha;
-                mSurfaceControl.setAlpha(alpha);
-                mLastDsdx = dsdx;
-                mLastDtdx = dtdx;
-                mLastDsdy = dsdy;
-                mLastDtdy = dtdy;
-                mSurfaceControl.setMatrix(
-                        dsdx, dtdx, dsdy, dtdy);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error updating surface in " + title, e);
-                if (!recoveringMemory) {
-                    mAnimator.reclaimSomeSurfaceMemory("update", true);
-                }
-                return false;
-            }
+    boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha, float dsdx,
+            float dtdx, float dsdy, float dtdy) {
+        if (mSurfaceControl == null) {
+            return false;
         }
+
+        mSurfaceAlpha = alpha;
+        t.setAlpha(mSurfaceControl, alpha);
+        mLastDsdx = dsdx;
+        mLastDtdx = dtdx;
+        mLastDsdy = dsdy;
+        mLastDtdy = dtdy;
+        t.setMatrix(mSurfaceControl, dsdx, dtdx, dsdy, dtdy);
         return true;
     }
 
@@ -247,7 +216,7 @@
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion");
         mService.openSurfaceTransaction();
         try {
-            mSurfaceControl.setTransparentRegionHint(region);
+            getGlobalTransaction().setTransparentRegionHint(mSurfaceControl, region);
         } finally {
             mService.closeSurfaceTransaction("setTransparentRegion");
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
@@ -264,33 +233,13 @@
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
         mService.openSurfaceTransaction();
         try {
-            mSurfaceControl.setOpaque(isOpaque);
+            getGlobalTransaction().setOpaque(mSurfaceControl, isOpaque);
         } finally {
             mService.closeSurfaceTransaction("setOpaqueLocked");
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
         }
     }
 
-    void setBackgroundBlurRadius(int radius) {
-        ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE backgroundBlur=%o: %s", radius, title);
-
-        if (mSurfaceControl == null || radius == mLastBackgroundBlurRadius) {
-            return;
-        }
-        mLastBackgroundBlurRadius = radius;
-
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setBackgroundBlurRadius");
-        mService.openSurfaceTransaction();
-        try {
-            mSurfaceControl.setBackgroundBlurRadius(radius);
-        } finally {
-            mService.closeSurfaceTransaction("setBackgroundBlurRadius");
-            if (SHOW_LIGHT_TRANSACTIONS) {
-                Slog.i(TAG, "<<< CLOSE TRANSACTION setBackgroundBlurRadius");
-            }
-        }
-    }
-
     void setSecure(boolean isSecure) {
         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title);
 
@@ -300,7 +249,7 @@
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked");
         mService.openSurfaceTransaction();
         try {
-            mSurfaceControl.setSecure(isSecure);
+            getGlobalTransaction().setSecure(mSurfaceControl, isSecure);
         } finally {
             mService.closeSurfaceTransaction("setSecure");
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked");
@@ -318,7 +267,7 @@
         }
         mService.openSurfaceTransaction();
         try {
-            mSurfaceControl.setColorSpaceAgnostic(agnostic);
+            getGlobalTransaction().setColorSpaceAgnostic(mSurfaceControl, agnostic);
         } finally {
             mService.closeSurfaceTransaction("setColorSpaceAgnostic");
             if (SHOW_LIGHT_TRANSACTIONS) {
@@ -327,7 +276,7 @@
         }
     }
 
-    boolean showRobustlyInTransaction() {
+    boolean showRobustly(SurfaceControl.Transaction t) {
         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
         if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
                 + " during relayout");
@@ -336,21 +285,9 @@
             return true;
         }
 
-        try {
-            setShown(true);
-            mSurfaceControl.show();
-            return true;
-        } catch (RuntimeException e) {
-            Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + this, e);
-        }
-
-        mAnimator.reclaimSomeSurfaceMemory("show", true);
-        return false;
-    }
-
-    void deferTransactionUntil(SurfaceControl barrier, long frame) {
-        // TODO: Logging
-        mSurfaceControl.deferTransactionUntil(barrier, frame);
+        setShown(true);
+        t.show(mSurfaceControl);
+        return true;
     }
 
     boolean clearWindowContentFrameStats() {
@@ -391,14 +328,6 @@
         }
     }
 
-    int getWidth() {
-        return mSurfaceW;
-    }
-
-    int getHeight() {
-        return mSurfaceH;
-    }
-
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(SHOWN, mSurfaceShown);
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 34875ed..9e0fee39 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -827,15 +827,15 @@
      * system bars, or in other words extend outside of the "Decor Frame"
      */
     boolean canLayerAboveSystemBars() {
-        int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
-                mOwnerCanManageAppTokens);
+        int layer = getWindowLayerFromType();
         int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
                 mOwnerCanManageAppTokens);
         return mOwnerCanManageAppTokens && (layer > navLayer);
     }
 
     int getWindowLayerFromType() {
-        return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens);
+        return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
+                mRoundedCornerOverlay);
     }
 
     int getOwnerUid() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d37c7b0..2c4eb1b 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -22,6 +22,9 @@
         "BroadcastRadio/convert.cpp",
         "BroadcastRadio/regions.cpp",
         "gnss/GnssConfiguration.cpp",
+        "gnss/GnssMeasurement.cpp",
+        "gnss/GnssMeasurementCallback.cpp",
+        "gnss/Utils.cpp",
         "stats/PowerStatsPuller.cpp",
         "stats/SubsystemSleepStatePuller.cpp",
         "com_android_server_adb_AdbDebuggingManager.cpp",
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 6f74885..7fc5565 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,3 +12,18 @@
 per-file com_android_server_HardwarePropertiesManagerService.cpp = michaelwr@google.com, santoscordon@google.com
 per-file com_android_server_power_PowerManagerService.* = michaelwr@google.com, santoscordon@google.com
 
+per-file Android.bp = file:platform/build/soong:/OWNERS
+per-file com_android_server_Usb* = file:/services/usb/OWNERS
+per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
+per-file com_android_server_input_* = file:/core/java/android/hardware/input/OWNERS
+per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
+per-file com_android_server_location_* = file:/location/java/android/location/OWNERS
+per-file com_android_server_locksettings_* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file com_android_server_net_* = file:/services/core/java/com/android/server/net/OWNERS
+per-file com_android_server_pm_* = file:/services/core/java/com/android/server/pm/OWNERS
+per-file com_android_server_power_* = file:/services/core/java/com/android/server/power/OWNERS
+per-file com_android_server_se_* = file:/core/java/android/se/OWNERS
+per-file com_android_server_security_* = file:/core/java/android/security/OWNERS
+per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS
+per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/core/jni/com_android_server_VibratorManagerService.cpp b/services/core/jni/com_android_server_VibratorManagerService.cpp
index dae9cef..71de9bd 100644
--- a/services/core/jni/com_android_server_VibratorManagerService.cpp
+++ b/services/core/jni/com_android_server_VibratorManagerService.cpp
@@ -26,8 +26,13 @@
 
 #include <vibratorservice/VibratorManagerHalWrapper.h>
 
+#include "com_android_server_VibratorManagerService.h"
+
 namespace android {
 
+static std::mutex gManagerMutex;
+static vibrator::ManagerHalWrapper* gManager GUARDED_BY(gManagerMutex) = nullptr;
+
 class NativeVibratorManagerService {
 public:
     NativeVibratorManagerService() : mHal(std::make_unique<vibrator::LegacyManagerHalWrapper>()) {}
@@ -39,9 +44,16 @@
     const std::unique_ptr<vibrator::ManagerHalWrapper> mHal;
 };
 
+vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager() {
+    std::lock_guard<std::mutex> lock(gManagerMutex);
+    return gManager;
+}
+
 static void destroyNativeService(void* ptr) {
     NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr);
     if (service) {
+        std::lock_guard<std::mutex> lock(gManagerMutex);
+        gManager = nullptr;
         delete service;
     }
 }
@@ -49,6 +61,10 @@
 static jlong nativeInit(JNIEnv* /* env */, jclass /* clazz */) {
     std::unique_ptr<NativeVibratorManagerService> service =
             std::make_unique<NativeVibratorManagerService>();
+    {
+        std::lock_guard<std::mutex> lock(gManagerMutex);
+        gManager = service->hal();
+    }
     return reinterpret_cast<jlong>(service.release());
 }
 
diff --git a/services/core/jni/com_android_server_VibratorManagerService.h b/services/core/jni/com_android_server_VibratorManagerService.h
new file mode 100644
index 0000000..3f2a322
--- /dev/null
+++ b/services/core/jni/com_android_server_VibratorManagerService.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_SERVER_VIBRATOR_MANAGER_SERVICE_H
+#define _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H
+
+#include <vibratorservice/VibratorManagerHalWrapper.h>
+
+namespace android {
+
+extern vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager();
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 13450be..57d28ba 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -62,11 +62,11 @@
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
 
-#include "com_android_server_power_PowerManagerService.h"
+#include "android_hardware_display_DisplayViewport.h"
 #include "android_hardware_input_InputApplicationHandle.h"
 #include "android_hardware_input_InputWindowHandle.h"
-#include "android_hardware_display_DisplayViewport.h"
 #include "android_util_Binder.h"
+#include "com_android_server_power_PowerManagerService.h"
 
 #include <vector>
 
@@ -101,6 +101,8 @@
     jmethodID notifyConnectionUnresponsive;
     jmethodID notifyConnectionResponsive;
     jmethodID notifyFocusChanged;
+    jmethodID notifySensorEvent;
+    jmethodID notifySensorAccuracy;
     jmethodID notifyUntrustedTouch;
     jmethodID filterInputEvent;
     jmethodID interceptKeyBeforeQueueing;
@@ -149,6 +151,37 @@
     jmethodID getAffineTransform;
 } gTouchCalibrationClassInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID constructor;
+    jmethodID keyAt;
+    jmethodID valueAt;
+    jmethodID size;
+} gSparseArrayClassInfo;
+
+struct InputSensorInfoOffsets {
+    jclass clazz;
+    // fields
+    jfieldID name;
+    jfieldID vendor;
+    jfieldID version;
+    jfieldID handle;
+    jfieldID maxRange;
+    jfieldID resolution;
+    jfieldID power;
+    jfieldID minDelay;
+    jfieldID fifoReservedEventCount;
+    jfieldID fifoMaxEventCount;
+    jfieldID stringType;
+    jfieldID requiredPermission;
+    jfieldID maxDelay;
+    jfieldID flags;
+    jfieldID type;
+    jfieldID id;
+    // methods
+    jmethodID init;
+} gInputSensorInfo;
+
 // --- Global functions ---
 
 template<typename T>
@@ -216,7 +249,8 @@
                                                                    const std::string& name);
     base::Result<std::unique_ptr<InputChannel>> createInputMonitor(JNIEnv* env, int32_t displayId,
                                                                    bool isGestureMonitor,
-                                                                   const std::string& name);
+                                                                   const std::string& name,
+                                                                   int32_t pid);
     status_t removeInputChannel(JNIEnv* env, const sp<IBinder>& connectionToken);
     status_t pilferPointers(const sp<IBinder>& token);
 
@@ -232,8 +266,8 @@
     void reloadCalibration();
     void setPointerIconType(int32_t iconId);
     void reloadPointerIcons();
+    void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled);
     void setCustomPointerIcon(const SpriteIcon& icon);
-    void setPointerCapture(bool enabled);
     void setMotionClassifierEnabled(bool enabled);
 
     /* --- InputReaderPolicyInterface implementation --- */
@@ -259,6 +293,11 @@
     void notifyConnectionResponsive(const sp<IBinder>& token) override;
     void notifyInputChannelBroken(const sp<IBinder>& token) override;
     void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
+    void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
+                           InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
+                           const std::vector<float>& values) override;
+    void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
+                              InputDeviceSensorAccuracy accuracy) override;
     void notifyUntrustedTouch(const std::string& obscuringPackage) override;
     bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override;
     void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override;
@@ -272,6 +311,7 @@
     void pokeUserActivity(nsecs_t eventTime, int32_t eventType) override;
     bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
     void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
+    void setPointerCapture(bool enabled) override;
 
     /* --- PointerControllerPolicyInterface implementation --- */
 
@@ -448,9 +488,11 @@
 }
 
 base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputMonitor(
-        JNIEnv* /* env */, int32_t displayId, bool isGestureMonitor, const std::string& name) {
+        JNIEnv* /* env */, int32_t displayId, bool isGestureMonitor, const std::string& name,
+        int32_t pid) {
     ATRACE_CALL();
-    return mInputManager->getDispatcher()->createInputMonitor(displayId, isGestureMonitor, name);
+    return mInputManager->getDispatcher()->createInputMonitor(displayId, isGestureMonitor, name,
+                                                              pid);
 }
 
 status_t NativeInputManager::removeInputChannel(JNIEnv* /* env */,
@@ -811,6 +853,35 @@
     checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
 }
 
+void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
+                                           InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
+                                           const std::vector<float>& values) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+    ALOGD("notifySensorEvent");
+#endif
+    ATRACE_CALL();
+    JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
+    jfloatArray arr = env->NewFloatArray(values.size());
+    env->SetFloatArrayRegion(arr, 0, values.size(), values.data());
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySensorEvent, deviceId,
+                        static_cast<jint>(sensorType), accuracy, timestamp, arr);
+    checkAndClearExceptionFromCallback(env, "notifySensorEvent");
+}
+
+void NativeInputManager::notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
+                                              InputDeviceSensorAccuracy accuracy) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+    ALOGD("notifySensorAccuracy");
+#endif
+    ATRACE_CALL();
+    JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySensorAccuracy, deviceId,
+                        static_cast<jint>(sensorType), accuracy);
+    checkAndClearExceptionFromCallback(env, "notifySensorAccuracy");
+}
+
 void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
@@ -922,20 +993,8 @@
             InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
 }
 
-void NativeInputManager::setPointerCapture(bool enabled) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mLocked.pointerCapture == enabled) {
-            return;
-        }
-
-        ALOGI("Setting pointer capture to %s.", enabled ? "enabled" : "disabled");
-        mLocked.pointerCapture = enabled;
-    } // release lock
-
-    mInputManager->getReader()->requestRefreshConfiguration(
-            InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+void NativeInputManager::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
+    mInputManager->getDispatcher()->requestPointerCapture(windowToken, enabled);
 }
 
 void NativeInputManager::setInteractive(bool interactive) {
@@ -1207,7 +1266,6 @@
     android_server_PowerManagerService_userActivity(eventTime, eventType);
 }
 
-
 bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
         int32_t injectorPid, int32_t injectorUid) {
     ATRACE_CALL();
@@ -1230,6 +1288,22 @@
     checkAndClearExceptionFromCallback(env, "onPointerDownOutsideFocus");
 }
 
+void NativeInputManager::setPointerCapture(bool enabled) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mLocked.pointerCapture == enabled) {
+            return;
+        }
+
+        ALOGV("%s pointer capture.", enabled ? "Enabling" : "Disabling");
+        mLocked.pointerCapture = enabled;
+    } // release lock
+
+    mInputManager->getReader()->requestRefreshConfiguration(
+            InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+}
+
 void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
@@ -1432,7 +1506,7 @@
 }
 
 static jobject nativeCreateInputMonitor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId,
-                                        jboolean isGestureMonitor, jstring nameObj) {
+                                        jboolean isGestureMonitor, jstring nameObj, jint pid) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     if (displayId == ADISPLAY_ID_NONE) {
@@ -1445,7 +1519,7 @@
     std::string name = nameChars.c_str();
 
     base::Result<std::unique_ptr<InputChannel>> inputChannel =
-            im->createInputMonitor(env, displayId, isGestureMonitor, name);
+            im->createInputMonitor(env, displayId, isGestureMonitor, name, pid);
 
     if (!inputChannel) {
         std::string message = inputChannel.error().message();
@@ -1623,11 +1697,12 @@
     im->setFocusedDisplay(env, displayId);
 }
 
-static void nativeSetPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
-        jboolean enabled) {
+static void nativeRequestPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
+                                        jobject tokenObj, jboolean enabled) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    sp<IBinder> windowToken = ibinderForJavaObject(env, tokenObj);
 
-    im->setPointerCapture(enabled);
+    im->requestPointerCapture(windowToken, enabled);
 }
 
 static void nativeSetInputDispatchMode(JNIEnv* /* env */,
@@ -1705,19 +1780,73 @@
             patternObj, nullptr));
     jint* amplitudes = static_cast<jint*>(env->GetPrimitiveArrayCritical(amplitudesObj, nullptr));
 
-    std::vector<VibrationElement> elements(patternSize);
+    VibrationSequence sequence(patternSize);
+    std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId);
     for (size_t i = 0; i < patternSize; i++) {
         // VibrationEffect.validate guarantees duration > 0.
         std::chrono::milliseconds duration(patternMillis[i]);
-        elements[i].duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
-        // TODO: (b/161629089) apply channel specific amplitudes from development API.
-        elements[i].channels = {static_cast<uint8_t>(amplitudes[i]),
-                                static_cast<uint8_t>(amplitudes[i])};
+        VibrationElement element(CHANNEL_SIZE);
+        element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
+        // Vibrate on both channels
+        for (int32_t channel = 0; channel < vibrators.size(); channel++) {
+            element.addChannel(vibrators[channel], static_cast<uint8_t>(amplitudes[i]));
+        }
+        sequence.addElement(element);
     }
     env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
     env->ReleasePrimitiveArrayCritical(amplitudesObj, amplitudes, JNI_ABORT);
 
-    im->getInputManager()->getReader()->vibrate(deviceId, elements, repeat, token);
+    im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token);
+}
+
+static void nativeVibrateCombined(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                  jlongArray patternObj, jobject amplitudesObj, jint repeat,
+                                  jint token) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    size_t patternSize = env->GetArrayLength(patternObj);
+
+    if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
+        ALOGI("Skipped requested vibration because the pattern size is %zu "
+              "which is more than the maximum supported size of %d.",
+              patternSize, MAX_VIBRATE_PATTERN_SIZE);
+        return; // limit to reasonable size
+    }
+    const jlong* patternMillis = env->GetLongArrayElements(patternObj, nullptr);
+
+    std::array<jint*, CHANNEL_SIZE> amplitudesArray;
+    std::array<jint, CHANNEL_SIZE> vibratorIdArray;
+    jint amplSize = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.size);
+    if (amplSize > CHANNEL_SIZE) {
+        ALOGE("Can not fit into input device vibration element.");
+        return;
+    }
+
+    for (int i = 0; i < amplSize; i++) {
+        vibratorIdArray[i] = env->CallIntMethod(amplitudesObj, gSparseArrayClassInfo.keyAt, i);
+        jintArray arr = static_cast<jintArray>(
+                env->CallObjectMethod(amplitudesObj, gSparseArrayClassInfo.valueAt, i));
+        amplitudesArray[i] = env->GetIntArrayElements(arr, nullptr);
+        if (env->GetArrayLength(arr) != patternSize) {
+            ALOGE("Amplitude length not equal to pattern length!");
+            return;
+        }
+    }
+
+    VibrationSequence sequence(patternSize);
+    for (size_t i = 0; i < patternSize; i++) {
+        VibrationElement element(CHANNEL_SIZE);
+        // VibrationEffect.validate guarantees duration > 0.
+        std::chrono::milliseconds duration(patternMillis[i]);
+        element.duration = std::min(duration, MAX_VIBRATE_PATTERN_DELAY_MILLIS);
+        for (int32_t channel = 0; channel < CHANNEL_SIZE; channel++) {
+            element.addChannel(vibratorIdArray[channel],
+                               static_cast<uint8_t>(amplitudesArray[channel][i]));
+        }
+        sequence.addElement(element);
+    }
+
+    im->getInputManager()->getReader()->vibrate(deviceId, sequence, repeat, token);
 }
 
 static void nativeCancelVibrate(JNIEnv* /* env */,
@@ -1727,6 +1856,23 @@
     im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
 }
 
+static bool nativeIsVibrating(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    return im->getInputManager()->getReader()->isVibrating(deviceId);
+}
+
+static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    std::vector<int32_t> vibrators = im->getInputManager()->getReader()->getVibratorIds(deviceId);
+
+    jintArray vibIdArray = env->NewIntArray(vibrators.size());
+    if (vibIdArray != nullptr) {
+        env->SetIntArrayRegion(vibIdArray, 0, vibrators.size(), vibrators.data());
+    }
+    return vibIdArray;
+}
+
 static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
         jclass /* clazz */, jlong ptr) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1827,6 +1973,111 @@
     im->setMotionClassifierEnabled(enabled);
 }
 
+static jobject createInputSensorInfo(JNIEnv* env, jstring name, jstring vendor, jint version,
+                                     jint handle, jint type, jfloat maxRange, jfloat resolution,
+                                     jfloat power, jfloat minDelay, jint fifoReservedEventCount,
+                                     jint fifoMaxEventCount, jstring stringType,
+                                     jstring requiredPermission, jint maxDelay, jint flags,
+                                     jint id) {
+    // SensorInfo sensorInfo = new Sensor();
+    jobject sensorInfo = env->NewObject(gInputSensorInfo.clazz, gInputSensorInfo.init, "");
+
+    if (sensorInfo != NULL) {
+        env->SetObjectField(sensorInfo, gInputSensorInfo.name, name);
+        env->SetObjectField(sensorInfo, gInputSensorInfo.vendor, vendor);
+        env->SetIntField(sensorInfo, gInputSensorInfo.version, version);
+        env->SetIntField(sensorInfo, gInputSensorInfo.handle, handle);
+        env->SetFloatField(sensorInfo, gInputSensorInfo.maxRange, maxRange);
+        env->SetFloatField(sensorInfo, gInputSensorInfo.resolution, resolution);
+        env->SetFloatField(sensorInfo, gInputSensorInfo.power, power);
+        env->SetIntField(sensorInfo, gInputSensorInfo.minDelay, minDelay);
+        env->SetIntField(sensorInfo, gInputSensorInfo.fifoReservedEventCount,
+                         fifoReservedEventCount);
+        env->SetIntField(sensorInfo, gInputSensorInfo.fifoMaxEventCount, fifoMaxEventCount);
+        env->SetObjectField(sensorInfo, gInputSensorInfo.requiredPermission, requiredPermission);
+        env->SetIntField(sensorInfo, gInputSensorInfo.maxDelay, maxDelay);
+        env->SetIntField(sensorInfo, gInputSensorInfo.flags, flags);
+        env->SetObjectField(sensorInfo, gInputSensorInfo.stringType, stringType);
+        env->SetIntField(sensorInfo, gInputSensorInfo.type, type);
+        env->SetIntField(sensorInfo, gInputSensorInfo.id, id);
+    }
+    return sensorInfo;
+}
+
+static jobjectArray nativeGetSensorList(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    std::vector<InputDeviceInfo> devices = im->getInputManager()->getReader()->getInputDevices();
+    // Find the input device by deviceId
+    auto it = std::find_if(devices.begin(), devices.end(),
+                           [deviceId](InputDeviceInfo& info) { return info.getId() == deviceId; });
+
+    if (it == devices.end()) {
+        // Return an array of size 0
+        return env->NewObjectArray(0, gInputSensorInfo.clazz, nullptr);
+    }
+
+    std::vector<InputDeviceSensorType> types = it->getSensorTypes();
+    jobjectArray arr = env->NewObjectArray(types.size(), gInputSensorInfo.clazz, nullptr);
+    for (int i = 0; i < types.size(); i++) {
+        const InputDeviceSensorInfo* sensorInfo = it->getSensorInfo(types[i]);
+        if (sensorInfo == nullptr) {
+            ALOGW("Failed to get input device %d sensor info for type %s", deviceId,
+                  NamedEnum::string(types[i]).c_str());
+            continue;
+        }
+
+        jobject info =
+                createInputSensorInfo(env, env->NewStringUTF(sensorInfo->name.c_str()),
+                                      env->NewStringUTF(sensorInfo->vendor.c_str()),
+                                      (jint)sensorInfo->version, 0 /* handle */,
+                                      (jint)sensorInfo->type, (jfloat)sensorInfo->maxRange,
+                                      (jfloat)sensorInfo->resolution, (jfloat)sensorInfo->power,
+                                      (jfloat)sensorInfo->minDelay,
+                                      (jint)sensorInfo->fifoReservedEventCount,
+                                      (jint)sensorInfo->fifoMaxEventCount,
+                                      env->NewStringUTF(sensorInfo->stringType.c_str()),
+                                      env->NewStringUTF("") /* requiredPermission */,
+                                      (jint)sensorInfo->maxDelay, (jint)sensorInfo->flags,
+                                      (jint)sensorInfo->id);
+        env->SetObjectArrayElement(arr, i, info);
+        env->DeleteLocalRef(info);
+    }
+    return arr;
+}
+
+static jboolean nativeEnableSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                   jint sensorType, jint samplingPeriodUs,
+                                   jint maxBatchReportLatencyUs) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    return im->getInputManager()
+            ->getReader()
+            ->enableSensor(deviceId, static_cast<InputDeviceSensorType>(sensorType),
+                           std::chrono::microseconds(samplingPeriodUs),
+                           std::chrono::microseconds(maxBatchReportLatencyUs));
+    return true;
+}
+
+static void nativeDisableSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                jint sensorType) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    im->getInputManager()->getReader()->disableSensor(deviceId,
+                                                      static_cast<InputDeviceSensorType>(
+                                                              sensorType));
+}
+
+static jboolean nativeFlushSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+                                  jint sensorType) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    im->getInputManager()->getReader()->flushSensor(deviceId,
+                                                    static_cast<InputDeviceSensorType>(sensorType));
+    return im->getInputManager()->getDispatcher()->flushSensor(deviceId,
+                                                               static_cast<InputDeviceSensorType>(
+                                                                       sensorType));
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -1844,7 +2095,7 @@
         {"nativeHasKeys", "(JII[I[Z)Z", (void*)nativeHasKeys},
         {"nativeCreateInputChannel", "(JLjava/lang/String;)Landroid/view/InputChannel;",
          (void*)nativeCreateInputChannel},
-        {"nativeCreateInputMonitor", "(JIZLjava/lang/String;)Landroid/view/InputChannel;",
+        {"nativeCreateInputMonitor", "(JIZLjava/lang/String;I)Landroid/view/InputChannel;",
          (void*)nativeCreateInputMonitor},
         {"nativeRemoveInputChannel", "(JLandroid/os/IBinder;)V", (void*)nativeRemoveInputChannel},
         {"nativePilferPointers", "(JLandroid/os/IBinder;)V", (void*)nativePilferPointers},
@@ -1862,7 +2113,8 @@
         {"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
          (void*)nativeSetFocusedApplication},
         {"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
-        {"nativeSetPointerCapture", "(JZ)V", (void*)nativeSetPointerCapture},
+        {"nativeRequestPointerCapture", "(JLandroid/os/IBinder;Z)V",
+         (void*)nativeRequestPointerCapture},
         {"nativeSetInputDispatchMode", "(JZZ)V", (void*)nativeSetInputDispatchMode},
         {"nativeSetSystemUiLightsOut", "(JZ)V", (void*)nativeSetSystemUiLightsOut},
         {"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)Z",
@@ -1872,7 +2124,11 @@
         {"nativeSetInteractive", "(JZ)V", (void*)nativeSetInteractive},
         {"nativeReloadCalibration", "(J)V", (void*)nativeReloadCalibration},
         {"nativeVibrate", "(JI[J[III)V", (void*)nativeVibrate},
+        {"nativeVibrateCombined", "(JI[JLandroid/util/SparseArray;II)V",
+         (void*)nativeVibrateCombined},
         {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
+        {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
+        {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
         {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
         {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
         {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},
@@ -1887,6 +2143,11 @@
         {"nativeCanDispatchToDisplay", "(JII)Z", (void*)nativeCanDispatchToDisplay},
         {"nativeNotifyPortAssociationsChanged", "(J)V", (void*)nativeNotifyPortAssociationsChanged},
         {"nativeSetMotionClassifierEnabled", "(JZ)V", (void*)nativeSetMotionClassifierEnabled},
+        {"nativeGetSensorList", "(JI)[Landroid/hardware/input/InputSensorInfo;",
+         (void*)nativeGetSensorList},
+        {"nativeEnableSensor", "(JIIII)Z", (void*)nativeEnableSensor},
+        {"nativeDisableSensor", "(JII)V", (void*)nativeDisableSensor},
+        {"nativeFlushSensor", "(JII)Z", (void*)nativeFlushSensor},
 };
 
 #define FIND_CLASS(var, className) \
@@ -1932,6 +2193,10 @@
     GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
             "notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");
 
+    GET_METHOD_ID(gServiceClassInfo.notifySensorEvent, clazz, "notifySensorEvent", "(IIIJ[F)V");
+
+    GET_METHOD_ID(gServiceClassInfo.notifySensorAccuracy, clazz, "notifySensorAccuracy", "(III)V");
+
     GET_METHOD_ID(gServiceClassInfo.notifyUntrustedTouch, clazz, "notifyUntrustedTouch",
                   "(Ljava/lang/String;)V");
 
@@ -2048,6 +2313,42 @@
     GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
             "getAffineTransform", "()[F");
 
+    // SparseArray
+    FIND_CLASS(gSparseArrayClassInfo.clazz, "android/util/SparseArray");
+    gSparseArrayClassInfo.clazz = jclass(env->NewGlobalRef(gSparseArrayClassInfo.clazz));
+    GET_METHOD_ID(gSparseArrayClassInfo.constructor, gSparseArrayClassInfo.clazz, "<init>", "()V");
+    GET_METHOD_ID(gSparseArrayClassInfo.keyAt, gSparseArrayClassInfo.clazz, "keyAt", "(I)I");
+    GET_METHOD_ID(gSparseArrayClassInfo.valueAt, gSparseArrayClassInfo.clazz, "valueAt",
+                  "(I)Ljava/lang/Object;");
+    GET_METHOD_ID(gSparseArrayClassInfo.size, gSparseArrayClassInfo.clazz, "size", "()I");
+    // InputSensorInfo
+    // android.hardware.input.InputDeviceSensorInfo
+    FIND_CLASS(clazz, "android/hardware/input/InputSensorInfo");
+    gInputSensorInfo.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+
+    GET_FIELD_ID(gInputSensorInfo.name, gInputSensorInfo.clazz, "mName", "Ljava/lang/String;");
+    GET_FIELD_ID(gInputSensorInfo.vendor, gInputSensorInfo.clazz, "mVendor", "Ljava/lang/String;");
+    GET_FIELD_ID(gInputSensorInfo.version, gInputSensorInfo.clazz, "mVersion", "I");
+    GET_FIELD_ID(gInputSensorInfo.handle, gInputSensorInfo.clazz, "mHandle", "I");
+    GET_FIELD_ID(gInputSensorInfo.maxRange, gInputSensorInfo.clazz, "mMaxRange", "F");
+    GET_FIELD_ID(gInputSensorInfo.resolution, gInputSensorInfo.clazz, "mResolution", "F");
+    GET_FIELD_ID(gInputSensorInfo.power, gInputSensorInfo.clazz, "mPower", "F");
+    GET_FIELD_ID(gInputSensorInfo.minDelay, gInputSensorInfo.clazz, "mMinDelay", "I");
+    GET_FIELD_ID(gInputSensorInfo.fifoReservedEventCount, gInputSensorInfo.clazz,
+                 "mFifoReservedEventCount", "I");
+    GET_FIELD_ID(gInputSensorInfo.fifoMaxEventCount, gInputSensorInfo.clazz, "mFifoMaxEventCount",
+                 "I");
+    GET_FIELD_ID(gInputSensorInfo.stringType, gInputSensorInfo.clazz, "mStringType",
+                 "Ljava/lang/String;");
+    GET_FIELD_ID(gInputSensorInfo.requiredPermission, gInputSensorInfo.clazz, "mRequiredPermission",
+                 "Ljava/lang/String;");
+    GET_FIELD_ID(gInputSensorInfo.maxDelay, gInputSensorInfo.clazz, "mMaxDelay", "I");
+    GET_FIELD_ID(gInputSensorInfo.flags, gInputSensorInfo.clazz, "mFlags", "I");
+    GET_FIELD_ID(gInputSensorInfo.type, gInputSensorInfo.clazz, "mType", "I");
+    GET_FIELD_ID(gInputSensorInfo.id, gInputSensorInfo.clazz, "mId", "I");
+
+    GET_METHOD_ID(gInputSensorInfo.init, gInputSensorInfo.clazz, "<init>", "()V");
+
     return 0;
 }
 
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 1a6128f..066dbce 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -31,6 +31,7 @@
 #include <android/hardware/gnss/2.1/IGnssMeasurement.h>
 #include <android/hardware/gnss/3.0/IGnssPsds.h>
 #include <android/hardware/gnss/BnGnss.h>
+#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
 #include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
 #include <android/hardware/gnss/BnGnssPsdsCallback.h>
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
@@ -41,6 +42,8 @@
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
 #include "gnss/GnssConfiguration.h"
+#include "gnss/GnssMeasurement.h"
+#include "gnss/Utils.h"
 #include "hardware_legacy/power.h"
 #include "jni.h"
 #include "utils/Log.h"
@@ -56,11 +59,8 @@
 #include <string.h>
 #include <utils/SystemClock.h>
 
-static jclass class_gnssMeasurementsEvent;
-static jclass class_gnssMeasurement;
 static jclass class_location;
 static jclass class_gnssNavigationMessage;
-static jclass class_gnssClock;
 static jclass class_gnssAntennaInfoBuilder;
 static jclass class_gnssPowerStats;
 static jclass class_phaseCenterOffset;
@@ -68,7 +68,7 @@
 static jclass class_arrayList;
 static jclass class_doubleArray;
 
-static jobject mCallbacksObj = nullptr;
+jobject android::mCallbacksObj = nullptr;
 
 static jmethodID method_reportLocation;
 static jmethodID method_reportStatus;
@@ -90,7 +90,6 @@
 static jmethodID method_reportGeofenceRemoveStatus;
 static jmethodID method_reportGeofencePauseStatus;
 static jmethodID method_reportGeofenceResumeStatus;
-static jmethodID method_reportMeasurementData;
 static jmethodID method_reportAntennaInfo;
 static jmethodID method_reportNavigationMessages;
 static jmethodID method_reportLocationBatch;
@@ -123,11 +122,8 @@
 static jmethodID method_correctionPlaneAzimDeg;
 static jmethodID method_reportNfwNotification;
 static jmethodID method_isInEmergencySession;
-static jmethodID method_gnssMeasurementsEventCtor;
 static jmethodID method_locationCtor;
 static jmethodID method_gnssNavigationMessageCtor;
-static jmethodID method_gnssClockCtor;
-static jmethodID method_gnssMeasurementCtor;
 static jmethodID method_gnssAntennaInfoBuilderCtor;
 static jmethodID method_gnssPowerStatsCtor;
 static jmethodID method_phaseCenterOffsetCtor;
@@ -145,7 +141,7 @@
  * Save a pointer to JavaVm to attach/detach threads executing
  * callback methods that need to make JNI calls.
  */
-static JavaVM* sJvm;
+JavaVM* android::ScopedJniThreadAttach::sJvm;
 
 using android::OK;
 using android::sp;
@@ -201,14 +197,6 @@
 using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
 using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
 using IGnssAntennaInfoCallback = android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
-using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
-using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
-using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
-using IGnssMeasurement_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
-using IGnssMeasurementCallback_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
 using IAGnssRil_V1_0 = android::hardware::gnss::V1_0::IAGnssRil;
 using IAGnssRil_V2_0 = android::hardware::gnss::V2_0::IAGnssRil;
 using IAGnss_V1_0 = android::hardware::gnss::V1_0::IAGnss;
@@ -246,12 +234,11 @@
         ALOGE("IGNSS hidl service failed, trying to recover...");
 
         JNIEnv* env = android::AndroidRuntime::getJNIEnv();
-        env->CallVoidMethod(mCallbacksObj, method_reportGnssServiceDied);
+        env->CallVoidMethod(android::mCallbacksObj, method_reportGnssServiceDied);
     }
 };
 
 // Must match the value from GnssMeasurement.java
-static const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1<<4);
 static const uint32_t SVID_FLAGS_HAS_BASEBAND_CN0 = (1<<4);
 
 sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr;
@@ -274,10 +261,6 @@
 sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
 sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
 sp<IGnssNi> gnssNiIface = nullptr;
-sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
-sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
-sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
-sp<IGnssMeasurement_V2_1> gnssMeasurementIface_V2_1 = nullptr;
 sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 sp<IGnssPowerIndication> gnssPowerIndicationIface = nullptr;
 sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
@@ -286,6 +269,7 @@
 sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
 
 std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
+std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
 
@@ -305,172 +289,11 @@
 }
 
 }  // namespace
-template<class T>
-class JavaMethodHelper {
- public:
-    // Helper function to call setter on a Java object.
-    static void callJavaMethod(
-           JNIEnv* env,
-           jclass clazz,
-           jobject object,
-           const char* method_name,
-           T value);
-
- private:
-    static const char* const signature_;
-};
-
-template<class T>
-void JavaMethodHelper<T>::callJavaMethod(
-        JNIEnv* env,
-        jclass clazz,
-        jobject object,
-        const char* method_name,
-        T value) {
-    jmethodID method = env->GetMethodID(clazz, method_name, signature_);
-    env->CallVoidMethod(object, method, value);
-}
-
-class JavaObject {
- public:
-    JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
-    JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1);
-    JavaObject(JNIEnv* env, jclass clazz, jobject object);
-
-    virtual ~JavaObject() = default;
-
-    template<class T>
-    void callSetter(const char* method_name, T value);
-    template<class T>
-    void callSetter(const char* method_name, T* value, size_t size);
-    jobject get();
-
- private:
-    JNIEnv* env_;
-    jclass clazz_;
-    jobject object_;
-};
-
-JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor) : env_(env),
-        clazz_(clazz) {
-    object_ = env_->NewObject(clazz_, defaultCtor);
-}
-
-
-JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char * sz_arg_1)
-        : env_(env), clazz_(clazz) {
-    jstring szArg = env->NewStringUTF(sz_arg_1);
-    object_ = env_->NewObject(clazz_, stringCtor, szArg);
-    if (szArg) {
-        env_->DeleteLocalRef(szArg);
-    }
-}
-
-
-JavaObject::JavaObject(JNIEnv* env, jclass clazz, jobject object)
-    : env_(env), clazz_(clazz), object_(object) {
-}
-
-template<class T>
-void JavaObject::callSetter(const char* method_name, T value) {
-    JavaMethodHelper<T>::callJavaMethod(
-            env_, clazz_, object_, method_name, value);
-}
-
-template<>
-void JavaObject::callSetter(
-        const char* method_name, uint8_t* value, size_t size) {
-    jbyteArray array = env_->NewByteArray(size);
-    env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
-    jmethodID method = env_->GetMethodID(
-            clazz_,
-            method_name,
-            "([B)V");
-    env_->CallVoidMethod(object_, method, array);
-    env_->DeleteLocalRef(array);
-}
-
-jobject JavaObject::get() {
-    return object_;
-}
-
-// Define Java method signatures for all known types.
-template<>
-const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
-template<>
-const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
-template<>
-const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
-template<>
-const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
-template<>
-const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
-template<>
-const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
-template<>
-const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
-template<>
-const char *const JavaMethodHelper<uint64_t>::signature_ = "(J)V";
-template<>
-const char *const JavaMethodHelper<float>::signature_ = "(F)V";
-template<>
-const char *const JavaMethodHelper<double>::signature_ = "(D)V";
-template<>
-const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
-template<>
-const char *const JavaMethodHelper<jstring>::signature_ = "(Ljava/lang/String;)V";
-template <>
-const char* const JavaMethodHelper<jdoubleArray>::signature_ = "([D)V";
-
-#define SET(setter, value) object.callSetter("set" # setter, (value))
 
 static inline jboolean boolToJbool(bool value) {
     return value ? JNI_TRUE : JNI_FALSE;
 }
 
-template<class T>
-static inline void logHidlError(Return<T>& result, const char* errorMessage) {
-    ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
-}
-
-template<class T>
-static jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
-    if (!result.isOk()) {
-        logHidlError(result, errorMessage);
-        return JNI_FALSE;
-    } else {
-        return JNI_TRUE;
-    }
-}
-
-static jboolean checkHidlReturn(Return<bool>& result, const char* errorMessage) {
-    if (!result.isOk()) {
-        logHidlError(result, errorMessage);
-        return JNI_FALSE;
-    } else if (!result) {
-        ALOGE("%s", errorMessage);
-        return JNI_FALSE;
-    } else {
-        return JNI_TRUE;
-    }
-}
-
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-static jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
-    if (!status.isOk()) {
-        ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
-        return JNI_FALSE;
-    }
-    return JNI_TRUE;
-}
-
 struct ScopedJniString {
     ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) {
         mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr);
@@ -499,62 +322,6 @@
     const char* mNativeString;
 };
 
-class ScopedJniThreadAttach {
-public:
-    ScopedJniThreadAttach() {
-        /*
-         * attachResult will also be JNI_OK if the thead was already attached to
-         * JNI before the call to AttachCurrentThread().
-         */
-        jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
-        LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
-                            attachResult);
-    }
-
-    ~ScopedJniThreadAttach() {
-        jint detachResult = sJvm->DetachCurrentThread();
-        /*
-         * Return if the thread was already detached. Log error for any other
-         * failure.
-         */
-        if (detachResult == JNI_EDETACHED) {
-            return;
-        }
-
-        LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
-                            detachResult);
-    }
-
-    JNIEnv* getEnv() {
-        /*
-         * Checking validity of mEnv in case the thread was detached elsewhere.
-         */
-        LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
-        return mEnv;
-    }
-
-private:
-    JNIEnv* mEnv = nullptr;
-};
-
-thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
-
-static JNIEnv* getJniEnv() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-    /*
-     * If env is nullptr, the thread is not already attached to
-     * JNI. It is attached below and the destructor for ScopedJniThreadAttach
-     * will detach it on thread exit.
-     */
-    if (env == nullptr) {
-        tJniThreadAttacher.reset(new ScopedJniThreadAttach());
-        env = tJniThreadAttacher->getEnv();
-    }
-
-    return env;
-}
-
 static jobject translateGnssLocation(JNIEnv* env,
                                      const GnssLocation_V1_0& location) {
     JavaObject object(env, class_location, method_locationCtor, "gps");
@@ -1386,322 +1153,6 @@
 }
 
 /*
- * GnssMeasurementCallback implements the callback methods required for the
- * GnssMeasurement interface.
- */
-struct GnssMeasurementCallback : public IGnssMeasurementCallback_V2_1 {
-    Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_V2_1::GnssData& data)
-            override;
-    Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_V2_0::GnssData& data)
-            override;
-    Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_V1_1::GnssData& data) override;
-    Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_V1_0::GnssData& data) override;
- private:
-    template<class T>
-    void translateSingleGnssMeasurement(const T* measurement, JavaObject& object);
-
-    template<class T>
-    jobjectArray translateAllGnssMeasurements(JNIEnv* env, const T* measurements, size_t count);
-
-    template<class T>
-    void translateAndSetGnssData(const T& data);
-
-    template<class T>
-    size_t getMeasurementCount(const T& data);
-
-    template<class T>
-    void translateGnssClock(JavaObject& object, const T& data);
-
-    void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
-};
-
-Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_1(
-        const IGnssMeasurementCallback_V2_1::GnssData& data) {
-    translateAndSetGnssData(data);
-    return Void();
-}
-
-Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_0(
-        const IGnssMeasurementCallback_V2_0::GnssData& data) {
-    translateAndSetGnssData(data);
-    return Void();
-}
-
-Return<void> GnssMeasurementCallback::gnssMeasurementCb(
-        const IGnssMeasurementCallback_V1_1::GnssData& data) {
-    translateAndSetGnssData(data);
-    return Void();
-}
-
-Return<void> GnssMeasurementCallback::GnssMeasurementCb(
-        const IGnssMeasurementCallback_V1_0::GnssData& data) {
-    translateAndSetGnssData(data);
-    return Void();
-}
-
-template<class T>
-void GnssMeasurementCallback::translateAndSetGnssData(const T& data) {
-    JNIEnv* env = getJniEnv();
-
-    JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
-    translateGnssClock(gnssClockJavaObject, data);
-    jobject clock = gnssClockJavaObject.get();
-
-    size_t count = getMeasurementCount(data);
-    jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements.data(), count);
-    setMeasurementData(env, clock, measurementArray);
-
-    env->DeleteLocalRef(clock);
-    env->DeleteLocalRef(measurementArray);
-}
-
-template<>
-size_t GnssMeasurementCallback::getMeasurementCount<IGnssMeasurementCallback_V1_0::GnssData>
-        (const IGnssMeasurementCallback_V1_0::GnssData& data) {
-    return data.measurementCount;
-}
-
-template<class T>
-size_t GnssMeasurementCallback::getMeasurementCount(const T& data) {
-    return data.measurements.size();
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template<>
-void GnssMeasurementCallback::translateSingleGnssMeasurement
-        <IGnssMeasurementCallback_V1_0::GnssMeasurement>(
-        const IGnssMeasurementCallback_V1_0::GnssMeasurement* measurement,
-        JavaObject& object) {
-    uint32_t flags = static_cast<uint32_t>(measurement->flags);
-
-    SET(Svid, static_cast<int32_t>(measurement->svid));
-    SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
-    SET(TimeOffsetNanos, measurement->timeOffsetNs);
-    SET(State, static_cast<int32_t>(measurement->state));
-    SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
-    SET(ReceivedSvTimeUncertaintyNanos,
-        measurement->receivedSvTimeUncertaintyInNs);
-    SET(Cn0DbHz, measurement->cN0DbHz);
-    SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
-    SET(PseudorangeRateUncertaintyMetersPerSecond,
-        measurement->pseudorangeRateUncertaintyMps);
-    SET(AccumulatedDeltaRangeState,
-        (static_cast<int32_t>(measurement->accumulatedDeltaRangeState) &
-        ~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0
-    SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
-    SET(AccumulatedDeltaRangeUncertaintyMeters,
-        measurement->accumulatedDeltaRangeUncertaintyM);
-
-    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
-        SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
-    }
-
-    // Intentionally not copying deprecated fields of carrierCycles,
-    // carrierPhase, carrierPhaseUncertainty
-
-    SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
-
-    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
-        SET(SnrInDb, measurement->snrDb);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL)) {
-        SET(AutomaticGainControlLevelInDb, measurement->agcLevelDb);
-    }
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template<>
-void GnssMeasurementCallback::translateSingleGnssMeasurement
-        <IGnssMeasurementCallback_V1_1::GnssMeasurement>(
-        const IGnssMeasurementCallback_V1_1::GnssMeasurement* measurement_V1_1,
-        JavaObject& object) {
-    translateSingleGnssMeasurement(&(measurement_V1_1->v1_0), object);
-
-    // Set the V1_1 flag, and mark that new field has valid information for Java Layer
-    SET(AccumulatedDeltaRangeState,
-            (static_cast<int32_t>(measurement_V1_1->accumulatedDeltaRangeState) |
-            ADR_STATE_HALF_CYCLE_REPORTED));
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template<>
-void GnssMeasurementCallback::translateSingleGnssMeasurement
-        <IGnssMeasurementCallback_V2_0::GnssMeasurement>(
-        const IGnssMeasurementCallback_V2_0::GnssMeasurement* measurement_V2_0,
-        JavaObject& object) {
-    JNIEnv* env = getJniEnv();
-    translateSingleGnssMeasurement(&(measurement_V2_0->v1_1), object);
-
-    jstring codeType = env->NewStringUTF(measurement_V2_0->codeType.c_str());
-    SET(CodeType, codeType);
-
-    // Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
-    SET(State, static_cast<int32_t>(measurement_V2_0->state));
-
-    // Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated.
-    SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation));
-
-    if (codeType) {
-        env->DeleteLocalRef(codeType);
-    }
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template<>
-void GnssMeasurementCallback::translateSingleGnssMeasurement
-        <IGnssMeasurementCallback_V2_1::GnssMeasurement>(
-        const IGnssMeasurementCallback_V2_1::GnssMeasurement* measurement_V2_1,
-        JavaObject& object) {
-    translateSingleGnssMeasurement(&(measurement_V2_1->v2_0), object);
-
-    SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
-
-    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB) {
-        SET(FullInterSignalBiasNanos, measurement_V2_1->fullInterSignalBiasNs);
-    }
-
-    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) {
-        SET(FullInterSignalBiasUncertaintyNanos,
-            measurement_V2_1->fullInterSignalBiasUncertaintyNs);
-    }
-
-    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
-        SET(SatelliteInterSignalBiasNanos, measurement_V2_1->satelliteInterSignalBiasNs);
-    }
-
-    if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) {
-        SET(SatelliteInterSignalBiasUncertaintyNanos,
-            measurement_V2_1->satelliteInterSignalBiasUncertaintyNs);
-    }
-}
-
-template<class T>
-void GnssMeasurementCallback::translateGnssClock(JavaObject& object, const T& data) {
-    translateGnssClock(object, data.clock);
-}
-
-template<>
-void GnssMeasurementCallback::translateGnssClock(
-       JavaObject& object, const IGnssMeasurementCallback_V1_0::GnssClock& clock) {
-    uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags);
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
-        SET(LeapSecond, static_cast<int32_t>(clock.leapSecond));
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
-        SET(TimeUncertaintyNanos, clock.timeUncertaintyNs);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
-        SET(FullBiasNanos, clock.fullBiasNs);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
-        SET(BiasNanos, clock.biasNs);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
-        SET(BiasUncertaintyNanos, clock.biasUncertaintyNs);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
-        SET(DriftNanosPerSecond, clock.driftNsps);
-    }
-
-    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
-        SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps);
-    }
-
-    SET(TimeNanos, clock.timeNs);
-    SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount);
-}
-
-template<>
-void GnssMeasurementCallback::translateGnssClock(
-       JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssClock& clock) {
-    JNIEnv* env = getJniEnv();
-    SET(ReferenceConstellationTypeForIsb,
-            static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
-    SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz);
-
-    jstring referenceCodeTypeForIsb =
-            env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str());
-    SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb);
-
-    translateGnssClock(object, clock.v1_0);
-
-    if (referenceCodeTypeForIsb) {
-        env->DeleteLocalRef(referenceCodeTypeForIsb);
-    }
-}
-
-template<>
-void GnssMeasurementCallback::translateGnssClock(
-       JavaObject& object, const IGnssMeasurementCallback_V2_0::GnssData& data) {
-    auto elapsedRealtime = data.elapsedRealtime;
-    uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
-    if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
-        SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
-    }
-    if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
-        SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(elapsedRealtime.timeUncertaintyNs));
-    }
-    translateGnssClock(object, data.clock);
-}
-
-template<>
-void GnssMeasurementCallback::translateGnssClock(
-       JavaObject& object, const IGnssMeasurementCallback_V2_1::GnssData& data) {
-    auto elapsedRealtime = data.elapsedRealtime;
-    uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
-    if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
-        SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
-    }
-    if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
-        SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(elapsedRealtime.timeUncertaintyNs));
-    }
-    translateGnssClock(object, data.clock);
-}
-
-template<class T>
-jobjectArray GnssMeasurementCallback::translateAllGnssMeasurements(JNIEnv* env,
-        const T* measurements,
-        size_t count) {
-    if (count == 0) {
-        return nullptr;
-    }
-
-    jobjectArray gnssMeasurementArray = env->NewObjectArray(
-            count,
-            class_gnssMeasurement,
-            nullptr /* initialElement */);
-
-    for (uint16_t i = 0; i < count; ++i) {
-        JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
-        translateSingleGnssMeasurement(&(measurements[i]), object);
-        jobject gnssMeasurement = object.get();
-        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
-        env->DeleteLocalRef(gnssMeasurement);
-    }
-
-    return gnssMeasurementArray;
-}
-
-void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
-                             jobjectArray measurementArray) {
-    jobject gnssMeasurementsEvent = env->NewObject(class_gnssMeasurementsEvent,
-                                                   method_gnssMeasurementsEventCtor,
-                                                   clock,
-                                                   measurementArray);
-
-    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
-                      gnssMeasurementsEvent);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    env->DeleteLocalRef(gnssMeasurementsEvent);
-}
-
-/*
  * MeasurementCorrectionsCallback implements callback methods of interface
  * IMeasurementCorrectionsCallback.hal.
  */
@@ -2073,10 +1524,6 @@
     method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
             "(II)V");
     method_reportAntennaInfo = env->GetMethodID(clazz, "reportAntennaInfo", "(Ljava/util/List;)V");
-    method_reportMeasurementData = env->GetMethodID(
-            clazz,
-            "reportMeasurementData",
-            "(Landroid/location/GnssMeasurementsEvent;)V");
     method_reportNavigationMessages = env->GetMethodID(
             clazz,
             "reportNavigationMessage",
@@ -2150,17 +1597,6 @@
     method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
     method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
 
-    jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
-    class_gnssMeasurementsEvent= (jclass) env->NewGlobalRef(gnssMeasurementsEventClass);
-    method_gnssMeasurementsEventCtor = env->GetMethodID(
-                    class_gnssMeasurementsEvent,
-                    "<init>",
-                    "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
-    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
-    class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
-    method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
-
     jclass gnssAntennaInfoBuilder = env->FindClass("android/location/GnssAntennaInfo$Builder");
     class_gnssAntennaInfoBuilder = (jclass)env->NewGlobalRef(gnssAntennaInfoBuilder);
     method_gnssAntennaInfoBuilderCtor =
@@ -2206,10 +1642,6 @@
     class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
     method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
 
-    jclass gnssClockClass = env->FindClass("android/location/GnssClock");
-    class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
-    method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
-
     jclass arrayListClass = env->FindClass("java/util/ArrayList");
     class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
     method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
@@ -2219,6 +1651,7 @@
     class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
 
     gnss::GnssConfiguration_class_init_once(env);
+    gnss::GnssMeasurement_class_init_once(env, clazz);
 }
 
 /* Initialization needed at system boot and whenever GNSS service dies. */
@@ -2227,7 +1660,7 @@
     /*
      * Save a pointer to JVM.
      */
-    jint jvmStatus = env->GetJavaVM(&sJvm);
+    jint jvmStatus = env->GetJavaVM(&android::ScopedJniThreadAttach::sJvm);
     if (jvmStatus != JNI_OK) {
         LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
     }
@@ -2322,42 +1755,40 @@
     // 1.1@IGnss can be paired {1.0, 1.1}@IGnssMeasurement
     // 1.0@IGnss is paired with 1.0@IGnssMeasurement
     gnssMeasurementIface = nullptr;
-    if (gnssHal_V2_1 != nullptr) {
+    if (gnssHalAidl != nullptr) {
+        sp<hardware::gnss::IGnssMeasurementInterface> gnssMeasurement;
+        auto status = gnssHalAidl->getExtensionGnssMeasurement(&gnssMeasurement);
+        if (checkAidlStatus(status, "Unable to get a handle to GnssMeasurement AIDL interface.")) {
+            gnssMeasurementIface =
+                    std::make_unique<android::gnss::GnssMeasurement>(gnssMeasurement);
+        }
+    }
+    if (gnssHal_V2_1 != nullptr && gnssMeasurementIface == nullptr) {
         auto gnssMeasurement = gnssHal_V2_1->getExtensionGnssMeasurement_2_1();
-        if (!gnssMeasurement.isOk()) {
-            ALOGD("Unable to get a handle to GnssMeasurement_V2_1");
-        } else {
-            gnssMeasurementIface_V2_1 = gnssMeasurement;
-            gnssMeasurementIface_V2_0 = gnssMeasurementIface_V2_1;
-            gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
-            gnssMeasurementIface = gnssMeasurementIface_V1_1;
+        if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V2_1")) {
+            gnssMeasurementIface =
+                    std::make_unique<android::gnss::GnssMeasurement_V2_1>(gnssMeasurement);
         }
     }
     if (gnssHal_V2_0 != nullptr && gnssMeasurementIface == nullptr) {
         auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
-        if (!gnssMeasurement.isOk()) {
-            ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
-        } else {
-            gnssMeasurementIface_V2_0 = gnssMeasurement;
-            gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
-            gnssMeasurementIface = gnssMeasurementIface_V1_1;
+        if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V2_0")) {
+            gnssMeasurementIface =
+                    std::make_unique<android::gnss::GnssMeasurement_V2_0>(gnssMeasurement);
         }
     }
     if (gnssHal_V1_1 != nullptr && gnssMeasurementIface == nullptr) {
-         auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
-         if (!gnssMeasurement.isOk()) {
-             ALOGD("Unable to get a handle to GnssMeasurement_V1_1");
-         } else {
-             gnssMeasurementIface_V1_1 = gnssMeasurement;
-             gnssMeasurementIface = gnssMeasurementIface_V1_1;
-         }
+        auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
+        if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_1")) {
+            gnssMeasurementIface =
+                    std::make_unique<android::gnss::GnssMeasurement_V1_1>(gnssMeasurement);
+        }
     }
     if (gnssMeasurementIface == nullptr) {
          auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
-         if (!gnssMeasurement.isOk()) {
-             ALOGD("Unable to get a handle to GnssMeasurement");
-         } else {
-             gnssMeasurementIface = gnssMeasurement;
+         if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_0")) {
+             gnssMeasurementIface =
+                     std::make_unique<android::gnss::GnssMeasurement_V1_0>(gnssMeasurement);
          }
     }
 
@@ -3274,36 +2705,9 @@
         return JNI_FALSE;
     }
 
-    sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
-    Return<IGnssMeasurement_V1_0::GnssMeasurementStatus> result =
-            IGnssMeasurement_V1_0::GnssMeasurementStatus::ERROR_GENERIC;
-    if (gnssMeasurementIface_V2_1 != nullptr) {
-        result = gnssMeasurementIface_V2_1->setCallback_2_1(cbIface, enableFullTracking);
-    } else if (gnssMeasurementIface_V2_0 != nullptr) {
-        result = gnssMeasurementIface_V2_0->setCallback_2_0(cbIface, enableFullTracking);
-    } else if (gnssMeasurementIface_V1_1 != nullptr) {
-        result = gnssMeasurementIface_V1_1->setCallback_1_1(cbIface, enableFullTracking);
-    } else {
-        if (enableFullTracking == JNI_TRUE) {
-            ALOGW("Full tracking mode not supported in 1.0 GNSS HAL.");
-        }
-        result = gnssMeasurementIface->setCallback(cbIface);
-    }
-
-    if (!checkHidlReturn(result, "IGnssMeasurement setCallback() failed.")) {
-        return JNI_FALSE;
-    }
-
-    IGnssMeasurement_V1_0::GnssMeasurementStatus initRet = result;
-    if (initRet != IGnssMeasurement_V1_0::GnssMeasurementStatus::SUCCESS) {
-        ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
-              static_cast<int32_t>(initRet));
-        return JNI_FALSE;
-    } else {
-        ALOGD("gnss measurement infc has been enabled");
-    }
-
-    return JNI_TRUE;
+    return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
+                                                     mCallbacksObj),
+                                             enableFullTracking);
 }
 
 static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection(
@@ -3314,8 +2718,7 @@
         return JNI_FALSE;
     }
 
-    auto result = gnssMeasurementIface->close();
-    return checkHidlReturn(result, "IGnssMeasurement close() failed.");
+    return gnssMeasurementIface->close();
 }
 
 static jboolean
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index afce537..7ed3748 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -29,6 +29,8 @@
 
 #include <vibratorservice/VibratorHalController.h>
 
+#include "com_android_server_VibratorManagerService.h"
+
 namespace V1_0 = android::hardware::vibrator::V1_0;
 namespace V1_1 = android::hardware::vibrator::V1_1;
 namespace V1_2 = android::hardware::vibrator::V1_2;
@@ -70,13 +72,26 @@
 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
               static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
 
+static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId) {
+    // TODO(b/167946816): remove this once VibratorService is removed.
+    if (vibratorId < 0) {
+        return std::move(std::make_unique<vibrator::HalController>());
+    }
+    vibrator::ManagerHalWrapper* manager = android_server_VibratorManagerService_getManager();
+    if (manager == nullptr) {
+        return nullptr;
+    }
+    auto result = manager->getVibrator(vibratorId);
+    return result.isOk() ? std::move(result.value()) : nullptr;
+}
+
 class VibratorControllerWrapper {
 public:
     VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener)
-          // TODO(b/167946816): use ManagerHalController to get vibrator by id
-          : mHal(std::make_unique<vibrator::HalController>()),
+          : mHal(std::move(findVibrator(vibratorId))),
             mVibratorId(vibratorId),
             mCallbackListener(env->NewGlobalRef(callbackListener)) {
+        LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator hal");
         LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
                             "Unable to create global reference to vibration callback handler");
     }
@@ -97,7 +112,7 @@
     }
 
 private:
-    const std::unique_ptr<vibrator::HalController> mHal;
+    const std::shared_ptr<vibrator::HalController> mHal;
     const int32_t mVibratorId;
     const jobject mCallbackListener;
 };
diff --git a/services/core/jni/gnss/GnssConfiguration.cpp b/services/core/jni/gnss/GnssConfiguration.cpp
index 8610c75..3677641 100644
--- a/services/core/jni/gnss/GnssConfiguration.cpp
+++ b/services/core/jni/gnss/GnssConfiguration.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "GnssConfigurationJni"
 
 #include "GnssConfiguration.h"
+#include "Utils.h"
 
 using android::hardware::gnss::GnssConstellationType;
 using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
@@ -42,29 +43,6 @@
 jclass class_gnssConfiguration_halInterfaceVersion;
 jmethodID method_halInterfaceVersionCtor;
 
-jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
-    if (!status.isOk()) {
-        ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
-        return JNI_FALSE;
-    }
-    return JNI_TRUE;
-}
-
-template <class T>
-inline void logHidlError(Return<T>& result, const char* errorMessage) {
-    ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
-}
-
-template <class T>
-jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
-    if (!result.isOk()) {
-        logHidlError(result, errorMessage);
-        return JNI_FALSE;
-    } else {
-        return JNI_TRUE;
-    }
-}
-
 jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
     return env->NewObject(class_gnssConfiguration_halInterfaceVersion,
                           method_halInterfaceVersionCtor, major, minor);
diff --git a/services/core/jni/gnss/GnssMeasurement.cpp b/services/core/jni/gnss/GnssMeasurement.cpp
new file mode 100644
index 0000000..2261c38
--- /dev/null
+++ b/services/core/jni/gnss/GnssMeasurement.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssMeasurementJni"
+
+#include "GnssMeasurement.h"
+#include "Utils.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+using IGnssMeasurementInterface = android::hardware::gnss::IGnssMeasurementInterface;
+using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
+using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
+using IGnssMeasurement_V2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
+
+namespace {
+jboolean checkGnssMeasurementStatus(const IGnssMeasurement_V1_0::GnssMeasurementStatus& status) {
+    if (status != IGnssMeasurement_V1_0::GnssMeasurementStatus::SUCCESS) {
+        ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
+              static_cast<int32_t>(status));
+        return JNI_FALSE;
+    } else {
+        ALOGD("gnss measurement infc has been enabled");
+        return JNI_TRUE;
+    }
+}
+} // anonymous namespace
+
+namespace android::gnss {
+
+// Implementation of GnssMeasurement
+
+GnssMeasurement::GnssMeasurement(const sp<IGnssMeasurementInterface>& iGnssMeasurement)
+      : mIGnssMeasurement(iGnssMeasurement) {}
+
+jboolean GnssMeasurement::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                      bool enableFullTracking) {
+    auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking);
+    return checkAidlStatus(status, "IGnssMeasurement setCallback() failed.");
+}
+
+jboolean GnssMeasurement::close() {
+    auto status = mIGnssMeasurement->close();
+    return checkAidlStatus(status, "IGnssMeasurement close() failed.");
+}
+
+// Implementation of GnssMeasurement_V1_0
+
+GnssMeasurement_V1_0::GnssMeasurement_V1_0(const sp<IGnssMeasurement_V1_0>& iGnssMeasurement)
+      : mIGnssMeasurement_V1_0(iGnssMeasurement) {}
+
+jboolean GnssMeasurement_V1_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                           bool enableFullTracking) {
+    if (enableFullTracking == true) {
+        ALOGW("Full tracking is mode not supported in 1.0 GNSS HAL.");
+    }
+    auto status = mIGnssMeasurement_V1_0->setCallback(callback->getHidl());
+    if (!checkHidlReturn(status, "IGnssMeasurement setCallback() failed.")) {
+        return JNI_FALSE;
+    }
+
+    return checkGnssMeasurementStatus(status);
+}
+
+jboolean GnssMeasurement_V1_0::close() {
+    auto result = mIGnssMeasurement_V1_0->close();
+    return checkHidlReturn(result, "IGnssMeasurement close() failed.");
+}
+
+// Implementation of GnssMeasurement_V1_1
+
+GnssMeasurement_V1_1::GnssMeasurement_V1_1(const sp<IGnssMeasurement_V1_1>& iGnssMeasurement)
+      : GnssMeasurement_V1_0{iGnssMeasurement}, mIGnssMeasurement_V1_1(iGnssMeasurement) {}
+
+jboolean GnssMeasurement_V1_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                           bool enableFullTracking) {
+    auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback->getHidl(), enableFullTracking);
+    if (!checkHidlReturn(status, "IGnssMeasurement setCallback_V1_1() failed.")) {
+        return JNI_FALSE;
+    }
+
+    return checkGnssMeasurementStatus(status);
+}
+
+// Implementation of GnssMeasurement_V2_0
+
+GnssMeasurement_V2_0::GnssMeasurement_V2_0(const sp<IGnssMeasurement_V2_0>& iGnssMeasurement)
+      : GnssMeasurement_V1_1{iGnssMeasurement}, mIGnssMeasurement_V2_0(iGnssMeasurement) {}
+
+jboolean GnssMeasurement_V2_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                           bool enableFullTracking) {
+    auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback->getHidl(), enableFullTracking);
+    if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_0() failed.")) {
+        return JNI_FALSE;
+    }
+
+    return checkGnssMeasurementStatus(status);
+}
+
+// Implementation of GnssMeasurement_V2_1
+
+GnssMeasurement_V2_1::GnssMeasurement_V2_1(const sp<IGnssMeasurement_V2_1>& iGnssMeasurement)
+      : GnssMeasurement_V2_0{iGnssMeasurement}, mIGnssMeasurement_V2_1(iGnssMeasurement) {}
+
+jboolean GnssMeasurement_V2_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                           bool enableFullTracking) {
+    auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback->getHidl(), enableFullTracking);
+    if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_1() failed.")) {
+        return JNI_FALSE;
+    }
+
+    return checkGnssMeasurementStatus(status);
+}
+
+} // namespace android::gnss
\ No newline at end of file
diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h
new file mode 100644
index 0000000..e64336f
--- /dev/null
+++ b/services/core/jni/gnss/GnssMeasurement.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
+#define _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/BnGnssMeasurementInterface.h>
+#include <log/log.h>
+#include "GnssMeasurementCallback.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+class GnssMeasurementInterface {
+public:
+    virtual ~GnssMeasurementInterface() {}
+    virtual jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                                 bool enableFullTracking) = 0;
+    virtual jboolean close() = 0;
+};
+
+class GnssMeasurement : public GnssMeasurementInterface {
+public:
+    GnssMeasurement(const sp<android::hardware::gnss::IGnssMeasurementInterface>& iGnssMeasurement);
+    jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                         bool enableFullTracking) override;
+    jboolean close() override;
+
+private:
+    const sp<android::hardware::gnss::IGnssMeasurementInterface> mIGnssMeasurement;
+};
+
+class GnssMeasurement_V1_0 : public GnssMeasurementInterface {
+public:
+    GnssMeasurement_V1_0(
+            const sp<android::hardware::gnss::V1_0::IGnssMeasurement>& iGnssMeasurement);
+    jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                         bool enableFullTracking) override;
+    jboolean close() override;
+
+private:
+    const sp<android::hardware::gnss::V1_0::IGnssMeasurement> mIGnssMeasurement_V1_0;
+};
+
+class GnssMeasurement_V1_1 : public GnssMeasurement_V1_0 {
+public:
+    GnssMeasurement_V1_1(
+            const sp<android::hardware::gnss::V1_1::IGnssMeasurement>& iGnssMeasurement);
+    jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                         bool enableFullTracking) override;
+
+private:
+    const sp<android::hardware::gnss::V1_1::IGnssMeasurement> mIGnssMeasurement_V1_1;
+};
+
+class GnssMeasurement_V2_0 : public GnssMeasurement_V1_1 {
+public:
+    GnssMeasurement_V2_0(
+            const sp<android::hardware::gnss::V2_0::IGnssMeasurement>& iGnssMeasurement);
+    jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                         bool enableFullTracking) override;
+
+private:
+    const sp<android::hardware::gnss::V2_0::IGnssMeasurement> mIGnssMeasurement_V2_0;
+};
+
+class GnssMeasurement_V2_1 : public GnssMeasurement_V2_0 {
+public:
+    GnssMeasurement_V2_1(
+            const sp<android::hardware::gnss::V2_1::IGnssMeasurement>& iGnssMeasurement);
+    jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+                         bool enableFullTracking) override;
+
+private:
+    const sp<android::hardware::gnss::V2_1::IGnssMeasurement> mIGnssMeasurement_V2_1;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSMEASUREMENT_H
\ No newline at end of file
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
new file mode 100644
index 0000000..bb020f3
--- /dev/null
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -0,0 +1,387 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GnssMeasCbJni"
+
+#include "GnssMeasurementCallback.h"
+
+namespace android::gnss {
+
+using binder::Status;
+using hardware::gnss::ElapsedRealtime;
+using hardware::gnss::GnssClock;
+using hardware::gnss::GnssData;
+using hardware::gnss::GnssMeasurement;
+
+jclass class_gnssMeasurementsEvent;
+jclass class_gnssMeasurement;
+jclass class_gnssClock;
+
+jmethodID method_gnssMeasurementsEventCtor;
+jmethodID method_gnssClockCtor;
+jmethodID method_gnssMeasurementCtor;
+jmethodID method_reportMeasurementData;
+
+void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) {
+    method_reportMeasurementData = env->GetMethodID(clazz, "reportMeasurementData",
+                                                    "(Landroid/location/GnssMeasurementsEvent;)V");
+    jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
+    class_gnssMeasurementsEvent = (jclass)env->NewGlobalRef(gnssMeasurementsEventClass);
+    method_gnssMeasurementsEventCtor =
+            env->GetMethodID(class_gnssMeasurementsEvent, "<init>",
+                             "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
+
+    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+    class_gnssMeasurement = (jclass)env->NewGlobalRef(gnssMeasurementClass);
+    method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
+
+    jclass gnssClockClass = env->FindClass("android/location/GnssClock");
+    class_gnssClock = (jclass)env->NewGlobalRef(gnssClockClass);
+    method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
+}
+
+void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
+                        jobjectArray measurementArray) {
+    jobject gnssMeasurementsEvent =
+            env->NewObject(class_gnssMeasurementsEvent, method_gnssMeasurementsEventCtor, clock,
+                           measurementArray);
+
+    env->CallVoidMethod(callbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    env->DeleteLocalRef(gnssMeasurementsEvent);
+}
+
+template <class T_Measurement, class T_Flags>
+void setMeasurementFields_V1_0(const T_Measurement& measurement, JavaObject& object) {
+    uint32_t flags = static_cast<uint32_t>(measurement.flags);
+
+    SET(Svid, static_cast<int32_t>(measurement.svid));
+    SET(TimeOffsetNanos, measurement.timeOffsetNs);
+    SET(State, static_cast<int32_t>(measurement.state));
+    SET(ReceivedSvTimeNanos, measurement.receivedSvTimeInNs);
+    SET(ReceivedSvTimeUncertaintyNanos, measurement.receivedSvTimeUncertaintyInNs);
+    SET(PseudorangeRateMetersPerSecond, measurement.pseudorangeRateMps);
+    SET(PseudorangeRateUncertaintyMetersPerSecond, measurement.pseudorangeRateUncertaintyMps);
+    SET(AccumulatedDeltaRangeState,
+        (static_cast<int32_t>(measurement.accumulatedDeltaRangeState) &
+         ~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0
+    SET(AccumulatedDeltaRangeMeters, measurement.accumulatedDeltaRangeM);
+    SET(AccumulatedDeltaRangeUncertaintyMeters, measurement.accumulatedDeltaRangeUncertaintyM);
+
+    // Intentionally not copying deprecated fields of carrierCycles,
+    // carrierPhase, carrierPhaseUncertainty
+
+    SET(MultipathIndicator, static_cast<int32_t>(measurement.multipathIndicator));
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_SNR)) {
+        SET(SnrInDb, measurement.snrDb);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_AUTOMATIC_GAIN_CONTROL)) {
+        SET(AutomaticGainControlLevelInDb, measurement.agcLevelDb);
+    }
+}
+
+template <class T_Measurement, class T_Flags>
+void setMeasurementFields_V2_1(const T_Measurement& measurement, JavaObject& object) {
+    SET(BasebandCn0DbHz, measurement.basebandCN0DbHz);
+
+    if (measurement.flags & T_Flags::HAS_FULL_ISB) {
+        SET(FullInterSignalBiasNanos, measurement.fullInterSignalBiasNs);
+    }
+
+    if (measurement.flags & T_Flags::HAS_FULL_ISB_UNCERTAINTY) {
+        SET(FullInterSignalBiasUncertaintyNanos, measurement.fullInterSignalBiasUncertaintyNs);
+    }
+
+    if (measurement.flags & T_Flags::HAS_SATELLITE_ISB) {
+        SET(SatelliteInterSignalBiasNanos, measurement.satelliteInterSignalBiasNs);
+    }
+
+    if (measurement.flags & T_Flags::HAS_SATELLITE_ISB_UNCERTAINTY) {
+        SET(SatelliteInterSignalBiasUncertaintyNanos,
+            measurement.satelliteInterSignalBiasUncertaintyNs);
+    }
+}
+
+template <class T_Clock, class T_Flags>
+void setClockFields_V1_0(const T_Clock& clock, JavaObject& object) {
+    uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags);
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_LEAP_SECOND)) {
+        SET(LeapSecond, static_cast<int32_t>(clock.leapSecond));
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_TIME_UNCERTAINTY)) {
+        SET(TimeUncertaintyNanos, clock.timeUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_FULL_BIAS)) {
+        SET(FullBiasNanos, clock.fullBiasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS)) {
+        SET(BiasNanos, clock.biasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS_UNCERTAINTY)) {
+        SET(BiasUncertaintyNanos, clock.biasUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT)) {
+        SET(DriftNanosPerSecond, clock.driftNsps);
+    }
+
+    if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT_UNCERTAINTY)) {
+        SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps);
+    }
+
+    SET(TimeNanos, clock.timeNs);
+    SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount);
+}
+
+template <class T_Clock, class T_Flags>
+void setClockFields_V2_1(const T_Clock& clock, JavaObject& object) {
+    JNIEnv* env = getJniEnv();
+    SET(ReferenceConstellationTypeForIsb,
+        static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
+    SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz);
+
+    jstring referenceCodeTypeForIsb =
+            env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str());
+    SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb);
+    env->DeleteLocalRef(referenceCodeTypeForIsb);
+}
+
+template <class T_ElapsedRealtime, class T_Flags>
+void setElapsedRealtimeFields(const T_ElapsedRealtime& elapsedRealtime, JavaObject& object) {
+    uint32_t flags = static_cast<uint32_t>(elapsedRealtime.flags);
+    if (flags & T_Flags::HAS_TIMESTAMP_NS) {
+        SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
+    }
+    if (flags & T_Flags::HAS_TIME_UNCERTAINTY_NS) {
+        SET(ElapsedRealtimeUncertaintyNanos,
+            static_cast<double>(elapsedRealtime.timeUncertaintyNs));
+    }
+}
+
+// Implementation of GnssMeasurementCallbackAidl class.
+
+Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& data) {
+    ALOGD("%s", __func__);
+    translateAndSetGnssData(data);
+    return Status::ok();
+}
+
+void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data) {
+    JNIEnv* env = getJniEnv();
+
+    JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
+    translateGnssClock(env, data, gnssClockJavaObject);
+    jobject clock = gnssClockJavaObject.get();
+
+    jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements);
+    setMeasurementData(env, mCallbacksObj, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
+void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env,
+                                                                 const GnssMeasurement& measurement,
+                                                                 JavaObject& object) {
+    setMeasurementFields_V1_0<GnssMeasurement, GnssMeasurement>(measurement, object);
+    setMeasurementFields_V2_1<GnssMeasurement, GnssMeasurement>(measurement, object);
+
+    SET(Cn0DbHz, measurement.antennaCN0DbHz);
+    SET(ConstellationType, static_cast<int32_t>(measurement.signalType.constellation));
+
+    if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CARRIER_FREQUENCY)) {
+        SET(CarrierFrequencyHz, static_cast<float>(measurement.signalType.carrierFrequencyHz));
+    }
+
+    jstring codeType = env->NewStringUTF(measurement.signalType.codeType.c_str());
+    SET(CodeType, codeType);
+    env->DeleteLocalRef(codeType);
+}
+
+jobjectArray GnssMeasurementCallbackAidl::translateAllGnssMeasurements(
+        JNIEnv* env, const std::vector<GnssMeasurement>& measurements) {
+    if (measurements.size() == 0) {
+        return nullptr;
+    }
+
+    jobjectArray gnssMeasurementArray =
+            env->NewObjectArray(measurements.size(), class_gnssMeasurement,
+                                nullptr /* initialElement */);
+
+    for (uint16_t i = 0; i < measurements.size(); ++i) {
+        JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
+        translateSingleGnssMeasurement(env, measurements[i], object);
+        jobject gnssMeasurement = object.get();
+        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+        env->DeleteLocalRef(gnssMeasurement);
+    }
+
+    return gnssMeasurementArray;
+}
+
+void GnssMeasurementCallbackAidl::translateGnssClock(JNIEnv* env, const GnssData& data,
+                                                     JavaObject& object) {
+    setElapsedRealtimeFields<ElapsedRealtime, ElapsedRealtime>(data.elapsedRealtime, object);
+    setClockFields_V1_0<GnssClock, GnssClock>(data.clock, object);
+    setClockFields_V2_1<GnssClock, GnssClock>(data.clock, object);
+}
+
+// Implementation of GnssMeasurementCallbackHidl class.
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_1(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
+    translateAndSetGnssData(data);
+    return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_0(
+        const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
+    translateAndSetGnssData(data);
+    return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb(
+        const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) {
+    translateAndSetGnssData(data);
+    return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::GnssMeasurementCb(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
+    translateAndSetGnssData(data);
+    return hardware::Void();
+}
+
+template <>
+size_t GnssMeasurementCallbackHidl::getMeasurementCount<
+        hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
+    return data.measurementCount;
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement& measurement,
+        JavaObject& object) {
+    setMeasurementFields_V1_0<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement,
+                              GnssMeasurementFlags>(measurement, object);
+
+    SET(ConstellationType, static_cast<int32_t>(measurement.constellation));
+    SET(Cn0DbHz, measurement.cN0DbHz);
+    if (measurement.flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+        SET(CarrierFrequencyHz, measurement.carrierFrequencyHz);
+    }
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V1_1,
+        JavaObject& object) {
+    translateSingleGnssMeasurement(measurement_V1_1.v1_0, object);
+
+    // Set the V1_1 flag, and mark that new field has valid information for Java Layer
+    SET(AccumulatedDeltaRangeState,
+        (static_cast<int32_t>(measurement_V1_1.accumulatedDeltaRangeState) |
+         ADR_STATE_HALF_CYCLE_REPORTED));
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_0,
+        JavaObject& object) {
+    JNIEnv* env = getJniEnv();
+    translateSingleGnssMeasurement(measurement_V2_0.v1_1, object);
+
+    jstring codeType = env->NewStringUTF(measurement_V2_0.codeType.c_str());
+    SET(CodeType, codeType);
+
+    // Overwrite with v2_0.state since V2_0.v1_1.v1_0.state is deprecated.
+    SET(State, static_cast<int32_t>(measurement_V2_0.state));
+
+    // Overwrite with v2_0.constellation since V2_0.v1_1.v1_0.constellation is deprecated.
+    SET(ConstellationType, static_cast<int32_t>(measurement_V2_0.constellation));
+
+    if (codeType) {
+        env->DeleteLocalRef(codeType);
+    }
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_1,
+        JavaObject& object) {
+    translateSingleGnssMeasurement(measurement_V2_1.v2_0, object);
+
+    setMeasurementFields_V2_1<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement,
+                              GnssMeasurementFlags>(measurement_V2_1, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock,
+        JavaObject& object) {
+    setClockFields_V1_0<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock,
+                        GnssClockFlags>(clock, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock,
+        JavaObject& object) {
+    setClockFields_V2_1<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock,
+                        GnssClockFlags>(clock, object);
+    translateGnssClock(clock.v1_0, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object) {
+    setElapsedRealtimeFields<hardware::gnss::V2_0::ElapsedRealtime,
+                             hardware::gnss::V2_0::ElapsedRealtimeFlags>(data.elapsedRealtime,
+                                                                         object);
+    translateGnssClock(data.clock, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data, JavaObject& object) {
+    auto elapsedRealtime = data.elapsedRealtime;
+    uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
+    if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+        SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
+    }
+    if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
+        SET(ElapsedRealtimeUncertaintyNanos,
+            static_cast<double>(elapsedRealtime.timeUncertaintyNs));
+    }
+    translateGnssClock(data.clock, object);
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h
new file mode 100644
index 0000000..26f1243
--- /dev/null
+++ b/services/core/jni/gnss/GnssMeasurementCallback.h
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
+#define _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
+#include <log/log.h>
+#include "Utils.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+extern jclass class_gnssMeasurementsEvent;
+extern jclass class_gnssMeasurement;
+extern jclass class_gnssClock;
+
+extern jmethodID method_gnssMeasurementsEventCtor;
+extern jmethodID method_gnssClockCtor;
+extern jmethodID method_gnssMeasurementCtor;
+extern jmethodID method_reportMeasurementData;
+
+void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz);
+
+void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
+                        jobjectArray measurementArray);
+
+class GnssMeasurementCallbackAidl : public hardware::gnss::BnGnssMeasurementCallback {
+public:
+    GnssMeasurementCallbackAidl(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+    android::binder::Status gnssMeasurementCb(const hardware::gnss::GnssData& data) override;
+
+private:
+    void translateSingleGnssMeasurement(JNIEnv* env,
+                                        const hardware::gnss::GnssMeasurement& measurement,
+                                        JavaObject& object);
+
+    jobjectArray translateAllGnssMeasurements(
+            JNIEnv* env, const std::vector<hardware::gnss::GnssMeasurement>& measurements);
+
+    void translateAndSetGnssData(const hardware::gnss::GnssData& data);
+
+    void translateGnssClock(JNIEnv* env, const hardware::gnss::GnssData& data, JavaObject& object);
+
+    jobject& mCallbacksObj;
+};
+
+/*
+ * GnssMeasurementCallback implements the callback methods required for the
+ * GnssMeasurement interface.
+ */
+class GnssMeasurementCallbackHidl : public hardware::gnss::V2_1::IGnssMeasurementCallback {
+public:
+    GnssMeasurementCallbackHidl(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+    hardware::Return<void> gnssMeasurementCb_2_1(
+            const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) override;
+    hardware::Return<void> gnssMeasurementCb_2_0(
+            const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) override;
+    hardware::Return<void> gnssMeasurementCb(
+            const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) override;
+    hardware::Return<void> GnssMeasurementCb(
+            const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) override;
+
+private:
+    template <class T>
+    void translateSingleGnssMeasurement(const T& measurement, JavaObject& object);
+
+    template <class T>
+    jobjectArray translateAllGnssMeasurements(JNIEnv* env, const T* measurements, size_t count);
+
+    template <class T>
+    void translateAndSetGnssData(const T& data);
+
+    template <class T>
+    size_t getMeasurementCount(const T& data);
+
+    template <class T>
+    void translateGnssClock(const T& data, JavaObject& object);
+
+    jobject& mCallbacksObj;
+};
+
+class GnssMeasurementCallback {
+public:
+    GnssMeasurementCallback(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+    sp<GnssMeasurementCallbackAidl> getAidl() {
+        if (callbackAidl == nullptr) {
+            callbackAidl = sp<GnssMeasurementCallbackAidl>::make(mCallbacksObj);
+        }
+        return callbackAidl;
+    }
+
+    sp<GnssMeasurementCallbackHidl> getHidl() {
+        if (callbackHidl == nullptr) {
+            callbackHidl = sp<GnssMeasurementCallbackHidl>::make(mCallbacksObj);
+        }
+        return callbackHidl;
+    }
+
+private:
+    jobject& mCallbacksObj;
+    sp<GnssMeasurementCallbackAidl> callbackAidl;
+    sp<GnssMeasurementCallbackHidl> callbackHidl;
+};
+
+template <class T>
+void GnssMeasurementCallbackHidl::translateAndSetGnssData(const T& data) {
+    JNIEnv* env = getJniEnv();
+
+    JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
+    translateGnssClock(data, gnssClockJavaObject);
+    jobject clock = gnssClockJavaObject.get();
+
+    size_t count = getMeasurementCount(data);
+    jobjectArray measurementArray =
+            translateAllGnssMeasurements(env, data.measurements.data(), count);
+    setMeasurementData(env, mCallbacksObj, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
+template <>
+size_t GnssMeasurementCallbackHidl::getMeasurementCount<
+        hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data);
+
+template <class T>
+size_t GnssMeasurementCallbackHidl::getMeasurementCount(const T& data) {
+    return data.measurements.size();
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement& measurement,
+        JavaObject& object);
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V1_1,
+        JavaObject& object);
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_0,
+        JavaObject& object);
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+        hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_1,
+        JavaObject& object);
+
+template <class T>
+void GnssMeasurementCallbackHidl::translateGnssClock(const T& data, JavaObject& object) {
+    translateGnssClock(data.clock, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object);
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object);
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object);
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+        const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data, JavaObject& object);
+
+template <class T>
+jobjectArray GnssMeasurementCallbackHidl::translateAllGnssMeasurements(JNIEnv* env,
+                                                                       const T* measurements,
+                                                                       size_t count) {
+    if (count == 0) {
+        return nullptr;
+    }
+
+    jobjectArray gnssMeasurementArray =
+            env->NewObjectArray(count, class_gnssMeasurement, nullptr /* initialElement */);
+
+    for (uint16_t i = 0; i < count; ++i) {
+        JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
+        translateSingleGnssMeasurement(measurements[i], object);
+        jobject gnssMeasurement = object.get();
+        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+        env->DeleteLocalRef(gnssMeasurement);
+    }
+
+    return gnssMeasurementArray;
+}
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSMEASUREMENTCALLBACK_H
\ No newline at end of file
diff --git a/services/core/jni/gnss/OWNERS b/services/core/jni/gnss/OWNERS
new file mode 100644
index 0000000..5ac6028
--- /dev/null
+++ b/services/core/jni/gnss/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp
new file mode 100644
index 0000000..20e14a9
--- /dev/null
+++ b/services/core/jni/gnss/Utils.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GnssUtilsJni"
+
+#include "Utils.h"
+
+namespace android {
+
+namespace {
+
+thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
+
+} // anonymous namespace
+
+// Define Java method signatures for all known types.
+template <>
+const char* const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
+template <>
+const char* const JavaMethodHelper<int8_t>::signature_ = "(B)V";
+template <>
+const char* const JavaMethodHelper<int16_t>::signature_ = "(S)V";
+template <>
+const char* const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
+template <>
+const char* const JavaMethodHelper<int32_t>::signature_ = "(I)V";
+template <>
+const char* const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
+template <>
+const char* const JavaMethodHelper<int64_t>::signature_ = "(J)V";
+template <>
+const char* const JavaMethodHelper<uint64_t>::signature_ = "(J)V";
+template <>
+const char* const JavaMethodHelper<float>::signature_ = "(F)V";
+template <>
+const char* const JavaMethodHelper<double>::signature_ = "(D)V";
+template <>
+const char* const JavaMethodHelper<bool>::signature_ = "(Z)V";
+template <>
+const char* const JavaMethodHelper<jstring>::signature_ = "(Ljava/lang/String;)V";
+template <>
+const char* const JavaMethodHelper<jdoubleArray>::signature_ = "([D)V";
+
+jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage) {
+    if (!status.isOk()) {
+        ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage) {
+    if (!result.isOk()) {
+        logHidlError(result, errorMessage);
+        return JNI_FALSE;
+    } else if (!result) {
+        ALOGE("%s", errorMessage);
+        return JNI_FALSE;
+    } else {
+        return JNI_TRUE;
+    }
+}
+
+void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
+
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor)
+      : env_(env), clazz_(clazz) {
+    object_ = env_->NewObject(clazz_, defaultCtor);
+}
+
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char* sz_arg_1)
+      : env_(env), clazz_(clazz) {
+    jstring szArg = env->NewStringUTF(sz_arg_1);
+    object_ = env_->NewObject(clazz_, stringCtor, szArg);
+    if (szArg) {
+        env_->DeleteLocalRef(szArg);
+    }
+}
+
+JavaObject::JavaObject(JNIEnv* env, jclass clazz, jobject object)
+      : env_(env), clazz_(clazz), object_(object) {}
+
+template <>
+void JavaObject::callSetter(const char* method_name, uint8_t* value, size_t size) {
+    jbyteArray array = env_->NewByteArray(size);
+    env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
+    jmethodID method = env_->GetMethodID(clazz_, method_name, "([B)V");
+    env_->CallVoidMethod(object_, method, array);
+    env_->DeleteLocalRef(array);
+}
+
+JNIEnv* getJniEnv() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    /*
+     * If env is nullptr, the thread is not already attached to
+     * JNI. It is attached below and the destructor for ScopedJniThreadAttach
+     * will detach it on thread exit.
+     */
+    if (env == nullptr) {
+        tJniThreadAttacher.reset(new ScopedJniThreadAttach());
+        env = tJniThreadAttacher->getEnv();
+    }
+
+    return env;
+}
+
+} // namespace android
diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h
new file mode 100644
index 0000000..32f53d0
--- /dev/null
+++ b/services/core/jni/gnss/Utils.h
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_UTILS_H
+#define _ANDROID_SERVER_GNSS_UTILS_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
+#include "jni.h"
+
+namespace android {
+
+namespace {
+
+// Must match the value from GnssMeasurement.java
+const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4);
+
+} // anonymous namespace
+
+extern jobject mCallbacksObj;
+
+jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage);
+
+jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage);
+
+void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
+
+template <class T>
+void logHidlError(hardware::Return<T>& result, const char* errorMessage) {
+    ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
+}
+
+template <class T>
+jboolean checkHidlReturn(hardware::Return<T>& result, const char* errorMessage) {
+    if (!result.isOk()) {
+        logHidlError(result, errorMessage);
+        return JNI_FALSE;
+    } else {
+        return JNI_TRUE;
+    }
+}
+
+template <class T>
+class JavaMethodHelper {
+public:
+    // Helper function to call setter on a Java object.
+    static void callJavaMethod(JNIEnv* env, jclass clazz, jobject object, const char* method_name,
+                               T value);
+
+private:
+    static const char* const signature_;
+};
+
+// Define Java method signatures for all known types.
+template <>
+const char* const JavaMethodHelper<uint8_t>::signature_;
+template <>
+const char* const JavaMethodHelper<int8_t>::signature_;
+template <>
+const char* const JavaMethodHelper<int16_t>::signature_;
+template <>
+const char* const JavaMethodHelper<uint16_t>::signature_;
+template <>
+const char* const JavaMethodHelper<int32_t>::signature_;
+template <>
+const char* const JavaMethodHelper<uint32_t>::signature_;
+template <>
+const char* const JavaMethodHelper<int64_t>::signature_;
+template <>
+const char* const JavaMethodHelper<uint64_t>::signature_;
+template <>
+const char* const JavaMethodHelper<float>::signature_;
+template <>
+const char* const JavaMethodHelper<double>::signature_;
+template <>
+const char* const JavaMethodHelper<bool>::signature_;
+template <>
+const char* const JavaMethodHelper<jstring>::signature_;
+template <>
+const char* const JavaMethodHelper<jdoubleArray>::signature_;
+
+template <class T>
+void JavaMethodHelper<T>::callJavaMethod(JNIEnv* env, jclass clazz, jobject object,
+                                         const char* method_name, T value) {
+    jmethodID method = env->GetMethodID(clazz, method_name, signature_);
+    env->CallVoidMethod(object, method, value);
+}
+
+class JavaObject {
+public:
+    JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor);
+    JavaObject(JNIEnv* env, jclass clazz, jmethodID stringCtor, const char* sz_arg_1);
+    JavaObject(JNIEnv* env, jclass clazz, jobject object);
+
+    virtual ~JavaObject() = default;
+
+    template <class T>
+    void callSetter(const char* method_name, T value);
+    template <class T>
+    void callSetter(const char* method_name, T* value, size_t size);
+    jobject get() { return object_; }
+
+private:
+    JNIEnv* env_;
+    jclass clazz_;
+    jobject object_;
+};
+
+template <class T>
+void JavaObject::callSetter(const char* method_name, T value) {
+    JavaMethodHelper<T>::callJavaMethod(env_, clazz_, object_, method_name, value);
+}
+
+#define SET(setter, value) object.callSetter("set" #setter, (value))
+
+class ScopedJniThreadAttach {
+public:
+    static JavaVM* sJvm;
+
+    ScopedJniThreadAttach() {
+        /*
+         * attachResult will also be JNI_OK if the thead was already attached to
+         * JNI before the call to AttachCurrentThread().
+         */
+        jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
+        LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
+                            attachResult);
+    }
+
+    ~ScopedJniThreadAttach() {
+        jint detachResult = sJvm->DetachCurrentThread();
+        /*
+         * Return if the thread was already detached. Log error for any other
+         * failure.
+         */
+        if (detachResult == JNI_EDETACHED) {
+            return;
+        }
+
+        LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
+                            detachResult);
+    }
+
+    JNIEnv* getEnv() {
+        /*
+         * Checking validity of mEnv in case the thread was detached elsewhere.
+         */
+        LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
+        return mEnv;
+    }
+
+private:
+    JNIEnv* mEnv = nullptr;
+};
+
+JNIEnv* getJniEnv();
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_GNSS_UTILS_H
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 5014503..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/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index bbd8de2..d670991 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -29,12 +29,19 @@
                     <xs:annotation name="nonnull"/>
                     <xs:annotation name="final"/>
                 </xs:element>
+                <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
             </xs:sequence>
         </xs:complexType>
     </xs:element>
 
     <!-- Type definitions -->
 
+    <xs:complexType name="displayQuirks">
+        <xs:sequence>
+            <xs:element name="quirk" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+    </xs:complexType>
+
     <xs:complexType name="nitsMap">
         <xs:sequence>
             <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 7a35642..e68ca26 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -3,10 +3,17 @@
 
   public class DisplayConfiguration {
     ctor public DisplayConfiguration();
+    method public com.android.server.display.config.DisplayQuirks getQuirks();
     method @NonNull public final com.android.server.display.config.NitsMap getScreenBrightnessMap();
+    method public void setQuirks(com.android.server.display.config.DisplayQuirks);
     method public final void setScreenBrightnessMap(@NonNull com.android.server.display.config.NitsMap);
   }
 
+  public class DisplayQuirks {
+    ctor public DisplayQuirks();
+    method public java.util.List<java.lang.String> getQuirk();
+  }
+
   public class NitsMap {
     ctor public NitsMap();
     method @NonNull public final java.util.List<com.android.server.display.config.Point> getPoint();
diff --git a/services/core/xsd/platform-compat-schema/OWNERS b/services/core/xsd/platform-compat-schema/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/services/core/xsd/platform-compat-schema/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/services/devicepolicy/OWNERS b/services/devicepolicy/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/services/devicepolicy/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index ce61d50..6f1d451e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -44,19 +44,19 @@
     /**
      * To be called by {@link DevicePolicyManagerService#Lifecycle} when a new user starts.
      *
-     * @see {@link SystemService#onStartUser}
+     * @see {@link SystemService#onUserStarting}
      */
     abstract void handleStartUser(int userId);
     /**
      * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being unlocked.
      *
-     * @see {@link SystemService#onUnlockUser}
+     * @see {@link SystemService#onUserUnlocking}
      */
     abstract void handleUnlockUser(int userId);
     /**
      * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being stopped.
      *
-     * @see {@link SystemService#onStopUser}
+     * @see {@link SystemService#onUserStopping}
      */
     abstract void handleStopUser(int userId);
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index 31ba199..7ec5ff0 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 {
@@ -411,7 +413,6 @@
                 policy.mPermissionPolicy = permissionPolicy;
             }
 
-            parser.next();
             int outerDepth = parser.getDepth();
             policy.mLockTaskPackages.clear();
             policy.mAdminList.clear();
@@ -556,4 +557,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 edcf9e8..0c00e3d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -124,6 +124,7 @@
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AppOpsManager.Mode;
 import android.app.BroadcastOptions;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
@@ -215,7 +216,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 +245,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 +939,7 @@
 
             // Persist updates if the removed package was an admin or delegate.
             if (removedAdmin || removedDelegate) {
-                saveSettingsLocked(policy.mUserHandle);
+                saveSettingsLocked(policy.mUserId);
             }
         }
         if (removedAdmin) {
@@ -1276,8 +1275,13 @@
         }
 
         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.newBuilder(mContext).setReason(reason).setShutdown(shutdown)
+                    .setForce(force).setWipeEuicc(wipeEuicc)
+                    .setWipeAdoptableStorage(wipeExtRequested)
+                    .setWipeFactoryResetProtection(wipeResetProtectionData)
+                    .build().factoryReset();
         }
 
         boolean systemPropertiesGetBoolean(String key, boolean def) {
@@ -2328,7 +2332,8 @@
                     + admin.info.getTagForPolicy(reqPolicy));
         } else {
             throw new SecurityException("No active admin owned by uid "
-                    + callingUid + " for policy #" + reqPolicy);
+                    + callingUid + " for policy #" + reqPolicy + (permission == null ? ""
+                    : ", which doesn't have " + permission));
         }
     }
 
@@ -2388,6 +2393,7 @@
      * If not provided, iterate over all of the active admins in the DevicePolicyData for that user
      * and return the one with the uid specified as parameter, and has the policy specified.
      */
+    @Nullable
     private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy,
             int uid) {
         ensureLocked();
@@ -3351,6 +3357,18 @@
                 PREVENT_SETTING_PASSWORD_QUALITY_ON_PARENT, packageName, userId);
     }
 
+    private boolean isPasswordLimitingAdminTargetingP(CallerIdentity caller) {
+        if (!caller.hasAdminComponent()) {
+            return false;
+        }
+
+        synchronized (getLockObject()) {
+            return getActiveAdminWithPolicyForUidLocked(
+                    caller.getComponentName(), DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD,
+                    caller.getUid()) != null;
+        }
+    }
+
     @Override
     public void setPasswordQuality(ComponentName who, int quality, boolean parent) {
         if (!mHasFeature) {
@@ -3361,12 +3379,13 @@
 
         final CallerIdentity caller = getCallerIdentity(who);
         Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDeviceOwner(caller) || isSystemUid(caller));
+                isProfileOwner(caller) || isDeviceOwner(caller) || isSystemUid(caller)
+                || isPasswordLimitingAdminTargetingP(caller));
 
         final boolean qualityMayApplyToParent =
                 canSetPasswordQualityOnParent(who.getPackageName(), caller.getUserId());
         if (!qualityMayApplyToParent) {
-            Preconditions.checkArgument(!parent,
+            Preconditions.checkCallAuthorization(!parent,
                     "Profile Owner may not apply password quality requirements device-wide");
         }
 
@@ -5190,6 +5209,44 @@
         return false;
     }
 
+    @Override
+    public List<String> getKeyPairGrants(String callerPackage, String alias) {
+        final CallerIdentity caller = getCallerIdentity(callerPackage);
+        Preconditions.checkCallAuthorization(canManageCertificates(caller));
+
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            try (KeyChainConnection keyChainConnection =
+                         KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
+                final List<String> result = new ArrayList<>();
+                final int[] granteeUids = keyChainConnection.getService().getGrants(alias);
+                final PackageManager pm = mInjector.getPackageManager(caller.getUserId());
+
+                // TODO: Return Set<Set<String>> when AIDL supports it: b/136048684
+                // Public API returns a set of sets, where each internal set contains all package
+                // names corresponding to the same UID. For now a set of sets is marshalled as a
+                // null-separated list.
+                for (final int uid : granteeUids) {
+                    final String[] packages = pm.getPackagesForUid(uid);
+                    if (packages == null) {
+                        Slog.wtf(LOG_TAG, "No packages found for uid " + uid);
+                        continue;
+                    }
+                    if (!result.isEmpty()) {
+                        result.add(null);
+                    }
+                    result.addAll(Arrays.asList(packages));
+                }
+                return result;
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Querying keypair grants", e);
+            } catch (InterruptedException e) {
+                Log.w(LOG_TAG, "Interrupted while querying keypair grants", e);
+                Thread.currentThread().interrupt();
+            }
+            return Collections.emptyList();
+        });
+    }
+
     /**
      * Enforce one the following conditions are met:
      * (1) The device has a Device Owner, and one of the following holds:
@@ -5865,25 +5922,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) {
@@ -6033,17 +6091,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);
@@ -6055,9 +6110,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);
@@ -6096,10 +6150,15 @@
 
         final ActiveAdmin admin;
         synchronized (getLockObject()) {
-            admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA);
+            admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
+                    DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
         }
-        Preconditions.checkCallAuthorization(admin != null,
-                "No active admin for user %d", caller.getUserId());
+
+        Preconditions.checkCallAuthorization(
+                (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
+                "No active admin for user %d and caller %d does not hold MASTER_CLEAR permission",
+                caller.getUserId(), caller.getUid());
+        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_WIPE_DATA);
 
         if (TextUtils.isEmpty(wipeReasonForUser)) {
             if (calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance) {
@@ -6110,7 +6169,10 @@
             }
         }
 
-        int userId = admin.getUserHandle().getIdentifier();
+        int userId = admin != null ? admin.getUserHandle().getIdentifier()
+                : caller.getUserId();
+        Slog.i(LOG_TAG, String.format("wipeDataWithReason(%s): admin=%s, user=%d",
+                wipeReasonForUser, admin, userId));
         if (calledByProfileOwnerOnOrgOwnedDevice) {
             // When wipeData is called on the parent instance, it implies wiping the entire device.
             if (calledOnParentInstance) {
@@ -6133,20 +6195,35 @@
                 });
             }
         }
-
-        DevicePolicyEventLogger
+        DevicePolicyEventLogger event = DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.WIPE_DATA_WITH_REASON)
-                .setAdmin(admin.info.getComponent())
                 .setInt(flags)
                 .setStrings(calledOnParentInstance ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
-                .write();
+                ;
+        final String adminName;
+        final ComponentName adminComp;
+        if (admin != null) {
+            adminComp = admin.info.getComponent();
+            adminName = adminComp.flattenToShortString();
+            event.setAdmin(adminComp);
+        } else {
+            adminComp = null;
+            adminName = mInjector.getPackageManager().getPackagesForUid(caller.getUid())[0];
+            Slog.i(LOG_TAG, "Logging wipeData() event admin as " + adminName);
+            event.setAdmin(adminName);
+            if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+                // On headless system user mode, the call is meant to factory reset the whole
+                // device, otherwise the caller could simply remove the current user.
+                userId = UserHandle.USER_SYSTEM;
+            }
+        }
+        event.write();
+
         String internalReason = String.format(
                 "DevicePolicyManager.wipeDataWithReason() from %s, organization-owned? %s",
-                admin.info.getComponent().flattenToShortString(),
-                calledByProfileOwnerOnOrgOwnedDevice);
+                adminName, calledByProfileOwnerOnOrgOwnedDevice);
 
-        wipeDataNoLock(
-                admin.info.getComponent(), flags, internalReason, wipeReasonForUser, userId);
+        wipeDataNoLock(adminComp, flags, internalReason, wipeReasonForUser, userId);
     }
 
     private void wipeDataNoLock(ComponentName admin, int flags, String internalReason,
@@ -6168,22 +6245,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);
             }
@@ -7509,9 +7576,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;
         }
@@ -8496,16 +8569,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));
         }
     }
 
@@ -8633,6 +8709,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);
@@ -8684,37 +8769,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);
         }
     }
 
@@ -9574,7 +9629,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(),
@@ -9595,43 +9650,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);
         }
     }
 
@@ -9750,6 +9796,7 @@
         Objects.requireNonNull(who, "ComponentName is null");
         final CallerIdentity caller = getCallerIdentity(who);
         Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOGOUT_USER);
 
         final int callingUserId = caller.getUserId();
         synchronized (getLockObject()) {
@@ -9935,6 +9982,7 @@
                     throw new SecurityException("Profile owner cannot set user restriction " + key);
                 }
             }
+            checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
 
             // Save the restriction to ActiveAdmin.
             final Bundle restrictions = activeAdmin.ensureUserRestrictions();
@@ -11742,6 +11790,28 @@
             return profileOwnerInCallingUser != null
                     && packageName.equals(profileOwnerInCallingUser.getPackageName());
         }
+
+        @Override
+        public boolean supportsResetOp(int op) {
+            return op == AppOpsManager.OP_INTERACT_ACROSS_PROFILES
+                    && LocalServices.getService(CrossProfileAppsInternal.class) != null;
+        }
+
+        @Override
+        public void resetOp(int op, String packageName, @UserIdInt int userId) {
+            if (op != AppOpsManager.OP_INTERACT_ACROSS_PROFILES) {
+                throw new IllegalArgumentException("Unsupported op for DPM reset: " + op);
+            }
+            LocalServices.getService(CrossProfileAppsInternal.class)
+                    .setInteractAcrossProfilesAppOp(
+                            packageName, findInteractAcrossProfilesResetMode(packageName), userId);
+        }
+
+        private @Mode int findInteractAcrossProfilesResetMode(String packageName) {
+            return getDefaultCrossProfilePackages().contains(packageName)
+                    ? AppOpsManager.MODE_ALLOWED
+                    : AppOpsManager.opToDefaultMode(AppOpsManager.OP_INTERACT_ACROSS_PROFILES);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -12260,7 +12330,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;
@@ -12276,6 +12346,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.
@@ -12287,6 +12366,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;
                 }
@@ -12318,7 +12406,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);
         }
     }
@@ -12502,7 +12590,7 @@
         Objects.requireNonNull(admin, "ComponentName is null");
         final CallerIdentity caller = getCallerIdentity(admin);
         Preconditions.checkCallAuthorization(isDeviceOwner(caller));
-
+        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REBOOT);
         mInjector.binderWithCleanCallingIdentity(() -> {
             // Make sure there are no ongoing calls on the device.
             if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
@@ -13416,14 +13504,16 @@
         final CallerIdentity caller = getCallerIdentity(admin);
         Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
 
-        synchronized (getLockObject()) {
-            try {
-                IBackupManager ibm = mInjector.getIBackupManager();
-                return ibm != null && ibm.isBackupServiceActive(caller.getUserId());
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Failed requesting backup service state.", e);
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            synchronized (getLockObject()) {
+                try {
+                    IBackupManager ibm = mInjector.getIBackupManager();
+                    return ibm != null && ibm.isBackupServiceActive(caller.getUserId());
+                } catch (RemoteException e) {
+                    throw new IllegalStateException("Failed requesting backup service state.", e);
+                }
             }
-        }
+        });
     }
 
     @Override
@@ -14855,8 +14945,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..a0cf7a3
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.annotation.Nullable;
+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;
+import java.util.Objects;
+
+/**
+ * Entry point for "factory reset" requests.
+ */
+public final class FactoryResetter {
+
+    private static final String TAG = FactoryResetter.class.getSimpleName();
+
+    private final Context mContext;
+    private final @Nullable String mReason;
+    private final boolean mShutdown;
+    private final boolean mForce;
+    private final boolean mWipeEuicc;
+    private final boolean mWipeAdoptableStorage;
+    private final boolean mWipeFactoryResetProtection;
+
+
+    /**
+     * Factory reset the device according to the builder's arguments.
+     */
+    public void factoryReset() throws IOException {
+        Log.i(TAG, String.format("factoryReset(): reason=%s, shutdown=%b, force=%b, wipeEuicc=%b"
+                + ", wipeAdoptableStorage=%b, wipeFRP=%b", mReason, mShutdown, mForce, mWipeEuicc,
+                mWipeAdoptableStorage, mWipeFactoryResetProtection));
+
+        Preconditions.checkCallAuthorization(mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED);
+
+        UserManager um = mContext.getSystemService(UserManager.class);
+        if (!mForce && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
+            throw new SecurityException("Factory reset is not allowed for this user.");
+        }
+
+        if (mWipeFactoryResetProtection) {
+            PersistentDataBlockManager manager = mContext
+                    .getSystemService(PersistentDataBlockManager.class);
+            if (manager != null) {
+                Log.w(TAG, "Wiping factory reset protection");
+                manager.wipe();
+            } else {
+                Log.w(TAG, "No need to wipe factory reset protection");
+            }
+        }
+
+        if (mWipeAdoptableStorage) {
+            Log.w(TAG, "Wiping adoptable storage");
+            StorageManager sm = mContext.getSystemService(StorageManager.class);
+            sm.wipeAdoptableDisks();
+        }
+
+        RecoverySystem.rebootWipeUserData(mContext, mShutdown, mReason, mForce, mWipeEuicc);
+    }
+
+    private FactoryResetter(Builder builder) {
+        mContext = builder.mContext;
+        mShutdown = builder.mShutdown;
+        mReason = builder.mReason;
+        mForce = builder.mForce;
+        mWipeEuicc = builder.mWipeEuicc;
+        mWipeAdoptableStorage = builder.mWipeAdoptableStorage;
+        mWipeFactoryResetProtection = builder.mWipeFactoryResetProtection;
+    }
+
+    /**
+     * Creates a new builder.
+     */
+    public static Builder newBuilder(Context context) {
+        return new Builder(context);
+    }
+
+    /**
+     * Builder for {@link FactoryResetter} instances.
+     */
+    public static final class Builder {
+
+        private final Context mContext;
+        private @Nullable String mReason;
+        private boolean mShutdown;
+        private boolean mForce;
+        private boolean mWipeEuicc;
+        private boolean mWipeAdoptableStorage;
+        private boolean mWipeFactoryResetProtection;
+
+        private Builder(Context context) {
+            mContext = Objects.requireNonNull(context);
+        }
+
+        /**
+         * Sets the (non-null) reason for the factory reset that is visible in the logs
+         */
+        public Builder setReason(String reason) {
+            mReason = Objects.requireNonNull(reason);
+            return this;
+        }
+
+        /**
+         * Sets whether the device will be powered down after the wipe completes, rather than being
+         * rebooted back to the regular system.
+         */
+        public Builder setShutdown(boolean value) {
+            mShutdown = value;
+            return this;
+        }
+
+        /**
+         * Sets whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction should be
+         * ignored.
+         */
+        public Builder setForce(boolean value) {
+            mForce = value;
+            return this;
+        }
+
+        /**
+         * Sets whether to wipe the {@code euicc} data.
+         */
+        public Builder setWipeEuicc(boolean value) {
+            mWipeEuicc = value;
+            return this;
+        }
+
+        /**
+         * Sets whether to wipe the adoptable external storage (if any).
+         */
+        public Builder setWipeAdoptableStorage(boolean value) {
+            mWipeAdoptableStorage = value;
+            return this;
+        }
+
+        /**
+         * Sets whether to reset the factory reset protection.
+         */
+        public Builder setWipeFactoryResetProtection(boolean value) {
+            mWipeFactoryResetProtection = value;
+            return this;
+        }
+
+        /**
+         * Builds the {@link FactoryResetter} instance.
+         */
+        public FactoryResetter build() {
+            return new FactoryResetter(this);
+        }
+    }
+}
diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/incremental/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6525e11..69e29d6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -323,6 +323,8 @@
             "com.android.server.appprediction.AppPredictionManagerService";
     private static final String CONTENT_SUGGESTIONS_SERVICE_CLASS =
             "com.android.server.contentsuggestions.ContentSuggestionsManagerService";
+    private static final String SEARCH_UI_MANAGER_SERVICE_CLASS =
+            "com.android.server.searchui.SearchUiManagerService";
     private static final String DEVICE_IDLE_CONTROLLER_CLASS =
             "com.android.server.DeviceIdleController";
     private static final String BLOB_STORE_MANAGER_SERVICE_CLASS =
@@ -1252,6 +1254,10 @@
             mSystemServiceManager.startService(DropBoxManagerService.class);
             t.traceEnd();
 
+            t.traceBegin("StartVibratorManagerService");
+            mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class);
+            t.traceEnd();
+
             t.traceBegin("StartVibratorService");
             vibrator = new VibratorService(context);
             ServiceManager.addService("vibrator", vibrator);
@@ -1277,6 +1283,10 @@
             inputManager = new InputManagerService(context);
             t.traceEnd();
 
+            t.traceBegin("DeviceStateManagerService");
+            mSystemServiceManager.startService(DeviceStateManagerService.class);
+            t.traceEnd();
+
             if (!disableCameraService) {
                 t.traceBegin("StartCameraServiceProxy");
                 mSystemServiceManager.startService(CameraServiceProxy.class);
@@ -1370,10 +1380,6 @@
             mSystemServiceManager.startService(AppIntegrityManagerService.class);
             t.traceEnd();
 
-            t.traceBegin("DeviceStateManagerService");
-            mSystemServiceManager.startService(DeviceStateManagerService.class);
-            t.traceEnd();
-
         } catch (Throwable e) {
             Slog.e("System", "******************************************");
             Slog.e("System", "************ Failure starting core service");
@@ -1567,6 +1573,12 @@
                 Slog.d(TAG, "ContentSuggestionsService not defined by OEM");
             }
 
+            // Search UI manager service
+            // TODO: add deviceHasConfigString(context, R.string.config_defaultSearchUiService)
+            t.traceBegin("StartSearchUiService");
+            mSystemServiceManager.startService(SEARCH_UI_MANAGER_SERVICE_CLASS);
+            t.traceEnd();
+
             t.traceBegin("InitConnectivityModuleConnector");
             try {
                 ConnectivityModuleConnector.getInstance().init(context);
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
index e258ef0..3531512 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
@@ -113,7 +113,8 @@
 
             mRemoteService = new RemoteMusicRecognitionService(getContext(),
                     serviceComponent, mUserId, this,
-                    mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+                    mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(),
+                    mMaster.verbose);
         }
 
         return mRemoteService;
@@ -167,7 +168,8 @@
                         recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
                 audioRecord.startRecording();
                 while (bytesRead >= 0 && totalBytesRead
-                        < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE) {
+                        < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE
+                        && mRemoteService != null) {
                     bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
                     if (bytesRead > 0) {
                         totalBytesRead += bytesRead;
@@ -215,6 +217,7 @@
             } catch (RemoteException ignored) {
                 // Ignored.
             }
+            destroyService();
         }
 
         @Override
@@ -224,6 +227,7 @@
             } catch (RemoteException ignored) {
                 // Ignored.
             }
+            destroyService();
         }
     }
 
@@ -235,6 +239,17 @@
             // Ignored.
         }
         Slog.w(TAG, "remote service died: " + service);
+        destroyService();
+    }
+
+    @GuardedBy("mLock")
+    private void destroyService() {
+        synchronized (mLock) {
+            if (mRemoteService != null) {
+                mRemoteService.destroy();
+                mRemoteService = null;
+            }
+        }
     }
 
     /** Establishes an audio stream from the DSP audio source. */
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
index b4cb337..9123daf 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.musicrecognition;
 
+import static android.Manifest.permission.MANAGE_MUSIC_RECOGNITION;
 import static android.content.PermissionChecker.PERMISSION_GRANTED;
 import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
 
@@ -28,11 +29,14 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
 
+import java.io.FileDescriptor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -45,6 +49,7 @@
                 MusicRecognitionManagerPerUserService> {
 
     private static final String TAG = MusicRecognitionManagerService.class.getSimpleName();
+    private static final int MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS = 60_000;
 
     private MusicRecognitionManagerStub mMusicRecognitionManagerStub;
     final ExecutorService mExecutorService = Executors.newCachedThreadPool();
@@ -90,6 +95,16 @@
         throw new SecurityException(msg);
     }
 
+    @Override
+    protected void enforceCallingPermissionForManagement() {
+        getContext().enforceCallingPermission(MANAGE_MUSIC_RECOGNITION, TAG);
+    }
+
+    @Override
+    protected int getMaximumTemporaryServiceDurationMs() {
+        return MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS;
+    }
+
     final class MusicRecognitionManagerStub extends IMusicRecognitionManager.Stub {
         @Override
         public void beginRecognition(
@@ -112,5 +127,17 @@
                 }
             }
         }
+
+        @Override
+        public void onShellCommand(@Nullable FileDescriptor in,
+                @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err,
+                @NonNull String[] args,
+                @Nullable ShellCallback callback,
+                @NonNull ResultReceiver resultReceiver) throws RemoteException {
+            new MusicRecognitionManagerServiceShellCommand(
+                    MusicRecognitionManagerService.this).exec(this, in, out, err, args, callback,
+                    resultReceiver);
+        }
     }
 }
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java
new file mode 100644
index 0000000..b020a24
--- /dev/null
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java
@@ -0,0 +1,80 @@
+/*
+ * 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.musicrecognition;
+
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+/** Handles adb shell commands send to MusicRecognitionManagerService. */
+class MusicRecognitionManagerServiceShellCommand extends ShellCommand {
+
+    private final MusicRecognitionManagerService mService;
+
+    MusicRecognitionManagerServiceShellCommand(MusicRecognitionManagerService service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        final PrintWriter pw = getOutPrintWriter();
+        if ("set".equals(cmd)) {
+            return requestSet(pw);
+        }
+        return handleDefaultCommands(cmd);
+    }
+
+    private int requestSet(PrintWriter pw) {
+        final String what = getNextArgRequired();
+        if ("temporary-service".equals(what)) {
+            return setTemporaryService(pw);
+        }
+        pw.println("Invalid set: " + what);
+        return -1;
+    }
+
+    private int setTemporaryService(PrintWriter pw) {
+        final int userId = Integer.parseInt(getNextArgRequired());
+        final String serviceName = getNextArg();
+        if (serviceName == null) {
+            mService.resetTemporaryService(userId);
+            return 0;
+        }
+        final int duration = Integer.parseInt(getNextArgRequired());
+        mService.setTemporaryService(userId, serviceName, duration);
+        pw.println("MusicRecognitionService temporarily set to " + serviceName + " for "
+                + duration + "ms");
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        try (PrintWriter pw = getOutPrintWriter();) {
+            pw.println("MusicRecognition Service (music_recognition) commands:");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  set temporary-service USER_ID [COMPONENT_NAME DURATION]");
+            pw.println("    Temporarily (for DURATION ms) changes the service implementation.");
+            pw.println("    To reset, call with just the USER_ID argument.");
+            pw.println("");
+        }
+    }
+}
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/people/OWNERS b/services/people/OWNERS
new file mode 100644
index 0000000..7ac9b73
--- /dev/null
+++ b/services/people/OWNERS
@@ -0,0 +1,2 @@
+danningc@google.com
+juliacr@google.com
diff --git a/services/print/OWNERS b/services/print/OWNERS
new file mode 100644
index 0000000..2c7b881
--- /dev/null
+++ b/services/print/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/print/OWNERS
diff --git a/services/restrictions/OWNERS b/services/restrictions/OWNERS
new file mode 100644
index 0000000..95e614c
--- /dev/null
+++ b/services/restrictions/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/restrictions/OWNERS
diff --git a/services/robotests/backup/OWNERS b/services/robotests/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/robotests/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/robotests/src/com/android/server/backup/OWNERS b/services/robotests/src/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/robotests/src/com/android/server/location/OWNERS b/services/robotests/src/com/android/server/location/OWNERS
new file mode 100644
index 0000000..696a0c2
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/OWNERS
@@ -0,0 +1 @@
+file:/location/java/android/location/OWNERS
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 5fa809f..adf892a 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -37,7 +37,6 @@
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.Mode;
-import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
 import android.content.ContextWrapper;
@@ -94,12 +93,15 @@
     private static final int CALLING_PID = 1000;
     private static final String CROSS_PROFILE_APP_PACKAGE_NAME =
             "com.android.server.pm.crossprofileappsserviceimplrobotest.crossprofileapp";
-    private static final int PERSONAL_PROFILE_USER_ID = 0;
+    @UserIdInt private static final int PERSONAL_PROFILE_USER_ID = 0;
     private static final int PERSONAL_PROFILE_UID = 2222;
-    private static final int WORK_PROFILE_USER_ID = 10;
+    @UserIdInt private static final int WORK_PROFILE_USER_ID = 10;
     private static final int WORK_PROFILE_UID = 3333;
     private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20;
-    private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30;
+    @UserIdInt private static final int OTHER_PROFILE_GROUP_USER_ID = 30;
+    private static final int OTHER_PROFILE_GROUP_UID = 4444;
+    @UserIdInt private static final int OTHER_PROFILE_GROUP_2_USER_ID = 31;
+    private static final int OTHER_PROFILE_GROUP_2_UID = 5555;
 
     private final ContextWrapper mContext = ApplicationProvider.getApplicationContext();
     private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
@@ -138,6 +140,10 @@
         mockCrossProfileAppInstalledOnProfile(
                 packageInfo, PERSONAL_PROFILE_USER_ID, PERSONAL_PROFILE_UID);
         mockCrossProfileAppInstalledOnProfile(packageInfo, WORK_PROFILE_USER_ID, WORK_PROFILE_UID);
+        mockCrossProfileAppInstalledOnProfile(
+                packageInfo, OTHER_PROFILE_GROUP_USER_ID, OTHER_PROFILE_GROUP_UID);
+        mockCrossProfileAppInstalledOnProfile(
+                packageInfo, OTHER_PROFILE_GROUP_2_USER_ID, OTHER_PROFILE_GROUP_2_UID);
     }
 
     private void mockCrossProfileAppInstalledOnProfile(
@@ -200,16 +206,22 @@
 
     @Before
     public void setUpCrossProfileAppUidsAndPackageNames() {
+        setUpCrossProfileAppUidAndPackageName(
+                PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
+        setUpCrossProfileAppUidAndPackageName(
+                WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
+        setUpCrossProfileAppUidAndPackageName(
+                OTHER_PROFILE_GROUP_UID, OTHER_PROFILE_GROUP_USER_ID);
+        setUpCrossProfileAppUidAndPackageName(
+                OTHER_PROFILE_GROUP_2_UID, OTHER_PROFILE_GROUP_2_USER_ID);
+    }
+
+    private void setUpCrossProfileAppUidAndPackageName(int uid, @UserIdInt int userId) {
         ShadowApplicationPackageManager.setPackageUidAsUser(
-                CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
-        ShadowApplicationPackageManager.setPackageUidAsUser(
-                CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
-        when(mPackageManagerInternal.getPackageUid(
-                CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
-                .thenReturn(PERSONAL_PROFILE_UID);
-        when(mPackageManagerInternal.getPackageUid(
-                CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
-                .thenReturn(WORK_PROFILE_UID);
+                CROSS_PROFILE_APP_PACKAGE_NAME, uid, userId);
+        when(mPackageManagerInternal
+                .getPackageUid(CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, userId))
+                .thenReturn(uid);
     }
 
     @Before
@@ -229,7 +241,9 @@
                 PERSONAL_PROFILE_USER_ID,
                 WORK_PROFILE_USER_ID,
                 OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID);
-        shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID);
+        shadowUserManager.addProfileIds(
+                OTHER_PROFILE_GROUP_USER_ID,
+                OTHER_PROFILE_GROUP_2_USER_ID);
     }
 
     @Before
@@ -239,6 +253,8 @@
         final int defaultMode = AppOpsManager.opToDefaultMode(OP_INTERACT_ACROSS_PROFILES);
         explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, defaultMode);
         explicitlySetInteractAcrossProfilesAppOp(WORK_PROFILE_UID, defaultMode);
+        explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_UID, defaultMode);
+        explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_2_UID, defaultMode);
     }
 
     @Test
@@ -422,6 +438,27 @@
     }
 
     @Test
+    public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOp() {
+        mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+        assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_UID)).isEqualTo(MODE_ALLOWED);
+    }
+
+    @Test
+    public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOpOnOtherProfile() {
+        mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+        assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_2_UID)).isEqualTo(MODE_ALLOWED);
+    }
+
+    @Test
+    public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_doesNotSetCallerAppOp() {
+        mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+        assertThat(getCrossProfileAppOp()).isEqualTo(MODE_DEFAULT);
+    }
+
+    @Test
     public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
         mockUninstallCrossProfileAppFromWorkProfile();
         assertThat(mCrossProfileAppsServiceImpl
@@ -530,7 +567,7 @@
 
     @Test
     public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() {
-        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID))
+        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OTHER_PROFILE_GROUP_USER_ID))
                 .thenReturn(buildCrossProfileComponentName());
         assertThat(mCrossProfileAppsServiceImpl
                 .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -601,8 +638,14 @@
     private void mockCrossProfileAndroidPackage(AndroidPackage androidPackage) {
         when(mPackageManagerInternal.getPackage(CROSS_PROFILE_APP_PACKAGE_NAME))
                 .thenReturn(androidPackage);
-        when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID)).thenReturn(androidPackage);
-        when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)).thenReturn(androidPackage);
+        when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID))
+                .thenReturn(androidPackage);
+        when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID))
+                .thenReturn(androidPackage);
+        when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_UID))
+                .thenReturn(androidPackage);
+        when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_2_UID))
+                .thenReturn(androidPackage);
     }
 
     private void mockCrossProfileAppNotWhitelisted() {
diff --git a/services/robotests/src/com/android/server/pm/OWNERS b/services/robotests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/robotests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/searchui/Android.bp b/services/searchui/Android.bp
new file mode 100644
index 0000000..cc63294
--- /dev/null
+++ b/services/searchui/Android.bp
@@ -0,0 +1,13 @@
+filegroup {
+    name: "services.searchui-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
+java_library_static {
+    name: "services.searchui",
+    defaults: ["platform_service_defaults"],
+    srcs: [":services.searchui-sources"],
+    libs: ["services.core"],
+}
diff --git a/services/searchui/java/com/android/server/searchui/RemoteSearchUiService.java b/services/searchui/java/com/android/server/searchui/RemoteSearchUiService.java
new file mode 100644
index 0000000..706d2aa
--- /dev/null
+++ b/services/searchui/java/com/android/server/searchui/RemoteSearchUiService.java
@@ -0,0 +1,112 @@
+/*
+ * 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.searchui;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.service.search.ISearchUiService;
+import android.text.format.DateUtils;
+
+import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
+
+
+/**
+ * Proxy to the {@link android.service.searchui.SearchUiService} implementation in another
+ * process.
+ */
+public class RemoteSearchUiService extends
+        AbstractMultiplePendingRequestsRemoteService<RemoteSearchUiService,
+                ISearchUiService> {
+
+    private static final String TAG = "RemoteSearchUiService";
+
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+    private final RemoteSearchUiServiceCallbacks mCallback;
+
+    public RemoteSearchUiService(Context context, String serviceInterface,
+            ComponentName componentName, int userId,
+            RemoteSearchUiServiceCallbacks callback, boolean bindInstantServiceAllowed,
+            boolean verbose) {
+        super(context, serviceInterface, componentName, userId, callback,
+                context.getMainThreadHandler(),
+                bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
+                verbose, /* initialCapacity= */ 1);
+        mCallback = callback;
+    }
+
+    @Override
+    protected ISearchUiService getServiceInterface(IBinder service) {
+        return ISearchUiService.Stub.asInterface(service);
+    }
+
+    @Override
+    protected long getTimeoutIdleBindMillis() {
+        return PERMANENT_BOUND_TIMEOUT_MS;
+    }
+
+    @Override
+    protected long getRemoteRequestMillis() {
+        return TIMEOUT_REMOTE_REQUEST_MILLIS;
+    }
+
+    /**
+     * Schedules a request to bind to the remote service.
+     */
+    public void reconnect() {
+        super.scheduleBind();
+    }
+
+    /**
+     * Schedule async request on remote service.
+     */
+    public void scheduleOnResolvedService(@NonNull AsyncRequest<ISearchUiService> request) {
+        scheduleAsyncRequest(request);
+    }
+
+    /**
+     * Execute async request on remote service immediately instead of sending it to Handler queue.
+     */
+    public void executeOnResolvedService(@NonNull AsyncRequest<ISearchUiService> request) {
+        executeAsyncRequest(request);
+    }
+
+    /**
+     * Failure callback
+     */
+    public interface RemoteSearchUiServiceCallbacks
+            extends VultureCallback<RemoteSearchUiService> {
+
+        /**
+         * Notifies a the failure or timeout of a remote call.
+         */
+        void onFailureOrTimeout(boolean timedOut);
+
+        /**
+         * Notifies change in connected state of the remote service.
+         */
+        void onConnectedStateChanged(boolean connected);
+    }
+
+    @Override // from AbstractRemoteService
+    protected void handleOnConnectedStateChanged(boolean connected) {
+        if (mCallback != null) {
+            mCallback.onConnectedStateChanged(connected);
+        }
+    }
+}
diff --git a/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java b/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java
new file mode 100644
index 0000000..524002a
--- /dev/null
+++ b/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.searchui;
+
+import static android.Manifest.permission.MANAGE_SEARCH_UI;
+import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
+import static android.content.Context.SEARCH_UI_SERVICE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.app.search.ISearchCallback;
+import android.app.search.ISearchUiManager;
+import android.app.search.Query;
+import android.app.search.SearchContext;
+import android.app.search.SearchSessionId;
+import android.app.search.SearchTargetEvent;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.infra.AbstractMasterSystemService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
+import com.android.server.wm.ActivityTaskManagerInternal;
+
+import java.io.FileDescriptor;
+import java.util.function.Consumer;
+
+/**
+ * A service used to return search targets given a query.
+ */
+public class SearchUiManagerService extends
+        AbstractMasterSystemService<SearchUiManagerService, SearchUiPerUserService> {
+
+    private static final String TAG = SearchUiManagerService.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
+
+    private ActivityTaskManagerInternal mActivityTaskManagerInternal;
+
+    public SearchUiManagerService(Context context) {
+        super(context, new FrameworkResourcesServiceNameResolver(context,
+                com.android.internal.R.string.config_defaultSearchUiService), null,
+                PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH);
+        mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+    }
+
+    @Override
+    protected SearchUiPerUserService newServiceLocked(int resolvedUserId, boolean disabled) {
+        return new SearchUiPerUserService(this, mLock, resolvedUserId);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(SEARCH_UI_SERVICE, new SearchUiManagerStub());
+    }
+
+    @Override
+    protected void enforceCallingPermissionForManagement() {
+        getContext().enforceCallingPermission(MANAGE_SEARCH_UI, TAG);
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
+        final SearchUiPerUserService service = peekServiceForUserLocked(userId);
+        if (service != null) {
+            service.onPackageUpdatedLocked();
+        }
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
+        final SearchUiPerUserService service = peekServiceForUserLocked(userId);
+        if (service != null) {
+            service.onPackageRestartedLocked();
+        }
+    }
+
+    @Override
+    protected int getMaximumTemporaryServiceDurationMs() {
+        return MAX_TEMP_SERVICE_DURATION_MS;
+    }
+
+    private class SearchUiManagerStub extends ISearchUiManager.Stub {
+
+        @Override
+        public void createSearchSession(@NonNull SearchContext context,
+                @NonNull SearchSessionId sessionId, @NonNull IBinder token) {
+            runForUserLocked("createSearchSession", sessionId, (service) ->
+                    service.onCreateSearchSessionLocked(context, sessionId, token));
+        }
+
+        @Override
+        public void notifyEvent(@NonNull SearchSessionId sessionId, @NonNull Query query,
+                @NonNull SearchTargetEvent event) {
+            runForUserLocked("notifyEvent", sessionId,
+                    (service) -> service.notifyLocked(sessionId, query, event));
+        }
+
+        @Override
+        public void query(@NonNull SearchSessionId sessionId,
+                @NonNull Query query,
+                ISearchCallback callback) {
+            runForUserLocked("query", sessionId,
+                    (service) -> service.queryLocked(sessionId, query, callback));
+        }
+
+        @Override
+        public void destroySearchSession(@NonNull SearchSessionId sessionId) {
+            runForUserLocked("destroySearchSession", sessionId,
+                    (service) -> service.onDestroyLocked(sessionId));
+        }
+
+        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err,
+                @NonNull String[] args, @Nullable ShellCallback callback,
+                @NonNull ResultReceiver resultReceiver) {
+            new SearchUiManagerServiceShellCommand(SearchUiManagerService.this)
+                    .exec(this, in, out, err, args, callback, resultReceiver);
+        }
+
+        private void runForUserLocked(@NonNull final String func,
+                @NonNull final SearchSessionId sessionId,
+                @NonNull final Consumer<SearchUiPerUserService> c) {
+            ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
+            final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                    sessionId.getUserId(), false, ALLOW_NON_FULL, null, null);
+
+            if (DEBUG) {
+                Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+            }
+            if (!(mServiceNameResolver.isTemporary(userId)
+                    || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
+
+                String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid();
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    final SearchUiPerUserService service = getServiceForUserLocked(userId);
+                    c.accept(service);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+}
diff --git a/services/searchui/java/com/android/server/searchui/SearchUiManagerServiceShellCommand.java b/services/searchui/java/com/android/server/searchui/SearchUiManagerServiceShellCommand.java
new file mode 100644
index 0000000..24d74fb
--- /dev/null
+++ b/services/searchui/java/com/android/server/searchui/SearchUiManagerServiceShellCommand.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.searchui;
+
+import android.annotation.NonNull;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+/**
+ * The shell command implementation for the SearchUiManagerService.
+ */
+public class SearchUiManagerServiceShellCommand extends ShellCommand {
+
+    private static final String TAG =
+            SearchUiManagerServiceShellCommand.class.getSimpleName();
+
+    private final SearchUiManagerService mService;
+
+    public SearchUiManagerServiceShellCommand(@NonNull SearchUiManagerService service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        final PrintWriter pw = getOutPrintWriter();
+        switch (cmd) {
+            case "set": {
+                final String what = getNextArgRequired();
+                switch (what) {
+                    case "temporary-service": {
+                        final int userId = Integer.parseInt(getNextArgRequired());
+                        String serviceName = getNextArg();
+                        if (serviceName == null) {
+                            mService.resetTemporaryService(userId);
+                            pw.println("SearchUiService temporarily reset. ");
+                            return 0;
+                        }
+                        final int duration = Integer.parseInt(getNextArgRequired());
+                        mService.setTemporaryService(userId, serviceName, duration);
+                        pw.println("SearchUiService temporarily set to " + serviceName
+                                + " for " + duration + "ms");
+                        break;
+                    }
+                }
+            }
+            break;
+            default:
+                return handleDefaultCommands(cmd);
+        }
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        try (PrintWriter pw = getOutPrintWriter()) {
+            pw.println("SearchUiManagerService commands:");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  set temporary-service USER_ID [COMPONENT_NAME DURATION]");
+            pw.println("    Temporarily (for DURATION ms) changes the service implemtation.");
+            pw.println("    To reset, call with just the USER_ID argument.");
+            pw.println("");
+        }
+    }
+}
diff --git a/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java b/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java
new file mode 100644
index 0000000..4c31978
--- /dev/null
+++ b/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java
@@ -0,0 +1,374 @@
+/*
+ * 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.searchui;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppGlobals;
+import android.app.search.ISearchCallback;
+import android.app.search.Query;
+import android.app.search.SearchContext;
+import android.app.search.SearchSessionId;
+import android.app.search.SearchTargetEvent;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.service.search.ISearchUiService;
+import android.service.search.SearchUiService;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.AbstractRemoteService;
+import com.android.server.infra.AbstractPerUserSystemService;
+
+/**
+ * Per-user instance of {@link SearchUiManagerService}.
+ */
+public class SearchUiPerUserService extends
+        AbstractPerUserSystemService<SearchUiPerUserService, SearchUiManagerService>
+             implements RemoteSearchUiService.RemoteSearchUiServiceCallbacks {
+
+    private static final String TAG = SearchUiPerUserService.class.getSimpleName();
+
+    @Nullable
+    @GuardedBy("mLock")
+    private RemoteSearchUiService mRemoteService;
+
+    /**
+     * When {@code true}, remote service died but service state is kept so it's restored after
+     * the system re-binds to it.
+     */
+    @GuardedBy("mLock")
+    private boolean mZombie;
+
+    @GuardedBy("mLock")
+    private final ArrayMap<SearchSessionId, SearchSessionInfo> mSessionInfos =
+            new ArrayMap<>();
+
+    protected SearchUiPerUserService(SearchUiManagerService master,
+            Object lock, int userId) {
+        super(master, lock, userId);
+    }
+
+    @Override // from PerUserSystemService
+    protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
+            throws NameNotFoundException {
+
+        ServiceInfo si;
+        try {
+            si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
+                    PackageManager.GET_META_DATA, mUserId);
+        } catch (RemoteException e) {
+            throw new NameNotFoundException("Could not get service for " + serviceComponent);
+        }
+        // TODO(b/111701043): must check that either the service is from a system component,
+        // or it matches a service set by shell cmd (so it can be used on CTS tests and when
+        // OEMs are implementing the real service and also verify the proper permissions
+        return si;
+    }
+
+    @GuardedBy("mLock")
+    @Override // from PerUserSystemService
+    protected boolean updateLocked(boolean disabled) {
+        final boolean enabledChanged = super.updateLocked(disabled);
+        if (enabledChanged) {
+            if (!isEnabledLocked()) {
+                // Clear the remote service for the next call
+                updateRemoteServiceLocked();
+            }
+        }
+        return enabledChanged;
+    }
+
+    /**
+     * Notifies the service of a new search session.
+     */
+    @GuardedBy("mLock")
+    public void onCreateSearchSessionLocked(@NonNull SearchContext context,
+            @NonNull SearchSessionId sessionId, @NonNull IBinder token) {
+        final boolean serviceExists = resolveService(sessionId,
+                s -> s.onCreateSearchSession(context, sessionId));
+
+        if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
+            final SearchSessionInfo sessionInfo = new SearchSessionInfo(
+                    sessionId, context, token, () -> {
+                synchronized (mLock) {
+                    onDestroyLocked(sessionId);
+                }
+            });
+            if (sessionInfo.linkToDeath()) {
+                mSessionInfos.put(sessionId, sessionInfo);
+            } else {
+                // destroy the session if calling process is already dead
+                onDestroyLocked(sessionId);
+            }
+        }
+    }
+
+    /**
+     * Records an app target event to the service.
+     */
+    @GuardedBy("mLock")
+    public void notifyLocked(@NonNull SearchSessionId sessionId, @NonNull Query query,
+            @NonNull SearchTargetEvent event) {
+        final SearchSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+        if (sessionInfo == null) return;
+        resolveService(sessionId,
+                s -> s.onNotifyEvent(sessionId, query, event));
+    }
+
+    /**
+     * Requests the service to return search results of an input query.
+     */
+    @GuardedBy("mLock")
+    public void queryLocked(@NonNull SearchSessionId sessionId,
+            @NonNull Query input, @NonNull ISearchCallback callback) {
+        final SearchSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+        if (sessionInfo == null) return;
+        resolveService(sessionId,
+                s -> s.onQuery(sessionId, input, callback));
+    }
+
+    /**
+     * Notifies the service of the end of an existing search session.
+     */
+    @GuardedBy("mLock")
+    public void onDestroyLocked(@NonNull SearchSessionId sessionId) {
+        if (isDebug()) {
+            Slog.d(TAG, "onDestroyLocked(): sessionId=" + sessionId);
+        }
+        final SearchSessionInfo sessionInfo = mSessionInfos.remove(sessionId);
+        if (sessionInfo == null) return;
+        resolveService(sessionId,
+                s -> s.onDestroy(sessionId));
+        sessionInfo.destroy();
+    }
+
+    @Override
+    public void onFailureOrTimeout(boolean timedOut) {
+        if (isDebug()) {
+            Slog.d(TAG, "onFailureOrTimeout(): timed out=" + timedOut);
+        }
+        // Do nothing, we are just proxying to the search ui service
+    }
+
+    @Override
+    public void onConnectedStateChanged(boolean connected) {
+        if (isDebug()) {
+            Slog.d(TAG, "onConnectedStateChanged(): connected=" + connected);
+        }
+        if (connected) {
+            synchronized (mLock) {
+                if (mZombie) {
+                    // Validation check - shouldn't happen
+                    if (mRemoteService == null) {
+                        Slog.w(TAG, "Cannot resurrect sessions because remote service is null");
+                        return;
+                    }
+                    mZombie = false;
+                    resurrectSessionsLocked();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onServiceDied(RemoteSearchUiService service) {
+        if (isDebug()) {
+            Slog.w(TAG, "onServiceDied(): service=" + service);
+        }
+        synchronized (mLock) {
+            mZombie = true;
+        }
+        updateRemoteServiceLocked();
+    }
+
+    @GuardedBy("mLock")
+    private void updateRemoteServiceLocked() {
+        if (mRemoteService != null) {
+            mRemoteService.destroy();
+            mRemoteService = null;
+        }
+    }
+
+    void onPackageUpdatedLocked() {
+        if (isDebug()) {
+            Slog.v(TAG, "onPackageUpdatedLocked()");
+        }
+        destroyAndRebindRemoteService();
+    }
+
+    void onPackageRestartedLocked() {
+        if (isDebug()) {
+            Slog.v(TAG, "onPackageRestartedLocked()");
+        }
+        destroyAndRebindRemoteService();
+    }
+
+    private void destroyAndRebindRemoteService() {
+        if (mRemoteService == null) {
+            return;
+        }
+
+        if (isDebug()) {
+            Slog.d(TAG, "Destroying the old remote service.");
+        }
+        mRemoteService.destroy();
+        mRemoteService = null;
+
+        synchronized (mLock) {
+            mZombie = true;
+        }
+        mRemoteService = getRemoteServiceLocked();
+        if (mRemoteService != null) {
+            if (isDebug()) {
+                Slog.d(TAG, "Rebinding to the new remote service.");
+            }
+            mRemoteService.reconnect();
+        }
+    }
+
+    /**
+     * Called after the remote service connected, it's used to restore state from a 'zombie'
+     * service (i.e., after it died).
+     */
+    private void resurrectSessionsLocked() {
+        final int numSessions = mSessionInfos.size();
+        if (isDebug()) {
+            Slog.d(TAG, "Resurrecting remote service (" + mRemoteService + ") on "
+                    + numSessions + " sessions.");
+        }
+
+        for (SearchSessionInfo sessionInfo : mSessionInfos.values()) {
+            sessionInfo.resurrectSessionLocked(this, sessionInfo.mToken);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @Nullable
+    protected boolean resolveService(
+            @NonNull final SearchSessionId sessionId,
+            @NonNull final AbstractRemoteService.AsyncRequest<ISearchUiService> cb) {
+
+        final RemoteSearchUiService service = getRemoteServiceLocked();
+        if (service != null) {
+            service.executeOnResolvedService(cb);
+        }
+        return service != null;
+    }
+
+    @GuardedBy("mLock")
+    @Nullable
+    private RemoteSearchUiService getRemoteServiceLocked() {
+        if (mRemoteService == null) {
+            final String serviceName = getComponentNameLocked();
+            if (serviceName == null) {
+                if (mMaster.verbose) {
+                    Slog.v(TAG, "getRemoteServiceLocked(): not set");
+                }
+                return null;
+            }
+            ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
+
+            mRemoteService = new RemoteSearchUiService(getContext(),
+                    SearchUiService.SERVICE_INTERFACE, serviceComponent, mUserId, this,
+                    mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+        }
+
+        return mRemoteService;
+    }
+
+    private static final class SearchSessionInfo {
+        private static final boolean DEBUG = true;  // Do not submit with true
+
+        @NonNull
+        private final SearchSessionId mSessionId;
+        @NonNull
+        private final SearchContext mSearchContext;
+        @NonNull
+        final IBinder mToken;
+        @NonNull
+        final IBinder.DeathRecipient mDeathRecipient;
+
+        private final RemoteCallbackList<ISearchCallback> mCallbacks =
+                new RemoteCallbackList<ISearchCallback>() {
+                    @Override
+                    public void onCallbackDied(ISearchCallback callback) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Binder died for session Id=" + mSessionId
+                                    + " and callback=" + callback.asBinder());
+                        }
+                        if (mCallbacks.getRegisteredCallbackCount() == 0) {
+                            destroy();
+                        }
+                    }
+                };
+
+        SearchSessionInfo(
+                @NonNull final SearchSessionId id,
+                @NonNull final SearchContext context,
+                @NonNull final IBinder token,
+                @NonNull final IBinder.DeathRecipient deathRecipient) {
+            if (DEBUG) {
+                Slog.d(TAG, "Creating SearchSessionInfo for session Id=" + id);
+            }
+            mSessionId = id;
+            mSearchContext = context;
+            mToken = token;
+            mDeathRecipient = deathRecipient;
+        }
+
+        boolean linkToDeath() {
+            try {
+                mToken.linkToDeath(mDeathRecipient, 0);
+            } catch (RemoteException e) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Caller is dead before session can be started, sessionId: "
+                            + mSessionId);
+                }
+                return false;
+            }
+            return true;
+        }
+
+        void destroy() {
+            if (DEBUG) {
+                Slog.d(TAG, "Removing all callbacks for session Id=" + mSessionId
+                        + " and " + mCallbacks.getRegisteredCallbackCount() + " callbacks.");
+            }
+            if (mToken != null) {
+                mToken.unlinkToDeath(mDeathRecipient, 0);
+            }
+            mCallbacks.kill();
+        }
+
+        void resurrectSessionLocked(SearchUiPerUserService service, IBinder token) {
+            int callbackCount = mCallbacks.getRegisteredCallbackCount();
+            if (DEBUG) {
+                Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked()
+                        + ") for session Id=" + mSessionId + " and "
+                        + callbackCount + " callbacks.");
+            }
+            service.onCreateSearchSessionLocked(mSearchContext, mSessionId, token);
+        }
+    }
+}
diff --git a/services/startop/OWNERS b/services/startop/OWNERS
new file mode 100644
index 0000000..bd3d829
--- /dev/null
+++ b/services/startop/OWNERS
@@ -0,0 +1 @@
+include /startop/OWNERS
diff --git a/services/tests/PackageManager/OWNERS b/services/tests/PackageManager/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/PackageManager/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/PackageManagerComponentOverrideTests/OWNERS b/services/tests/PackageManagerComponentOverrideTests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
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/assets/AppOpsUpgradeTest/OWNERS b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/mockingservicestests/assets/AppOpsUpgradeTest/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..e779e21
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/OWNERS b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 9f895c6..99693d2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -36,7 +36,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedXmlPullParser;
-import android.util.TypedXmlSerializer;
 import android.util.Xml;
 
 import androidx.test.InstrumentationRegistry;
@@ -53,7 +52,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 
 /**
  * Tests app ops version upgrades
@@ -183,8 +181,7 @@
 
         boolean parse() {
             try (FileInputStream stream = new FileInputStream(mFile)) {
-                TypedXmlPullParser parser = Xml.newFastPullParser();
-                parser.setInput(stream, StandardCharsets.UTF_8.name());
+                TypedXmlPullParser parser = Xml.resolvePullParser(stream);
                 int type;
                 while ((type = parser.next()) != XmlPullParser.START_TAG
                         && type != XmlPullParser.END_DOCUMENT) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
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..829e312
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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();
+
+    private static final String REASON = "self-destruct";
+
+    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(Class.class))).thenAnswer((inv) -> {
+            Log.d(TAG, "Mocking " + inv);
+            Class serviceClass = (Class) inv.getArguments()[0];
+            if (serviceClass.equals(PersistentDataBlockManager.class)) return mPdbm;
+            if (serviceClass.equals(StorageManager.class)) return mSm;
+            if (serviceClass.equals(UserManager.class)) return mUm;
+            throw new IllegalArgumentException("Not expecting call for " + serviceClass);
+        });
+
+        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 testFactoryResetBuilder_nullContext() throws Exception {
+        assertThrows(NullPointerException.class, () -> FactoryResetter.newBuilder(null));
+    }
+
+    @Test
+    public void testFactoryResetBuilder_nullReason() throws Exception {
+        assertThrows(NullPointerException.class,
+                () -> FactoryResetter.newBuilder(mContext).setReason(null));
+    }
+
+    @Test
+    public void testFactoryReset_minimumArgs_noMasterClearPermission() throws Exception {
+        revokeMasterClearPermission();
+        allowFactoryReset();
+
+        assertThrows(SecurityException.class,
+                () -> FactoryResetter.newBuilder(mContext).build().factoryReset());
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataNotCalled();
+    }
+
+    @Test
+    public void testFactoryReset_minimumArgs_withRestriction_notForced() throws Exception {
+        disallowFactoryReset();
+
+        assertThrows(SecurityException.class,
+                () -> FactoryResetter.newBuilder(mContext).build().factoryReset());
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataNotCalled();
+    }
+
+    @Test
+    public void testFactoryReset_minimumArgs_noRestriction_notForced() throws Exception {
+        allowFactoryReset();
+
+        FactoryResetter.newBuilder(mContext).build().factoryReset();
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataMinimumArgsCalled();
+    }
+
+    @Test
+    public void testFactoryReset_minimumArgs_withRestriction_forced() throws Exception {
+        disallowFactoryReset();
+
+        FactoryResetter.newBuilder(mContext).setForce(true).build().factoryReset();
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataMinimumArgsButForceCalled();
+    }
+
+    @Test
+    public void testFactoryReset_storageOnly() throws Exception {
+        allowFactoryReset();
+
+        FactoryResetter.newBuilder(mContext)
+                .setWipeAdoptableStorage(true).build()
+                .factoryReset();
+
+        verifyWipeAdoptableStorageCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataMinimumArgsCalled();
+    }
+
+    @Test
+    public void testFactoryReset_frpOnly() throws Exception {
+        allowFactoryReset();
+
+        FactoryResetter.newBuilder(mContext)
+                .setWipeFactoryResetProtection(true)
+                .build().factoryReset();
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionCalled();
+        verifyRebootWipeUserDataMinimumArgsCalled();
+    }
+
+    @Test
+    public void testFactoryReset_allArgs() throws Exception {
+        allowFactoryReset();
+
+        FactoryResetter.newBuilder(mContext)
+                .setReason(REASON)
+                .setForce(true)
+                .setShutdown(true)
+                .setWipeEuicc(true)
+                .setWipeAdoptableStorage(true)
+                .setWipeFactoryResetProtection(true)
+                .build().factoryReset();
+
+        verifyWipeAdoptableStorageCalled();
+        verifyWipeFactoryResetProtectionCalled();
+        verifyRebootWipeUserDataAllArgsCalled();
+    }
+
+    private void revokeMasterClearPermission() {
+        when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.MASTER_CLEAR))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+    }
+
+    private void allowFactoryReset() {
+        when(mUm.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)).thenReturn(false);
+    }
+
+    private void disallowFactoryReset() {
+        when(mUm.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)).thenReturn(true);
+    }
+
+    private void verifyRebootWipeUserDataNotCalled() {
+        verify(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(),
+                anyBoolean()), never());
+    }
+
+    private void verifyRebootWipeUserDataMinimumArgsCalled() {
+        verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false,
+                /* reason= */ null, /* force= */ false, /* wipeEuicc= */ false));
+    }
+
+    private void verifyRebootWipeUserDataMinimumArgsButForceCalled() {
+        verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false,
+                /* reason= */ null, /* force= */ true, /* wipeEuicc= */ false));
+    }
+
+    private void verifyRebootWipeUserDataAllArgsCalled() {
+        verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ true,
+                /* reason= */ REASON, /* force= */ true, /* wipeEuicc= */ true));
+    }
+
+    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/mockingservicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index dbdee979..af4130d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -19,11 +19,14 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.never;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -40,7 +43,9 @@
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.server.LocalServices;
+import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 
 import com.google.common.truth.Truth;
 
@@ -78,6 +83,8 @@
     private Resources mMockedResources;
     @Mock
     private LightsManager mMockedLightsManager;
+    @Mock
+    private LogicalLight mMockedBacklight;
 
     private Handler mHandler;
 
@@ -492,6 +499,49 @@
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
     }
 
+    @Test
+    public void testBacklightAdapter_withSurfaceControlSupport() {
+        final Binder displayToken = new Binder();
+        doReturn(true).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+
+        // Test as default display
+        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
+        ba.setBrightness(0.514f);
+        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.514f));
+
+        // Test as not default display
+        BacklightAdapter ba2 = new BacklightAdapter(displayToken,
+                false /*isDefault*/);
+        ba2.setBrightness(0.323f);
+        verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.323f));
+    }
+
+    @Test
+    public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() {
+        final Binder displayToken = new Binder();
+        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+        doReturn(mMockedBacklight).when(mMockedLightsManager)
+                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+
+        BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
+        ba.setBrightness(0.123f);
+        verify(mMockedBacklight).setBrightness(0.123f);
+    }
+
+    @Test
+    public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() {
+        final Binder displayToken = new Binder();
+        doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+        doReturn(mMockedBacklight).when(mMockedLightsManager)
+                .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+
+        BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/);
+        ba.setBrightness(0.456f);
+
+        // Adapter does not forward any brightness in this case.
+        verify(mMockedBacklight, never()).setBrightness(anyFloat());
+    }
+
     private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
                                   float expectedXdpi,
                                   float expectedYDpi,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/OWNERS b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS
new file mode 100644
index 0000000..6ce1ee4
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/display/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/OWNERS b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 4f3564d..344a19a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -327,10 +327,10 @@
         return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, jobInfo);
     }
 
-    private JobStatus createHpjJobStatus(String testTag, int jobId) {
+    private JobStatus createExpeditedJobStatus(String testTag, int jobId) {
         JobInfo jobInfo = new JobInfo.Builder(jobId,
-                new ComponentName(mContext, "TestQuotaHpjJobService"))
-                .setForeground(true)
+                new ComponentName(mContext, "TestQuotaExpeditedJobService"))
+                .setExpedited(true)
                 .build();
         return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, jobInfo);
     }
@@ -382,7 +382,7 @@
         assertNull(mQuotaController.getTimingSessions(0, "com.android.test"));
 
         List<TimingSession> expectedRegular = new ArrayList<>();
-        List<TimingSession> expectedHpj = new ArrayList<>();
+        List<TimingSession> expectedEJ = new ArrayList<>();
         TimingSession one = new TimingSession(1, 10, 1);
         TimingSession two = new TimingSession(11, 20, 2);
         TimingSession thr = new TimingSession(21, 30, 3);
@@ -392,25 +392,25 @@
         expectedRegular.add(one);
         assertEquals(expectedRegular, mQuotaController.getTimingSessions(0, "com.android.test"));
         assertTrue(
-                ArrayUtils.isEmpty(mQuotaController.getHpjTimingSessions(0, "com.android.test")));
+                ArrayUtils.isEmpty(mQuotaController.getEJTimingSessions(0, "com.android.test")));
 
         mQuotaController.saveTimingSession(0, "com.android.test", two, false);
         expectedRegular.add(two);
         assertEquals(expectedRegular, mQuotaController.getTimingSessions(0, "com.android.test"));
         assertTrue(
-                ArrayUtils.isEmpty(mQuotaController.getHpjTimingSessions(0, "com.android.test")));
+                ArrayUtils.isEmpty(mQuotaController.getEJTimingSessions(0, "com.android.test")));
 
         mQuotaController.saveTimingSession(0, "com.android.test", thr, true);
-        expectedHpj.add(thr);
+        expectedEJ.add(thr);
         assertEquals(expectedRegular, mQuotaController.getTimingSessions(0, "com.android.test"));
-        assertEquals(expectedHpj, mQuotaController.getHpjTimingSessions(0, "com.android.test"));
+        assertEquals(expectedEJ, mQuotaController.getEJTimingSessions(0, "com.android.test"));
 
         mQuotaController.saveTimingSession(0, "com.android.test", fou, false);
         mQuotaController.saveTimingSession(0, "com.android.test", fou, true);
         expectedRegular.add(fou);
-        expectedHpj.add(fou);
+        expectedEJ.add(fou);
         assertEquals(expectedRegular, mQuotaController.getTimingSessions(0, "com.android.test"));
-        assertEquals(expectedHpj, mQuotaController.getHpjTimingSessions(0, "com.android.test"));
+        assertEquals(expectedEJ, mQuotaController.getEJTimingSessions(0, "com.android.test"));
     }
 
     @Test
@@ -429,15 +429,15 @@
         TimingSession fiv = createTimingSession(
                 now - (25 * HOUR_IN_MILLIS), 5 * MINUTE_IN_MILLIS, 4);
         List<TimingSession> expectedRegular = new ArrayList<>();
-        List<TimingSession> expectedHpj = new ArrayList<>();
+        List<TimingSession> expectedEJ = new ArrayList<>();
         // Added in correct (chronological) order.
         expectedRegular.add(fou);
         expectedRegular.add(thr);
         expectedRegular.add(two);
         expectedRegular.add(one);
-        expectedHpj.add(fiv); // HPJ list should be unaffected
-        expectedHpj.add(fou);
-        expectedHpj.add(one);
+        expectedEJ.add(fiv); // EJ list should be unaffected
+        expectedEJ.add(fou);
+        expectedEJ.add(one);
         mQuotaController.saveTimingSession(0, "com.android.test", fiv, false);
         mQuotaController.saveTimingSession(0, "com.android.test", fou, false);
         mQuotaController.saveTimingSession(0, "com.android.test", thr, false);
@@ -452,7 +452,7 @@
         }
 
         assertEquals(expectedRegular, mQuotaController.getTimingSessions(0, "com.android.test"));
-        assertEquals(expectedHpj, mQuotaController.getHpjTimingSessions(0, "com.android.test"));
+        assertEquals(expectedEJ, mQuotaController.getEJTimingSessions(0, "com.android.test"));
     }
 
     @Test
@@ -484,9 +484,9 @@
         mQuotaController.saveTimingSession(0, "com.android.test.stay", one, true);
 
         assertNotNull(mQuotaController.getTimingSessions(0, "com.android.test.remove"));
-        assertNotNull(mQuotaController.getHpjTimingSessions(0, "com.android.test.remove"));
+        assertNotNull(mQuotaController.getEJTimingSessions(0, "com.android.test.remove"));
         assertNotNull(mQuotaController.getTimingSessions(0, "com.android.test.stay"));
-        assertNotNull(mQuotaController.getHpjTimingSessions(0, "com.android.test.stay"));
+        assertNotNull(mQuotaController.getEJTimingSessions(0, "com.android.test.stay"));
 
         ExecutionStats expectedStats = new ExecutionStats();
         expectedStats.expirationTimeElapsed = now + 24 * HOUR_IN_MILLIS;
@@ -499,7 +499,7 @@
             mQuotaController.onAppRemovedLocked("com.android.test.remove", uid);
         }
         assertNull(mQuotaController.getTimingSessions(0, "com.android.test.remove"));
-        assertNull(mQuotaController.getHpjTimingSessions(0, "com.android.test.remove"));
+        assertNull(mQuotaController.getEJTimingSessions(0, "com.android.test.remove"));
         assertEquals(expected, mQuotaController.getTimingSessions(0, "com.android.test.stay"));
         synchronized (mQuotaController.mLock) {
             assertEquals(expectedStats,
@@ -534,19 +534,19 @@
         TimingSession two = createTimingSession(
                 now - (70 * MINUTE_IN_MILLIS), 9 * MINUTE_IN_MILLIS, 1);
         List<TimingSession> expectedRegular = new ArrayList<>();
-        List<TimingSession> expectedHpj = new ArrayList<>();
+        List<TimingSession> expectedEJ = new ArrayList<>();
         // Added in correct (chronological) order.
         expectedRegular.add(two);
         expectedRegular.add(one);
-        expectedHpj.add(one);
+        expectedEJ.add(one);
         mQuotaController.saveTimingSession(10, "com.android.test", two, false);
         mQuotaController.saveTimingSession(10, "com.android.test", one, false);
         mQuotaController.saveTimingSession(10, "com.android.test", one, true);
 
         assertNotNull(mQuotaController.getTimingSessions(0, "com.android.test"));
-        assertNotNull(mQuotaController.getHpjTimingSessions(0, "com.android.test"));
+        assertNotNull(mQuotaController.getEJTimingSessions(0, "com.android.test"));
         assertNotNull(mQuotaController.getTimingSessions(10, "com.android.test"));
-        assertNotNull(mQuotaController.getHpjTimingSessions(10, "com.android.test"));
+        assertNotNull(mQuotaController.getEJTimingSessions(10, "com.android.test"));
 
         ExecutionStats expectedStats = new ExecutionStats();
         expectedStats.expirationTimeElapsed = now + 24 * HOUR_IN_MILLIS;
@@ -557,11 +557,11 @@
         synchronized (mQuotaController.mLock) {
             mQuotaController.onUserRemovedLocked(0);
             assertNull(mQuotaController.getTimingSessions(0, "com.android.test"));
-            assertNull(mQuotaController.getHpjTimingSessions(0, "com.android.test"));
+            assertNull(mQuotaController.getEJTimingSessions(0, "com.android.test"));
             assertEquals(expectedRegular,
                     mQuotaController.getTimingSessions(10, "com.android.test"));
-            assertEquals(expectedHpj,
-                    mQuotaController.getHpjTimingSessions(10, "com.android.test"));
+            assertEquals(expectedEJ,
+                    mQuotaController.getEJTimingSessions(10, "com.android.test"));
             assertEquals(expectedStats,
                     mQuotaController.getExecutionStatsLocked(0, "com.android.test", RARE_INDEX));
             assertNotEquals(expectedStats,
@@ -1960,6 +1960,79 @@
                 .set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
     }
 
+    /**
+     * Test that QC handles invalid cases where an app is in the NEVER bucket but has still run
+     * jobs.
+     */
+    @Test
+    public void testMaybeScheduleStartAlarmLocked_Never_EffectiveNotNever() {
+        // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
+        // because it schedules an alarm too. Prevent it from doing so.
+        spyOn(mQuotaController);
+        doNothing().when(mQuotaController).maybeScheduleCleanupAlarmLocked();
+
+        // The app is really in the NEVER bucket but is elevated somehow (eg via uidActive).
+        setStandbyBucket(NEVER_INDEX);
+        final int effectiveStandbyBucket = FREQUENT_INDEX;
+
+        // No sessions saved yet.
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+        // Test with timing sessions out of window.
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(now - 10 * HOUR_IN_MILLIS, 5 * MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+        // Test with timing sessions in window but still in quota.
+        final long start = now - (6 * HOUR_IN_MILLIS);
+        final long expectedAlarmTime = start + 8 * HOUR_IN_MILLIS + mQcConstants.IN_QUOTA_BUFFER_MS;
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(start, 5 * MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+        // Add some more sessions, but still in quota.
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(now - 3 * HOUR_IN_MILLIS, MINUTE_IN_MILLIS, 1), false);
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(now - HOUR_IN_MILLIS, 3 * MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+        // Test when out of quota.
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(now - HOUR_IN_MILLIS, MINUTE_IN_MILLIS, 1), false);
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, times(1))
+                .set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
+
+        // Alarm already scheduled, so make sure it's not scheduled again.
+        synchronized (mQuotaController.mLock) {
+            mQuotaController.maybeScheduleStartAlarmLocked(
+                    SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+        }
+        verify(mAlarmManager, times(1))
+                .set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
+    }
+
     @Test
     public void testMaybeScheduleStartAlarmLocked_Rare() {
         // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
@@ -2298,16 +2371,16 @@
         setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
                 10 * SECOND_IN_MILLIS);
         setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, 7 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 2 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 90 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 1 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 30 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, 27 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_WINDOW_SIZE_MS, 12 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS, 10 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_TOP_APP_MS, 87 * SECOND_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_INTERACTION_MS, 86 * SECOND_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS, 85 * SECOND_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 2 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 90 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 1 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 27 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 12 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 87 * SECOND_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, 86 * SECOND_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_NOTIFICATION_SEEN_MS, 85 * SECOND_IN_MILLIS);
 
         assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
         assertEquals(2 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
@@ -2335,16 +2408,16 @@
         assertEquals(10 * SECOND_IN_MILLIS,
                 mQuotaController.getTimingSessionCoalescingDurationMs());
         assertEquals(7 * MINUTE_IN_MILLIS, mQuotaController.getMinQuotaCheckDelayMs());
-        assertEquals(2 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[ACTIVE_INDEX]);
-        assertEquals(90 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[WORKING_INDEX]);
-        assertEquals(HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[FREQUENT_INDEX]);
-        assertEquals(30 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[RARE_INDEX]);
-        assertEquals(27 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[RESTRICTED_INDEX]);
-        assertEquals(12 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitWindowSizeMs());
-        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getHpjTopAppTimeChunkSizeMs());
-        assertEquals(87 * SECOND_IN_MILLIS, mQuotaController.getHpjRewardTopAppMs());
-        assertEquals(86 * SECOND_IN_MILLIS, mQuotaController.getHpjRewardInteractionMs());
-        assertEquals(85 * SECOND_IN_MILLIS, mQuotaController.getHpjRewardNotificationSeenMs());
+        assertEquals(2 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[ACTIVE_INDEX]);
+        assertEquals(90 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[WORKING_INDEX]);
+        assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
+        assertEquals(30 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
+        assertEquals(27 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
+        assertEquals(12 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
+        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
+        assertEquals(87 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
+        assertEquals(86 * SECOND_IN_MILLIS, mQuotaController.getEJRewardInteractionMs());
+        assertEquals(85 * SECOND_IN_MILLIS, mQuotaController.getEJRewardNotificationSeenMs());
     }
 
     @Test
@@ -2373,16 +2446,16 @@
         setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW, 0);
         setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, -1);
         setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_WINDOW_SIZE_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_TOP_APP_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_INTERACTION_MS, -1);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, -1);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_NOTIFICATION_SEEN_MS, -1);
 
         assertEquals(MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
         assertEquals(0, mQuotaController.getInQuotaBufferMs());
@@ -2407,16 +2480,16 @@
         assertEquals(0, mQuotaController.getBucketMaxSessionCounts()[RESTRICTED_INDEX]);
         assertEquals(0, mQuotaController.getTimingSessionCoalescingDurationMs());
         assertEquals(0, mQuotaController.getMinQuotaCheckDelayMs());
-        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[ACTIVE_INDEX]);
-        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[WORKING_INDEX]);
-        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[FREQUENT_INDEX]);
-        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getHpjLimitsMs()[RARE_INDEX]);
-        assertEquals(0, mQuotaController.getHpjLimitsMs()[RESTRICTED_INDEX]);
-        assertEquals(HOUR_IN_MILLIS, mQuotaController.getHpjLimitWindowSizeMs());
-        assertEquals(1, mQuotaController.getHpjTopAppTimeChunkSizeMs());
-        assertEquals(10 * SECOND_IN_MILLIS, mQuotaController.getHpjRewardTopAppMs());
-        assertEquals(5 * SECOND_IN_MILLIS, mQuotaController.getHpjRewardInteractionMs());
-        assertEquals(0, mQuotaController.getHpjRewardNotificationSeenMs());
+        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[ACTIVE_INDEX]);
+        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[WORKING_INDEX]);
+        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
+        assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
+        assertEquals(0, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
+        assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
+        assertEquals(1, mQuotaController.getEJTopAppTimeChunkSizeMs());
+        assertEquals(10 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
+        assertEquals(5 * SECOND_IN_MILLIS, mQuotaController.getEJRewardInteractionMs());
+        assertEquals(0, mQuotaController.getEJRewardNotificationSeenMs());
 
         // Invalid configurations.
         // In_QUOTA_BUFFER should never be greater than ALLOWED_TIME_PER_PERIOD
@@ -2439,16 +2512,16 @@
         setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
                 25 * HOUR_IN_MILLIS);
         setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_WINDOW_SIZE_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_TOP_APP_TIME_CHUNK_SIZE_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_TOP_APP_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_INTERACTION_MS, 25 * HOUR_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_REWARD_NOTIFICATION_SEEN_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, 25 * HOUR_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_NOTIFICATION_SEEN_MS, 25 * HOUR_IN_MILLIS);
 
         assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
         assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
@@ -2463,16 +2536,16 @@
         assertEquals(15 * MINUTE_IN_MILLIS,
                 mQuotaController.getTimingSessionCoalescingDurationMs());
         assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getMinQuotaCheckDelayMs());
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[ACTIVE_INDEX]);
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[WORKING_INDEX]);
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[FREQUENT_INDEX]);
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[RARE_INDEX]);
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitsMs()[RESTRICTED_INDEX]);
-        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getHpjLimitWindowSizeMs());
-        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getHpjTopAppTimeChunkSizeMs());
-        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getHpjRewardTopAppMs());
-        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getHpjRewardInteractionMs());
-        assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getHpjRewardNotificationSeenMs());
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[ACTIVE_INDEX]);
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[WORKING_INDEX]);
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
+        assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
+        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
+        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
+        assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJRewardInteractionMs());
+        assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getEJRewardNotificationSeenMs());
     }
 
     /** Tests that TimingSessions aren't saved when the device is charging. */
@@ -3387,22 +3460,22 @@
     }
 
     @Test
-    public void testGetRemainingHpjExecutionTimeLocked_NoHistory() {
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+    public void testGetRemainingEJExecutionTimeLocked_NoHistory() {
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong remaining HPJ execution time for bucket #" + i,
+            assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
                     limits[i],
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetRemainingHpjExecutionTimeLocked_AllSessionsWithinWindow() {
+    public void testGetRemainingEJExecutionTimeLocked_AllSessionsWithinWindow() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - mQcConstants.HPJ_WINDOW_SIZE_MS, MINUTE_IN_MILLIS, 5),
+                createTimingSession(now - mQcConstants.EJ_WINDOW_SIZE_MS, MINUTE_IN_MILLIS, 5),
                 true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
@@ -3413,26 +3486,26 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong remaining HPJ execution time for bucket #" + i,
+            assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
                     i == NEVER_INDEX ? 0 : (limits[i] - 5 * MINUTE_IN_MILLIS),
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetRemainingHpjExecutionTimeLocked_OneSessionStraddlesEdge() {
+    public void testGetRemainingEJExecutionTimeLocked_OneSessionStraddlesEdge() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             synchronized (mQuotaController.mLock) {
                 mQuotaController.onUserRemovedLocked(SOURCE_USER_ID);
             }
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                    createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
+                    createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
                             2 * MINUTE_IN_MILLIS, 5), true);
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                     createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
@@ -3444,32 +3517,32 @@
                     createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
             setStandbyBucket(i);
-            assertEquals("Got wrong remaining HPJ execution time for bucket #" + i,
+            assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
                     i == NEVER_INDEX ? 0 : (limits[i] - 5 * MINUTE_IN_MILLIS),
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetRemainingHpjExecutionTimeLocked_WithStaleSessions() {
+    public void testGetRemainingEJExecutionTimeLocked_WithStaleSessions() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             synchronized (mQuotaController.mLock) {
                 mQuotaController.onUserRemovedLocked(SOURCE_USER_ID);
             }
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                     createTimingSession(
-                            now - (mQcConstants.HPJ_WINDOW_SIZE_MS + 10 * MINUTE_IN_MILLIS),
+                            now - (mQcConstants.EJ_WINDOW_SIZE_MS + 10 * MINUTE_IN_MILLIS),
                             2 * MINUTE_IN_MILLIS, 5), true);
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                     createTimingSession(
-                            now - (mQcConstants.HPJ_WINDOW_SIZE_MS + 5 * MINUTE_IN_MILLIS),
+                            now - (mQcConstants.EJ_WINDOW_SIZE_MS + 5 * MINUTE_IN_MILLIS),
                             MINUTE_IN_MILLIS, 5), true);
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                    createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
+                    createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
                             2 * MINUTE_IN_MILLIS, 5), true);
             mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                     createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
@@ -3481,19 +3554,19 @@
                     createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
             setStandbyBucket(i);
-            assertEquals("Got wrong remaining HPJ execution time for bucket #" + i,
+            assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
                     i == NEVER_INDEX ? 0 : (limits[i] - 5 * MINUTE_IN_MILLIS),
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     /**
-     * Tests that getRemainingHpjExecutionTimeLocked returns the correct stats soon after device
+     * Tests that getRemainingEJExecutionTimeLocked returns the correct stats soon after device
      * startup.
      */
     @Test
-    public void testGetRemainingHpjExecutionTimeLocked_BeginningOfTime() {
+    public void testGetRemainingEJExecutionTimeLocked_BeginningOfTime() {
         // Set time to 3 minutes after boot.
         advanceElapsedClock(-JobSchedulerService.sElapsedRealtimeClock.millis());
         advanceElapsedClock(3 * MINUTE_IN_MILLIS);
@@ -3503,29 +3576,29 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(150 * SECOND_IN_MILLIS, 15 * SECOND_IN_MILLIS, 5), true);
 
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong remaining HPJ execution time for bucket #" + i,
+            assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
                     i == NEVER_INDEX ? 0 : (limits[i] - 75 * SECOND_IN_MILLIS),
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_NoHistory() {
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+    public void testGetTimeUntilEJQuotaConsumedLocked_NoHistory() {
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong time until HPJ quota consumed for bucket #" + i,
-                    limits[i], mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+            assertEquals("Got wrong time until EJ quota consumed for bucket #" + i,
+                    limits[i], mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_AllSessionsWithinWindow() {
+    public void testGetTimeUntilEJQuotaConsumedLocked_AllSessionsWithinWindow() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
@@ -3536,76 +3609,76 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong time until HPJ quota consumed for bucket #" + i,
+            assertEquals("Got wrong time until EJ quota consumed for bucket #" + i,
                     i == NEVER_INDEX ? 0 : (limits[i] - 5 * MINUTE_IN_MILLIS),
-                    mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                    mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_SessionsAtEdgeOfWindow() {
+    public void testGetTimeUntilEJQuotaConsumedLocked_SessionsAtEdgeOfWindow() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - mQcConstants.HPJ_WINDOW_SIZE_MS, MINUTE_IN_MILLIS, 5),
+                createTimingSession(now - mQcConstants.EJ_WINDOW_SIZE_MS, MINUTE_IN_MILLIS, 5),
                 true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS - 2 * MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS - 2 * MINUTE_IN_MILLIS),
                         MINUTE_IN_MILLIS, 5), true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS - 10 * MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS - 10 * MINUTE_IN_MILLIS),
                         MINUTE_IN_MILLIS, 5), true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 20 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
 
         setStandbyBucket(ACTIVE_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + ACTIVE_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + ACTIVE_INDEX,
                 28 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(WORKING_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + WORKING_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + WORKING_INDEX,
                 18 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(FREQUENT_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + FREQUENT_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + FREQUENT_INDEX,
                 13 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(RARE_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + RARE_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + RARE_INDEX,
                 7 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(RESTRICTED_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + RESTRICTED_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + RESTRICTED_INDEX,
                 MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_OneSessionStraddlesEdge() {
+    public void testGetTimeUntilEJQuotaConsumedLocked_OneSessionStraddlesEdge() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
                         2 * MINUTE_IN_MILLIS, 5), true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
@@ -3616,56 +3689,56 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5), true);
 
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
 
         setStandbyBucket(ACTIVE_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + ACTIVE_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + ACTIVE_INDEX,
                 26 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(WORKING_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + WORKING_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + WORKING_INDEX,
                 16 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(FREQUENT_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + FREQUENT_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + FREQUENT_INDEX,
                 11 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(RARE_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + RARE_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + RARE_INDEX,
                 6 * MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
 
         setStandbyBucket(RESTRICTED_INDEX);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + RESTRICTED_INDEX,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + RESTRICTED_INDEX,
                 MINUTE_IN_MILLIS,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_WithStaleSessions() {
+    public void testGetTimeUntilEJQuotaConsumedLocked_WithStaleSessions() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         List<TimingSession> timingSessions = new ArrayList<>();
         timingSessions.add(
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + 10 * MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + 10 * MINUTE_IN_MILLIS),
                         2 * MINUTE_IN_MILLIS, 5));
         timingSessions.add(
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + 5 * MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + 5 * MINUTE_IN_MILLIS),
                         MINUTE_IN_MILLIS, 5));
         timingSessions.add(
-                createTimingSession(now - (mQcConstants.HPJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
+                createTimingSession(now - (mQcConstants.EJ_WINDOW_SIZE_MS + MINUTE_IN_MILLIS),
                         2 * MINUTE_IN_MILLIS, 5));
         timingSessions.add(
                 createTimingSession(now - 40 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5));
@@ -3676,29 +3749,29 @@
         timingSessions.add(
                 createTimingSession(now - 10 * MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 5));
 
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 5 * MINUTE_IN_MILLIS);
 
-        runTestGetTimeUntilHpjQuotaConsumedLocked(
+        runTestGetTimeUntilEJQuotaConsumedLocked(
                 timingSessions, ACTIVE_INDEX, 26 * MINUTE_IN_MILLIS);
-        runTestGetTimeUntilHpjQuotaConsumedLocked(
+        runTestGetTimeUntilEJQuotaConsumedLocked(
                 timingSessions, WORKING_INDEX, 16 * MINUTE_IN_MILLIS);
-        runTestGetTimeUntilHpjQuotaConsumedLocked(
+        runTestGetTimeUntilEJQuotaConsumedLocked(
                 timingSessions, FREQUENT_INDEX, 11 * MINUTE_IN_MILLIS);
-        runTestGetTimeUntilHpjQuotaConsumedLocked(timingSessions, RARE_INDEX, 6 * MINUTE_IN_MILLIS);
-        runTestGetTimeUntilHpjQuotaConsumedLocked(
+        runTestGetTimeUntilEJQuotaConsumedLocked(timingSessions, RARE_INDEX, 6 * MINUTE_IN_MILLIS);
+        runTestGetTimeUntilEJQuotaConsumedLocked(
                 timingSessions, RESTRICTED_INDEX, MINUTE_IN_MILLIS);
     }
 
     /**
-     * Tests that getTimeUntilHpjQuotaConsumedLocked returns the correct stats soon after device
+     * Tests that getTimeUntilEJQuotaConsumedLocked returns the correct stats soon after device
      * startup.
      */
     @Test
-    public void testGetTimeUntilHpjQuotaConsumedLocked_BeginningOfTime() {
+    public void testGetTimeUntilEJQuotaConsumedLocked_BeginningOfTime() {
         // Set time to 3 minutes after boot.
         advanceElapsedClock(-JobSchedulerService.sElapsedRealtimeClock.millis());
         advanceElapsedClock(3 * MINUTE_IN_MILLIS);
@@ -3708,17 +3781,17 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(150 * SECOND_IN_MILLIS, 15 * SECOND_IN_MILLIS, 5), true);
 
-        final long[] limits = mQuotaController.getHpjLimitsMs();
+        final long[] limits = mQuotaController.getEJLimitsMs();
         for (int i = 0; i < limits.length; ++i) {
             setStandbyBucket(i);
-            assertEquals("Got wrong time until HPJ quota consumed for bucket #" + i,
+            assertEquals("Got wrong time until EJ quota consumed for bucket #" + i,
                     limits[i], // All existing sessions will phase out
-                    mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                    mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
-    private void runTestGetTimeUntilHpjQuotaConsumedLocked(
+    private void runTestGetTimeUntilEJQuotaConsumedLocked(
             List<TimingSession> timingSessions, int bucketIndex, long expectedValue) {
         synchronized (mQuotaController.mLock) {
             mQuotaController.onUserRemovedLocked(SOURCE_USER_ID);
@@ -3730,14 +3803,14 @@
         }
 
         setStandbyBucket(bucketIndex);
-        assertEquals("Got wrong time until HPJ quota consumed for bucket #" + bucketIndex,
+        assertEquals("Got wrong time until EJ quota consumed for bucket #" + bucketIndex,
                 expectedValue,
-                mQuotaController.getTimeUntilHpjQuotaConsumedLocked(
+                mQuotaController.getTimeUntilEJQuotaConsumedLocked(
                         SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     @Test
-    public void testMaybeScheduleStartAlarmLocked_Hpj() {
+    public void testMaybeScheduleStartAlarmLocked_EJ() {
         // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
         // because it schedules an alarm too. Prevent it from doing so.
         spyOn(mQuotaController);
@@ -3745,7 +3818,7 @@
 
         final int standbyBucket = WORKING_INDEX;
         setStandbyBucket(standbyBucket);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
 
         InOrder inOrder = inOrder(mAlarmManager);
 
@@ -3813,16 +3886,16 @@
 
     /** Tests that the start alarm is properly rescheduled if the app's bucket is changed. */
     @Test
-    public void testMaybeScheduleStartAlarmLocked_Hpj_BucketChange() {
+    public void testMaybeScheduleStartAlarmLocked_Ej_BucketChange() {
         // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
         // because it schedules an alarm too. Prevent it from doing so.
         spyOn(mQuotaController);
         doNothing().when(mQuotaController).maybeScheduleCleanupAlarmLocked();
 
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
-        setDeviceConfigLong(QcConstants.KEY_HPJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ACTIVE_MS, 30 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 20 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 15 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
 
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
         // Affects active bucket
@@ -3915,7 +3988,7 @@
      * to the app being out of quota contributes less than the quota buffer time.
      */
     @Test
-    public void testMaybeScheduleStartAlarmLocked_Hpj_SmallRollingQuota() {
+    public void testMaybeScheduleStartAlarmLocked_Ej_SmallRollingQuota() {
         // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
         // because it schedules an alarm too. Prevent it from doing so.
         spyOn(mQuotaController);
@@ -3924,7 +3997,7 @@
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
         setStandbyBucket(WORKING_INDEX);
         final long contributionMs = mQcConstants.IN_QUOTA_BUFFER_MS / 2;
-        final long remainingTimeMs = mQcConstants.HPJ_LIMIT_WORKING_MS - contributionMs;
+        final long remainingTimeMs = mQcConstants.EJ_LIMIT_WORKING_MS - contributionMs;
 
         // Session straddles edge of bucket window. Only the contribution should be counted towards
         // the quota.
@@ -3947,15 +4020,15 @@
 
     /** Tests that TimingSessions aren't saved when the device is charging. */
     @Test
-    public void testHpjTimerTracking_Charging() {
+    public void testEJTimerTracking_Charging() {
         setCharging();
 
-        JobStatus jobStatus = createHpjJobStatus("testHpjTimerTracking_Charging", 1);
+        JobStatus jobStatus = createExpeditedJobStatus("testEJTimerTracking_Charging", 1);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
 
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         synchronized (mQuotaController.mLock) {
             mQuotaController.prepareForExecutionLocked(jobStatus);
@@ -3964,21 +4037,21 @@
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStopTrackingJobLocked(jobStatus, null, false);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /** Tests that TimingSessions are saved properly when the device is discharging. */
     @Test
-    public void testHpjTimerTracking_Discharging() {
+    public void testEJTimerTracking_Discharging() {
         setDischarging();
         setProcessState(ActivityManager.PROCESS_STATE_BACKUP);
 
-        JobStatus jobStatus = createHpjJobStatus("testHpjTimerTracking_Discharging", 1);
+        JobStatus jobStatus = createExpeditedJobStatus("testEJTimerTracking_Discharging", 1);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
 
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         List<TimingSession> expected = new ArrayList<>();
 
@@ -3992,15 +4065,15 @@
         }
         expected.add(createTimingSession(start, 5 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         // Test overlapping jobs.
-        JobStatus jobStatus2 = createHpjJobStatus("testHpjTimerTracking_Discharging", 2);
+        JobStatus jobStatus2 = createExpeditedJobStatus("testEJTimerTracking_Discharging", 2);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus2, null);
         }
 
-        JobStatus jobStatus3 = createHpjJobStatus("testHpjTimerTracking_Discharging", 3);
+        JobStatus jobStatus3 = createExpeditedJobStatus("testEJTimerTracking_Discharging", 3);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus3, null);
         }
@@ -4034,7 +4107,7 @@
         }
         expected.add(createTimingSession(start, MINUTE_IN_MILLIS, 3));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
@@ -4042,22 +4115,25 @@
      * charging and discharging.
      */
     @Test
-    public void testHpjTimerTracking_ChargingAndDischarging() {
+    public void testEJTimerTracking_ChargingAndDischarging() {
         setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
 
-        JobStatus jobStatus = createHpjJobStatus("testHpjTimerTracking_ChargingAndDischarging", 1);
+        JobStatus jobStatus =
+                createExpeditedJobStatus("testEJTimerTracking_ChargingAndDischarging", 1);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
-        JobStatus jobStatus2 = createHpjJobStatus("testHpjTimerTracking_ChargingAndDischarging", 2);
+        JobStatus jobStatus2 =
+                createExpeditedJobStatus("testEJTimerTracking_ChargingAndDischarging", 2);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus2, null);
         }
-        JobStatus jobStatus3 = createHpjJobStatus("testHpjTimerTracking_ChargingAndDischarging", 3);
+        JobStatus jobStatus3 =
+                createExpeditedJobStatus("testEJTimerTracking_ChargingAndDischarging", 3);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus3, null);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
         List<TimingSession> expected = new ArrayList<>();
 
         // A job starting while charging. Only the portion that runs during the discharging period
@@ -4076,7 +4152,7 @@
         }
         expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
@@ -4119,7 +4195,7 @@
         }
         expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         // A job starting while discharging and ending while charging. Only the portion that runs
         // during the discharging period should be counted.
@@ -4137,20 +4213,20 @@
             mQuotaController.maybeStopTrackingJobLocked(jobStatus2, null, false);
         }
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /** Tests that TimingSessions are saved properly when all the jobs are background jobs. */
     @Test
-    public void testHpjTimerTracking_AllBackground() {
+    public void testEJTimerTracking_AllBackground() {
         setDischarging();
         setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
 
-        JobStatus jobStatus = createHpjJobStatus("testHpjTimerTracking_AllBackground", 1);
+        JobStatus jobStatus = createExpeditedJobStatus("testEJTimerTracking_AllBackground", 1);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         List<TimingSession> expected = new ArrayList<>();
 
@@ -4165,15 +4241,15 @@
         }
         expected.add(createTimingSession(start, 5 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         // Test overlapping jobs.
-        JobStatus jobStatus2 = createHpjJobStatus("testHpjTimerTracking_AllBackground", 2);
+        JobStatus jobStatus2 = createExpeditedJobStatus("testEJTimerTracking_AllBackground", 2);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus2, null);
         }
 
-        JobStatus jobStatus3 = createHpjJobStatus("testHpjTimerTracking_AllBackground", 3);
+        JobStatus jobStatus3 = createExpeditedJobStatus("testEJTimerTracking_AllBackground", 3);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus3, null);
         }
@@ -4207,21 +4283,21 @@
         }
         expected.add(createTimingSession(start, MINUTE_IN_MILLIS, 3));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /** Tests that Timers don't count foreground jobs. */
     @Test
-    public void testHpjTimerTracking_AllForeground() {
+    public void testEJTimerTracking_AllForeground() {
         setDischarging();
 
-        JobStatus jobStatus = createHpjJobStatus("testHpjTimerTracking_AllForeground", 1);
+        JobStatus jobStatus = createExpeditedJobStatus("testEJTimerTracking_AllForeground", 1);
         setProcessState(ActivityManager.PROCESS_STATE_TOP);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
 
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         synchronized (mQuotaController.mLock) {
             mQuotaController.prepareForExecutionLocked(jobStatus);
@@ -4233,7 +4309,7 @@
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStopTrackingJobLocked(jobStatus, null, false);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
@@ -4241,18 +4317,21 @@
      * states.
      */
     @Test
-    public void testHpjTimerTracking_ForegroundAndBackground() {
+    public void testEJTimerTracking_ForegroundAndBackground() {
         setDischarging();
 
-        JobStatus jobBg1 = createHpjJobStatus("testHpjTimerTracking_ForegroundAndBackground", 1);
-        JobStatus jobBg2 = createHpjJobStatus("testHpjTimerTracking_ForegroundAndBackground", 2);
-        JobStatus jobFg3 = createHpjJobStatus("testHpjTimerTracking_ForegroundAndBackground", 3);
+        JobStatus jobBg1 =
+                createExpeditedJobStatus("testEJTimerTracking_ForegroundAndBackground", 1);
+        JobStatus jobBg2 =
+                createExpeditedJobStatus("testEJTimerTracking_ForegroundAndBackground", 2);
+        JobStatus jobFg3 =
+                createExpeditedJobStatus("testEJTimerTracking_ForegroundAndBackground", 3);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
             mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
             mQuotaController.maybeStartTrackingJobLocked(jobFg3, null);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
         List<TimingSession> expected = new ArrayList<>();
 
         // UID starts out inactive.
@@ -4267,7 +4346,7 @@
         }
         expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
@@ -4296,7 +4375,7 @@
             mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
         }
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
@@ -4341,27 +4420,27 @@
         }
         expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
      * Tests that Timers properly track overlapping top and background jobs.
      */
     @Test
-    public void testHpjTimerTracking_TopAndNonTop() {
+    public void testEJTimerTracking_TopAndNonTop() {
         setDischarging();
 
-        JobStatus jobBg1 = createHpjJobStatus("testHpjTimerTracking_TopAndNonTop", 1);
-        JobStatus jobBg2 = createHpjJobStatus("testHpjTimerTracking_TopAndNonTop", 2);
-        JobStatus jobFg1 = createHpjJobStatus("testHpjTimerTracking_TopAndNonTop", 3);
-        JobStatus jobTop = createHpjJobStatus("testHpjTimerTracking_TopAndNonTop", 4);
+        JobStatus jobBg1 = createExpeditedJobStatus("testEJTimerTracking_TopAndNonTop", 1);
+        JobStatus jobBg2 = createExpeditedJobStatus("testEJTimerTracking_TopAndNonTop", 2);
+        JobStatus jobFg1 = createExpeditedJobStatus("testEJTimerTracking_TopAndNonTop", 3);
+        JobStatus jobTop = createExpeditedJobStatus("testEJTimerTracking_TopAndNonTop", 4);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
             mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
             mQuotaController.maybeStartTrackingJobLocked(jobFg1, null);
             mQuotaController.maybeStartTrackingJobLocked(jobTop, null);
         }
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
         List<TimingSession> expected = new ArrayList<>();
 
         // UID starts out inactive.
@@ -4376,7 +4455,7 @@
         }
         expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
@@ -4405,7 +4484,7 @@
             mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
         }
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
@@ -4460,22 +4539,22 @@
         }
         expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
         assertEquals(expected,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
-     * Tests that HPJs aren't stopped when an app runs out of quota.
+     * Tests that expedited jobs aren't stopped when an app runs out of quota.
      */
     @Test
-    public void testHpjTracking_OutOfQuota_ForegroundAndBackground() {
+    public void testEJTracking_OutOfQuota_ForegroundAndBackground() {
         setDischarging();
 
         JobStatus jobBg =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 1);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 1);
         JobStatus jobTop =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 2);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 2);
         JobStatus jobUnstarted =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 3);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 3);
         trackJobs(jobBg, jobTop, jobUnstarted);
         setStandbyBucket(WORKING_INDEX, jobTop, jobBg, jobUnstarted);
         // Now the package only has 20 seconds to run.
@@ -4483,7 +4562,7 @@
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(
                         JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS,
-                        mQcConstants.HPJ_LIMIT_WORKING_MS - remainingTimeMs, 1), true);
+                        mQcConstants.EJ_LIMIT_WORKING_MS - remainingTimeMs, 1), true);
 
         InOrder inOrder = inOrder(mJobSchedulerService);
 
@@ -4508,7 +4587,7 @@
                 .onControllerStateChanged();
         synchronized (mQuotaController.mLock) {
             assertEquals(remainingTimeMs / 2,
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
         // Go to a background state.
@@ -4517,24 +4596,25 @@
         inOrder.verify(mJobSchedulerService,
                 timeout(remainingTimeMs / 2 + 2 * SECOND_IN_MILLIS).times(1))
                 .onControllerStateChanged();
-        // Top and bg HPJs should still be allowed to run since they started before the app ran
+        // Top and bg EJs should still be allowed to run since they started before the app ran
         // out of quota.
-        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertFalse(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertFalse(
+                jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
         synchronized (mQuotaController.mLock) {
             assertTrue(
                     0 >= mQuotaController
-                            .getRemainingHpjExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+                            .getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
         }
 
         // New jobs to run.
         JobStatus jobBg2 =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 4);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 4);
         JobStatus jobTop2 =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 5);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 5);
         JobStatus jobFg =
-                createHpjJobStatus("testHpjTracking_OutOfQuota_ForegroundAndBackground", 6);
+                createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 6);
         setStandbyBucket(WORKING_INDEX, jobBg2, jobTop2, jobFg);
 
         advanceElapsedClock(20 * SECOND_IN_MILLIS);
@@ -4546,18 +4626,18 @@
         synchronized (mQuotaController.mLock) {
             mQuotaController.prepareForExecutionLocked(jobTop2);
         }
-        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
 
         // App still in foreground so everything should be in quota.
         advanceElapsedClock(20 * SECOND_IN_MILLIS);
         setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
-        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
 
         advanceElapsedClock(20 * SECOND_IN_MILLIS);
         setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
@@ -4565,16 +4645,17 @@
                 .onControllerStateChanged();
         // App is now in background and out of quota. Fg should now change to out of quota since it
         // wasn't started. Top should remain in quota since it started when the app was in TOP.
-        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertFalse(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertTrue(jobTop2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertFalse(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
         trackJobs(jobBg2);
-        assertFalse(jobBg2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
-        assertFalse(jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertFalse(jobBg2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
+        assertFalse(
+                jobUnstarted.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
         synchronized (mQuotaController.mLock) {
             assertTrue(
                     0 >= mQuotaController
-                            .getRemainingHpjExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+                            .getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
         }
     }
 
@@ -4582,26 +4663,26 @@
      * Tests that Timers properly track overlapping top and background jobs.
      */
     @Test
-    public void testHpjTimerTrackingSeparateFromRegularTracking() {
+    public void testEJTimerTrackingSeparateFromRegularTracking() {
         setDischarging();
         setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
 
-        JobStatus jobReg1 = createJobStatus("testHpjTimerTrackingSeparateFromRegularTracking", 1);
-        JobStatus jobHpj1 =
-                createHpjJobStatus("testHpjTimerTrackingSeparateFromRegularTracking", 2);
-        JobStatus jobReg2 = createJobStatus("testHpjTimerTrackingSeparateFromRegularTracking", 3);
-        JobStatus jobHpj2 =
-                createHpjJobStatus("testHpjTimerTrackingSeparateFromRegularTracking", 4);
+        JobStatus jobReg1 = createJobStatus("testEJTimerTrackingSeparateFromRegularTracking", 1);
+        JobStatus jobEJ1 =
+                createExpeditedJobStatus("testEJTimerTrackingSeparateFromRegularTracking", 2);
+        JobStatus jobReg2 = createJobStatus("testEJTimerTrackingSeparateFromRegularTracking", 3);
+        JobStatus jobEJ2 =
+                createExpeditedJobStatus("testEJTimerTrackingSeparateFromRegularTracking", 4);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobReg1, null);
-            mQuotaController.maybeStartTrackingJobLocked(jobHpj1, null);
+            mQuotaController.maybeStartTrackingJobLocked(jobEJ1, null);
             mQuotaController.maybeStartTrackingJobLocked(jobReg2, null);
-            mQuotaController.maybeStartTrackingJobLocked(jobHpj2, null);
+            mQuotaController.maybeStartTrackingJobLocked(jobEJ2, null);
         }
         assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
         List<TimingSession> expectedRegular = new ArrayList<>();
-        List<TimingSession> expectedHpj = new ArrayList<>();
+        List<TimingSession> expectedEJ = new ArrayList<>();
 
         // First, regular job runs by itself.
         long start = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -4615,31 +4696,31 @@
         expectedRegular.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expectedRegular,
                 mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
-        assertNull(mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertNull(mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
-        // Next, HPJ runs by itself.
+        // Next, EJ runs by itself.
         start = JobSchedulerService.sElapsedRealtimeClock.millis();
         synchronized (mQuotaController.mLock) {
-            mQuotaController.prepareForExecutionLocked(jobHpj1);
+            mQuotaController.prepareForExecutionLocked(jobEJ1);
         }
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         synchronized (mQuotaController.mLock) {
-            mQuotaController.maybeStopTrackingJobLocked(jobHpj1, null, false);
+            mQuotaController.maybeStopTrackingJobLocked(jobEJ1, null, false);
         }
-        expectedHpj.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        expectedEJ.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expectedRegular,
                 mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
-        assertEquals(expectedHpj,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertEquals(expectedEJ,
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
-        // Finally, a regular job and HPJ happen to overlap runs.
+        // Finally, a regular job and EJ happen to overlap runs.
         start = JobSchedulerService.sElapsedRealtimeClock.millis();
         synchronized (mQuotaController.mLock) {
-            mQuotaController.prepareForExecutionLocked(jobHpj2);
+            mQuotaController.prepareForExecutionLocked(jobEJ2);
         }
         advanceElapsedClock(5 * SECOND_IN_MILLIS);
         synchronized (mQuotaController.mLock) {
@@ -4647,9 +4728,9 @@
         }
         advanceElapsedClock(5 * SECOND_IN_MILLIS);
         synchronized (mQuotaController.mLock) {
-            mQuotaController.maybeStopTrackingJobLocked(jobHpj2, null, false);
+            mQuotaController.maybeStopTrackingJobLocked(jobEJ2, null, false);
         }
-        expectedHpj.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        expectedEJ.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
         advanceElapsedClock(5 * SECOND_IN_MILLIS);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStopTrackingJobLocked(jobReg2, null, false);
@@ -4658,8 +4739,8 @@
                 createTimingSession(start + 5 * SECOND_IN_MILLIS, 10 * SECOND_IN_MILLIS, 1));
         assertEquals(expectedRegular,
                 mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
-        assertEquals(expectedHpj,
-                mQuotaController.getHpjTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        assertEquals(expectedEJ,
+                mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
@@ -4667,8 +4748,8 @@
      * being phased out.
      */
     @Test
-    public void testHpjTracking_RollingQuota() {
-        JobStatus jobStatus = createHpjJobStatus("testHpjTracking_RollingQuota", 1);
+    public void testEJTracking_RollingQuota() {
+        JobStatus jobStatus = createExpeditedJobStatus("testEJTracking_RollingQuota", 1);
         synchronized (mQuotaController.mLock) {
             mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         }
@@ -4682,15 +4763,15 @@
         // The package only has one second to run, but this session is at the edge of the rolling
         // window, so as the package "reaches its quota" it will have more to keep running.
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
-                createTimingSession(now - mQcConstants.HPJ_WINDOW_SIZE_MS,
+                createTimingSession(now - mQcConstants.EJ_WINDOW_SIZE_MS,
                         10 * SECOND_IN_MILLIS - remainingTimeMs, 1), true);
         mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
                 createTimingSession(now - HOUR_IN_MILLIS,
-                        mQcConstants.HPJ_LIMIT_WORKING_MS - 10 * SECOND_IN_MILLIS, 1), true);
+                        mQcConstants.EJ_LIMIT_WORKING_MS - 10 * SECOND_IN_MILLIS, 1), true);
 
         synchronized (mQuotaController.mLock) {
             assertEquals(remainingTimeMs,
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
 
             // Start the job.
@@ -4702,19 +4783,19 @@
         verify(mJobSchedulerService,
                 timeout(remainingTimeMs + 2 * SECOND_IN_MILLIS).times(0))
                 .onControllerStateChanged();
-        assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_HPJ_QUOTA));
+        assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_EXPEDITED_QUOTA));
         // The job used up the remaining quota, but in that time, the same amount of time in the
         // old TimingSession also fell out of the quota window, so it should still have the same
         // amount of remaining time left its quota.
         synchronized (mQuotaController.mLock) {
             assertEquals(remainingTimeMs,
-                    mQuotaController.getRemainingHpjExecutionTimeLocked(
+                    mQuotaController.getRemainingEJExecutionTimeLocked(
                             SOURCE_USER_ID, SOURCE_PACKAGE));
         }
         // Handler is told to check when the quota will be consumed, not when the initial
         // remaining time is over.
         verify(handler, atLeast(1)).sendMessageDelayed(
-                argThat(msg -> msg.what == QuotaController.MSG_REACHED_HPJ_QUOTA),
+                argThat(msg -> msg.what == QuotaController.MSG_REACHED_EJ_QUOTA),
                 eq(10 * SECOND_IN_MILLIS));
         verify(handler, never()).sendMessageDelayed(any(), eq(remainingTimeMs));
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/OWNERS b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS
new file mode 100644
index 0000000..696a0c2
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS
@@ -0,0 +1 @@
+file:/location/java/android/location/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index 98fd1c9..2b21cc5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -43,9 +43,9 @@
 import android.location.GnssAntennaInfo.SphericalCorrections;
 import android.location.GnssClock;
 import android.location.GnssMeasurementCorrections;
+import android.location.GnssMeasurementRequest;
 import android.location.GnssMeasurementsEvent;
 import android.location.GnssNavigationMessage;
-import android.location.GnssRequest;
 import android.location.GnssSingleSatCorrection;
 import android.location.IGnssAntennaInfoListener;
 import android.location.IGnssMeasurementsListener;
@@ -403,7 +403,7 @@
 
         assertThrows(SecurityException.class,
                 () -> mGnssManagerService.addGnssMeasurementsListener(
-                        new GnssRequest.Builder().build(), mockGnssMeasurementsListener,
+                        new GnssMeasurementRequest.Builder().build(), mockGnssMeasurementsListener,
                         TEST_PACKAGE, null));
 
         mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
@@ -422,7 +422,7 @@
         enableLocationPermissions();
 
         mGnssManagerService.addGnssMeasurementsListener(
-                new GnssRequest.Builder().build(),
+                new GnssMeasurementRequest.Builder().build(),
                 mockGnssMeasurementsListener,
                 TEST_PACKAGE, null);
 
@@ -470,7 +470,8 @@
 
         enableLocationPermissions();
 
-        mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
+        mGnssManagerService.addGnssMeasurementsListener(
+                new GnssMeasurementRequest.Builder().build(),
                 mockGnssMeasurementsListener,
                 TEST_PACKAGE, null);
 
@@ -494,7 +495,8 @@
 
         enableLocationPermissions();
 
-        mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
+        mGnssManagerService.addGnssMeasurementsListener(
+                new GnssMeasurementRequest.Builder().build(),
                 mockGnssMeasurementsListener,
                 TEST_PACKAGE, null);
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index edae08a3..015eead 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -68,12 +68,12 @@
 import com.android.server.testutils.mock
 import com.android.server.testutils.nullable
 import com.android.server.testutils.whenever
+import com.android.server.utils.WatchedArrayMap
 import org.junit.Assert
 import org.junit.rules.TestRule
 import org.junit.runner.Description
 import org.junit.runners.model.Statement
 import org.mockito.AdditionalMatchers.or
-import org.mockito.invocation.InvocationOnMock
 import org.mockito.quality.Strictness
 import java.io.File
 import java.io.IOException
@@ -114,7 +114,7 @@
     private val mPreExistingSettings = ArrayMap<String, PackageSetting>()
 
     /** The active map simulating the in memory storage of Settings  */
-    private val mSettingsMap = ArrayMap<String, PackageSetting>()
+    private val mSettingsMap = WatchedArrayMap<String, PackageSetting>()
 
     init {
         val apply = ExtendedMockito.mockitoSession()
@@ -268,7 +268,7 @@
         wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory)
         wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName")
         wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory)
-        wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString())}
+        wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString()) }
                 .thenAnswer { FutureTask<Any?>(it.getArgument(0), null) }
 
         wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/usage/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/tests/servicestests/apks/OWNERS b/services/tests/servicestests/apks/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/apks/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/assets/NetworkPolicy/OWNERS b/services/tests/servicestests/assets/NetworkPolicy/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
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/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index a02c533..6814c050a 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -163,16 +163,26 @@
     }
 
     @Test
-    public void testIsEmergencyGestureEnabled_settingDisabled() {
+    public void testIsEmergencyGestureSettingEnabled_settingDisabled() {
+        withEmergencyGestureEnabledConfigValue(true);
         withEmergencyGestureEnabledSettingValue(false);
-        assertFalse(mGestureLauncherService.isEmergencyGestureEnabled(
+        assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled(
                 mContext, FAKE_USER_ID));
     }
 
     @Test
-    public void testIsEmergencyGestureEnabled_settingEnabled() {
+    public void testIsEmergencyGestureSettingEnabled_settingEnabled() {
+        withEmergencyGestureEnabledConfigValue(true);
         withEmergencyGestureEnabledSettingValue(true);
-        assertTrue(mGestureLauncherService.isEmergencyGestureEnabled(
+        assertTrue(mGestureLauncherService.isEmergencyGestureSettingEnabled(
+                mContext, FAKE_USER_ID));
+    }
+
+    @Test
+    public void testIsEmergencyGestureSettingEnabled_supportDisabled() {
+        withEmergencyGestureEnabledConfigValue(false);
+        withEmergencyGestureEnabledSettingValue(true);
+        assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled(
                 mContext, FAKE_USER_ID));
     }
 
@@ -438,6 +448,7 @@
             testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch() {
         withCameraDoubleTapPowerEnableConfigValue(true);
         withCameraDoubleTapPowerDisableSettingValue(0);
+        withEmergencyGestureEnabledConfigValue(true);
         withEmergencyGestureEnabledSettingValue(true);
         mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
         mGestureLauncherService.updateEmergencyGestureEnabled();
@@ -527,6 +538,7 @@
     @Test
     public void
             testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow() {
+        withEmergencyGestureEnabledConfigValue(true);
         withEmergencyGestureEnabledSettingValue(true);
         mGestureLauncherService.updateEmergencyGestureEnabled();
         withUserSetupCompleteValue(true);
@@ -580,6 +592,7 @@
     @Test
     public void
             testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted() {
+        withEmergencyGestureEnabledConfigValue(true);
         withEmergencyGestureEnabledSettingValue(true);
         mGestureLauncherService.updateEmergencyGestureEnabled();
         withUserSetupCompleteValue(true);
@@ -1146,6 +1159,12 @@
                 .thenReturn(enableConfigValue);
     }
 
+    private void withEmergencyGestureEnabledConfigValue(boolean enableConfigValue) {
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_emergencyGestureEnabled))
+                .thenReturn(enableConfigValue);
+    }
+
     private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) {
         Settings.Secure.putIntForUser(
                 mContentResolver,
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..6561778
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -0,0 +1,7 @@
+per-file *Alarm* = file:/apex/jobscheduler/OWNERS
+per-file *AppOp* = file:/core/java/android/permission/OWNERS
+per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
+per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
index 044bdba..726536d 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
@@ -19,17 +19,38 @@
 import static com.android.server.testutils.TestUtils.assertExpectException;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.vibrator.IVibrator;
 import android.os.CombinedVibrationEffect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
 import android.os.Process;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.os.VibratorInfo;
+import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.server.vibrator.VibratorController;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -37,6 +58,9 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Tests for {@link VibratorManagerService}.
  *
@@ -51,24 +75,54 @@
     private static final VibrationAttributes ALARM_ATTRS =
             new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
 
-    @Rule
-    public MockitoRule rule = MockitoJUnit.rule();
+    @Rule public MockitoRule rule = MockitoJUnit.rule();
 
-    @Mock
-    private VibratorManagerService.NativeWrapper mNativeWrapperMock;
+    @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
+    @Mock private PowerManagerInternal mPowerManagerInternalMock;
+    @Mock private PowerSaveState mPowerSaveStateMock;
+
+    private final Map<Integer, VibratorController.NativeWrapper> mNativeWrappers = new HashMap<>();
+
+    private TestLooper mTestLooper;
 
     @Before
     public void setUp() throws Exception {
+        mTestLooper = new TestLooper();
+
+        when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION))
+                .thenReturn(mPowerSaveStateMock);
+
+        addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
     }
 
     private VibratorManagerService createService() {
-        return new VibratorManagerService(InstrumentationRegistry.getContext(),
+        VibratorManagerService service = new VibratorManagerService(
+                InstrumentationRegistry.getContext(),
                 new VibratorManagerService.Injector() {
                     @Override
                     VibratorManagerService.NativeWrapper getNativeWrapper() {
                         return mNativeWrapperMock;
                     }
+
+                    @Override
+                    Handler createHandler(Looper looper) {
+                        return new Handler(mTestLooper.getLooper());
+                    }
+
+                    @Override
+                    VibratorController createVibratorController(int vibratorId,
+                            VibratorController.OnVibrationCompleteListener listener) {
+                        return new VibratorController(
+                                vibratorId, listener, mNativeWrappers.get(vibratorId));
+                    }
                 });
+        service.systemReady();
+        return service;
     }
 
     @Test
@@ -85,8 +139,156 @@
 
     @Test
     public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() {
-        when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1, 2});
-        assertArrayEquals(new int[]{1, 2}, createService().getVibratorIds());
+        mNativeWrappers.put(1, mockVibrator(/* capabilities= */ 0));
+        mNativeWrappers.put(2, mockVibrator(/* capabilities= */ 0));
+        when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{2, 1});
+        assertArrayEquals(new int[]{2, 1}, createService().getVibratorIds());
+    }
+
+    @Test
+    public void getVibratorInfo_withMissingVibratorId_returnsNull() {
+        mockVibrators(mockVibrator(/* capabilities= */ 0));
+        assertNull(createService().getVibratorInfo(2));
+    }
+
+    @Test
+    public void getVibratorInfo_withExistingVibratorId_returnsHalInfoForVibrator() {
+        VibratorController.NativeWrapper vibratorMock = mockVibrator(
+                IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL);
+        when(vibratorMock.getSupportedEffects()).thenReturn(
+                new int[]{VibrationEffect.EFFECT_CLICK});
+        when(vibratorMock.getSupportedPrimitives()).thenReturn(
+                new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+        mNativeWrappers.put(1, vibratorMock);
+        when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1});
+        VibratorInfo info = createService().getVibratorInfo(1);
+
+        assertNotNull(info);
+        assertEquals(1, info.getId());
+        assertTrue(info.hasAmplitudeControl());
+        assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS));
+        assertFalse(info.hasCapability(IVibrator.CAP_ON_CALLBACK));
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
+                info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
+                info.isEffectSupported(VibrationEffect.EFFECT_TICK));
+        assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
+        assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withMono_enablesAlwaysOnEffectToAllVibratorsWithCapability() {
+        VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[]{
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+                mockVibrator(/* capabilities= */ 0),
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+        };
+        mockVibrators(vibratorMocks);
+
+        CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+        assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
+
+        // Only vibrators 0 and 2 have always-on capabilities.
+        verify(vibratorMocks[0]).alwaysOnEnable(
+                eq(1L), eq((long) VibrationEffect.EFFECT_CLICK),
+                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG));
+        verify(vibratorMocks[1], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        verify(vibratorMocks[2]).alwaysOnEnable(
+                eq(1L), eq((long) VibrationEffect.EFFECT_CLICK),
+                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG));
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withStereo_enablesAlwaysOnEffectToAllVibratorsWithCapability() {
+        VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] {
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+                mockVibrator(0),
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+        };
+        mockVibrators(vibratorMocks);
+
+        CombinedVibrationEffect effect = CombinedVibrationEffect.startSynced()
+                .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+                .addVibrator(1, VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK))
+                .addVibrator(2, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+                .combine();
+        assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
+
+        // Enables click on vibrator 0 and tick on vibrator 1 only.
+        verify(vibratorMocks[0]).alwaysOnEnable(
+                eq(1L), eq((long) VibrationEffect.EFFECT_CLICK),
+                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG));
+        verify(vibratorMocks[1]).alwaysOnEnable(
+                eq(1L), eq((long) VibrationEffect.EFFECT_TICK),
+                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG));
+        verify(vibratorMocks[2], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        verify(vibratorMocks[3], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffects() {
+        VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] {
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+                mockVibrator(0),
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL),
+        };
+        mockVibrators(vibratorMocks);
+
+        assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS));
+
+        // Disables only 0 and 2 that have capability.
+        verify(vibratorMocks[0]).alwaysOnDisable(eq(1L));
+        verify(vibratorMocks[1], never()).alwaysOnDisable(anyLong());
+        verify(vibratorMocks[2]).alwaysOnDisable(eq(1L));
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() {
+        VibratorController.NativeWrapper vibratorMock =
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL);
+        mockVibrators(vibratorMock);
+
+        CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
+                VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+        assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
+
+        verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        verify(vibratorMock, never()).alwaysOnDisable(anyLong());
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withNonSyncedEffect_ignoresEffect() {
+        VibratorController.NativeWrapper vibratorMock =
+                mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL);
+        mockVibrators(vibratorMock);
+
+        CombinedVibrationEffect effect = CombinedVibrationEffect.startSequential()
+                .addNext(0, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .combine();
+        assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
+
+        verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        verify(vibratorMock, never()).alwaysOnDisable(anyLong());
+    }
+
+    @Test
+    public void setAlwaysOnEffect_withNoVibratorWithCapability_ignoresEffect() {
+        VibratorController.NativeWrapper vibratorMock = mockVibrator(0);
+        mockVibrators(vibratorMock);
+        VibratorManagerService service = createService();
+
+        CombinedVibrationEffect mono = CombinedVibrationEffect.createSynced(
+                VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+        CombinedVibrationEffect stereo = CombinedVibrationEffect.startSynced()
+                .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+                .combine();
+        assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 1, mono, ALARM_ATTRS));
+        assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 2, stereo, ALARM_ATTRS));
+
+        verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        verify(vibratorMock, never()).alwaysOnDisable(anyLong());
     }
 
     @Test
@@ -107,4 +309,24 @@
         assertExpectException(UnsupportedOperationException.class,
                 "Not implemented", () -> service.cancelVibrate(service));
     }
+
+    private VibratorController.NativeWrapper mockVibrator(int capabilities) {
+        VibratorController.NativeWrapper wrapper = mock(VibratorController.NativeWrapper.class);
+        when(wrapper.getCapabilities()).thenReturn((long) capabilities);
+        return wrapper;
+    }
+
+    private void mockVibrators(VibratorController.NativeWrapper... wrappers) {
+        int[] ids = new int[wrappers.length];
+        for (int i = 0; i < wrappers.length; i++) {
+            ids[i] = i;
+            mNativeWrappers.put(i, wrappers[i]);
+        }
+        when(mNativeWrapperMock.getVibratorIds()).thenReturn(ids);
+    }
+
+    private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+        LocalServices.removeServiceForTest(clazz);
+        LocalServices.addService(clazz, mock);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 64f3135..32ca7b5 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server;
 
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -52,7 +51,6 @@
 import android.os.IBinder;
 import android.os.IVibratorStateListener;
 import android.os.Looper;
-import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.os.Process;
@@ -62,6 +60,7 @@
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.os.VibratorInfo;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
@@ -101,6 +100,9 @@
 
     private static final int UID = Process.ROOT_UID;
     private static final String PACKAGE_NAME = "package";
+    private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
+    private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
+            .setBatterySaverEnabled(true).build();
     private static final VibrationAttributes ALARM_ATTRS =
             new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
     private static final VibrationAttributes HAPTIC_FEEDBACK_ATTRS =
@@ -118,7 +120,6 @@
 
     @Mock private PackageManagerInternal mPackageManagerInternalMock;
     @Mock private PowerManagerInternal mPowerManagerInternalMock;
-    @Mock private PowerSaveState mPowerSaveStateMock;
     // TODO(b/131311651): replace with a FakeVibrator instead.
     @Mock private Vibrator mVibratorMock;
     @Mock private AppOpsManager mAppOpsManagerMock;
@@ -129,6 +130,7 @@
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
+    private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
 
     @Before
     public void setUp() throws Exception {
@@ -150,8 +152,10 @@
         when(mVibratorStateListenerMock.asBinder()).thenReturn(mVibratorStateListenerBinderMock);
         when(mPackageManagerInternalMock.getSystemUiServiceComponent())
                 .thenReturn(new ComponentName("", ""));
-        when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION))
-                .thenReturn(mPowerSaveStateMock);
+        doAnswer(invocation -> {
+            mRegisteredPowerModeListener = invocation.getArgument(0);
+            return null;
+        }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
         when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
 
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
@@ -168,6 +172,7 @@
 
     @After
     public void tearDown() throws Exception {
+        InputManager.clearInstance();
         LocalServices.removeServiceForTest(PackageManagerInternal.class);
         LocalServices.removeServiceForTest(PowerManagerInternal.class);
     }
@@ -199,7 +204,7 @@
     public void createService_initializesNativeService() {
         createService();
         verify(mNativeWrapperMock).init(eq(0), notNull());
-        verify(mNativeWrapperMock).off();
+        verify(mNativeWrapperMock, times(2)).off(); // Called from constructor and onSystemReady
     }
 
     @Test
@@ -235,93 +240,21 @@
     }
 
     @Test
-    public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() {
-        when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null);
-        assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN},
-                createService().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}));
-    }
-
-    @Test
-    public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() {
-        int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK};
-
+    public void getVibratorInfo_returnsSameInfoFromNative() {
+        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL);
         when(mNativeWrapperMock.getSupportedEffects())
                 .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
-        assertArrayEquals(
-                new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
-                        Vibrator.VIBRATION_EFFECT_SUPPORT_NO},
-                createService().areEffectsSupported(effects));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() {
-        assertArrayEquals(new boolean[]{false, false},
-                createService().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_TICK
-                }));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() {
-        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
-        when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null);
-
-        assertArrayEquals(new boolean[]{false, false},
-                createService().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
-                }));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() {
-        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
         when(mNativeWrapperMock.getSupportedPrimitives())
                 .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
 
-        assertArrayEquals(new boolean[]{true, false},
-                createService().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
-                }));
-    }
-
-    @Test
-    public void setAlwaysOnEffect_withCapabilityAndValidEffect_enablesAlwaysOnEffect() {
-        mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL);
-
-        assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1,
-                VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS));
-        verify(mNativeWrapperMock).alwaysOnEnable(
-                eq(1L), eq((long) VibrationEffect.EFFECT_CLICK),
-                eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG));
-    }
-
-    @Test
-    public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() {
-        mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL);
-
-        assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1,
-                VibrationEffect.createOneShot(100, 255), ALARM_ATTRS));
-        verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong());
-        verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
-    }
-
-    @Test
-    public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffect() {
-        mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL);
-
-        assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS));
-        verify(mNativeWrapperMock).alwaysOnDisable(eq(1L));
-    }
-
-    @Test
-    public void setAlwaysOnEffect_withoutCapability_ignoresEffect() {
-        assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1,
-                VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS));
-        verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong());
-        verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong());
+        VibratorInfo info = createService().getVibratorInfo();
+        assertTrue(info.hasAmplitudeControl());
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
+                info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
+        assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
+                info.isEffectSupported(VibrationEffect.EFFECT_TICK));
+        assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
+        assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
     }
 
     @Test
@@ -346,6 +279,24 @@
     }
 
     @Test
+    public void vibrate_withPowerModeChange_usesLowPowerModeState() {
+        VibratorService service = createService();
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+        vibrate(service, VibrationEffect.createOneShot(1, 1), HAPTIC_FEEDBACK_ATTRS);
+        vibrate(service, VibrationEffect.createOneShot(2, 2), RINGTONE_ATTRS);
+
+        mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
+        vibrate(service, VibrationEffect.createOneShot(3, 3), /* attributes= */ null);
+        vibrate(service, VibrationEffect.createOneShot(4, 4), NOTIFICATION_ATTRS);
+
+        InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+        inOrderVerifier.verify(mNativeWrapperMock, never()).on(eq(1L), anyLong());
+        inOrderVerifier.verify(mNativeWrapperMock).on(eq(2L), anyLong());
+        inOrderVerifier.verify(mNativeWrapperMock).on(eq(3L), anyLong());
+        inOrderVerifier.verify(mNativeWrapperMock).on(eq(4L), anyLong());
+    }
+
+    @Test
     public void vibrate_withAudioAttributes_usesOriginalAudioUsageInAppOpsManager() {
         VibratorService service = createService();
 
@@ -888,7 +839,7 @@
 
     private InputDevice createInputDeviceWithVibrator(int id) {
         return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
-                null, /* hasVibrator= */ true, false, false);
+                null, /* hasVibrator= */ true, false, false, false /* hasSensor */);
     }
 
     private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/OWNERS b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
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/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 9ba9188..44b9f44 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -1174,7 +1174,7 @@
 
     private MagnificationSpec getInterpolatedMagSpec(MagnificationSpec start, MagnificationSpec end,
             float fraction) {
-        MagnificationSpec interpolatedSpec = MagnificationSpec.obtain();
+        MagnificationSpec interpolatedSpec = new MagnificationSpec();
         interpolatedSpec.scale = start.scale + fraction * (end.scale - start.scale);
         interpolatedSpec.offsetX = start.offsetX + fraction * (end.offsetX - start.offsetX);
         interpolatedSpec.offsetY = start.offsetY + fraction * (end.offsetY - start.offsetY);
@@ -1186,7 +1186,7 @@
     }
 
     private MagnificationSpec getMagnificationSpec(float scale, float offsetX, float offsetY) {
-        MagnificationSpec spec = MagnificationSpec.obtain();
+        MagnificationSpec spec = new MagnificationSpec();
         spec.scale = scale;
         spec.offsetX = offsetX;
         spec.offsetY = offsetY;
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/accounts/OWNERS b/services/tests/servicestests/src/com/android/server/accounts/OWNERS
new file mode 100644
index 0000000..df1b4f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accounts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/accounts/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/adb/OWNERS b/services/tests/servicestests/src/com/android/server/adb/OWNERS
new file mode 100644
index 0000000..b97f795
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/adb/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/adb:/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java
new file mode 100644
index 0000000..67d379a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.am;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.util.SparseLongArray;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.power.MeasuredEnergyArray;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test class for {@link MeasuredEnergySnapshot}.
+ *
+ * To run the tests, use
+ * atest FrameworksServicesTests:com.android.server.am.MeasuredEnergySnapshotTest
+ */
+@SmallTest
+public final class MeasuredEnergySnapshotTest {
+    private static final int NUMBER_SUBSYSTEMS = 3;
+    private static final int SUBSYSTEM_DISPLAY = 0;
+    private static final int SUBSYSTEM_NEVER_USED = 1;
+    private static final int SUBSYSTEM_CATAPULT = 2;
+
+    private MeasuredEnergySnapshot mSnapshot;
+
+    // Basic MeasuredEnergyArray that supports all the subsystems. Out of order on purpose.
+    private final int[] mAllSubsystems =
+            {SUBSYSTEM_DISPLAY, SUBSYSTEM_CATAPULT, SUBSYSTEM_NEVER_USED};
+    // E.g. mAllSubsystems[mSubsystemIndices[SUBSYSTEM_CATAPULT]]=SUBSYSTEM_CATAPULT
+    private final int[] mSubsystemIndices = {0, 2, 1};
+    private final long[] mCurrentSubsystemEnergyUJ = {111, 0, 0};
+    private final MeasuredEnergyArray mOmniEnergyArray = new MeasuredEnergyArray() {
+        @Override
+        public int getSubsystem(int index) {
+            return mAllSubsystems[index];
+        }
+
+        @Override
+        public long getEnergy(int index) {
+            return mCurrentSubsystemEnergyUJ[index];
+        }
+
+        @Override
+        public int size() {
+            return mAllSubsystems.length;
+        }
+    };
+    private final MeasuredEnergyArray mJustDisplayEnergyArray = new MeasuredEnergyArray() {
+        @Override
+        public int getSubsystem(int index) {
+            return mAllSubsystems[0];
+        }
+
+        @Override
+        public long getEnergy(int index) {
+            return mCurrentSubsystemEnergyUJ[0];
+        }
+
+        @Override
+        public int size() {
+            return 1;
+        }
+    };
+
+    @Before
+    public void setUp() {
+        mSnapshot = new MeasuredEnergySnapshot(NUMBER_SUBSYSTEMS, mOmniEnergyArray);
+    }
+
+    @Test
+    public void testUpdateAndGetDelta() {
+        SparseLongArray result;
+
+        // Increment DISPLAY by 15
+        incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 15);
+        result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+        assertEquals(1, result.size());
+        assertEquals(15, result.get(SUBSYSTEM_DISPLAY));
+
+        // Increment DISPLAY by 7
+        // Increment CATAPULT by 5. But do NOT include (pull) it in the passed in energy array.
+        incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 7);
+        incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 5);
+        result = mSnapshot.updateAndGetDelta(mJustDisplayEnergyArray); // Just pull display.
+        assertEquals(1, result.size());
+        assertEquals(7, result.get(SUBSYSTEM_DISPLAY));
+
+        // Increment CATAPULT by 64 (in addition to the previous increase of 5)
+        incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 64);
+        result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+        assertEquals(1, result.size());
+        assertEquals(5 + 64, result.get(SUBSYSTEM_CATAPULT));
+
+        // Do nothing
+        result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+        assertEquals("0 results should not appear at all", 0, result.size());
+
+        // Increment DISPLAY by 42
+        incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 42);
+        result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+        assertEquals(1, result.size());
+        assertEquals(42, result.get(SUBSYSTEM_DISPLAY));
+
+        // Increment DISPLAY by 106 and CATAPULT by 13
+        incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 106);
+        incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 13);
+        result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+        assertEquals(2, result.size());
+        assertEquals(106, result.get(SUBSYSTEM_DISPLAY));
+        assertEquals(13, result.get(SUBSYSTEM_CATAPULT));
+    }
+
+    private void incrementEnergyOfSubsystem(int subsystem, long energy) {
+        mCurrentSubsystemEnergyUJ[mSubsystemIndices[subsystem]] += energy;
+    }
+
+    @Test
+    public void testUpdateAndGetDelta_null() {
+        assertNull(mSnapshot.updateAndGetDelta(null));
+    }
+
+    @Test
+    public void testHasSubsystem() {
+        // Setup MeasuredEnergySnapshot which reported some of the subsystems.
+        final int[] subsystems = {SUBSYSTEM_DISPLAY, SUBSYSTEM_CATAPULT};
+        MeasuredEnergyArray measuredEnergyArray = new MeasuredEnergyArray() {
+            @Override
+            public int getSubsystem(int index) {
+                return subsystems[index];
+            }
+
+            @Override
+            public long getEnergy(int index) {
+                return 0; // Irrelevant for this test.
+            }
+
+            @Override
+            public int size() {
+                return subsystems.length;
+            }
+        };
+        final MeasuredEnergySnapshot snapshot =
+                new MeasuredEnergySnapshot(NUMBER_SUBSYSTEMS, measuredEnergyArray);
+
+        assertTrue(snapshot.hasSubsystem(SUBSYSTEM_DISPLAY));
+        assertTrue(snapshot.hasSubsystem(SUBSYSTEM_CATAPULT));
+        assertFalse(snapshot.hasSubsystem(SUBSYSTEM_NEVER_USED));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/OWNERS b/services/tests/servicestests/src/com/android/server/am/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index 1e602f8..41e1563 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -66,11 +66,11 @@
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
 
         // Stop watching
         appOpsManager.stopWatchingNoted(listener);
@@ -94,7 +94,7 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(2)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
 
         // Finish up
         appOpsManager.stopWatchingNoted(listener);
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
index 1aa697b..fec8aa9 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
@@ -63,11 +63,11 @@
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
         inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
 
         // Stop watching
         appOpsManager.stopWatchingStarted(listener);
@@ -91,7 +91,7 @@
         verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
                 .times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
                 eq(Process.myUid()), eq(getContext().getPackageName()),
-                eq(AppOpsManager.MODE_ALLOWED));
+                eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
         verifyNoMoreInteractions(listener);
 
         // Finish up
diff --git a/services/tests/servicestests/src/com/android/server/appop/OWNERS b/services/tests/servicestests/src/com/android/server/appop/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appop/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/OWNERS b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS
new file mode 100644
index 0000000..ebe9e4e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
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/attention/OWNERS b/services/tests/servicestests/src/com/android/server/attention/OWNERS
new file mode 100644
index 0000000..51fc9bd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/attention/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/attention/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/backup/OWNERS b/services/tests/servicestests/src/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index e588370..8c63bfc 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -190,6 +190,22 @@
     }
 
     @Test
+    public void testIsChangeEnabledForInvalidApp() throws Exception {
+        final long disabledChangeId = 1234L;
+        final long enabledChangeId = 1235L;
+        final long targetSdkChangeId = 1236L;
+        CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+                .addEnabledChangeWithId(enabledChangeId)
+                .addDisabledChangeWithId(disabledChangeId)
+                .addEnableSinceSdkChangeWithId(42, targetSdkChangeId)
+                .build();
+
+        assertThat(compatConfig.isChangeEnabled(enabledChangeId, null)).isTrue();
+        assertThat(compatConfig.isChangeEnabled(disabledChangeId, null)).isFalse();
+        assertThat(compatConfig.isChangeEnabled(targetSdkChangeId, null)).isTrue();
+    }
+
+    @Test
     public void testPreventAddOverride() throws Exception {
         final long changeId = 1234L;
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
diff --git a/services/tests/servicestests/src/com/android/server/compat/OWNERS b/services/tests/servicestests/src/com/android/server/compat/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
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 e2c5e97..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
@@ -5127,7 +5119,7 @@
                 admin1.getPackageName(), managedProfileUserId);
 
         try {
-            assertExpectException(IllegalArgumentException.class, null, () ->
+            assertExpectException(SecurityException.class, null, () ->
                     parentDpm.setPasswordQuality(
                             admin1, DevicePolicyManager.PASSWORD_QUALITY_COMPLEX));
         } finally {
@@ -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/devicepolicy/OWNERS b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
index 07ea855..2d76537 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
@@ -37,6 +37,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -83,6 +84,7 @@
     }
 
     @Test
+    @Ignore
     public void testFileContentValid() {
         TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
         assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OWNERS b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/display/OWNERS b/services/tests/servicestests/src/com/android/server/display/OWNERS
new file mode 100644
index 0000000..6ce1ee4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/display/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
new file mode 100644
index 0000000..da9dcb7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/** Tests for {@link DevicePowerStatusAction} */
+@SmallTest
+@RunWith(JUnit4.class)
+public class DevicePowerStatusActionTest {
+
+    private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+
+    private Context mContextSpy;
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecLocalDevice mPlaybackDevice;
+    private FakeNativeWrapper mNativeWrapper;
+
+    private TestLooper mTestLooper = new TestLooper();
+    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+    private int mPhysicalAddress;
+
+    private DevicePowerStatusAction mDevicePowerStatusAction;
+
+    @Mock private IHdmiControlCallback mCallbackMock;
+    @Mock private IPowerManager mIPowerManagerMock;
+    @Mock private IThermalService mIThermalServiceMock;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+
+        PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
+                mIThermalServiceMock, new Handler(mTestLooper.getLooper()));
+        when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
+        when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
+        when(mIPowerManagerMock.isInteractive()).thenReturn(true);
+
+        HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
+
+        mHdmiControlService = new HdmiControlService(mContextSpy) {
+            @Override
+            AudioManager getAudioManager() {
+                return new AudioManager() {
+                    @Override
+                    public void setWiredDeviceConnectionState(
+                            int type, int state, String address, String name) {
+                        // Do nothing.
+                    }
+                };
+            }
+
+            @Override
+            void wakeUp() {
+            }
+
+            @Override
+            boolean isPowerStandby() {
+                return false;
+            }
+
+            @Override
+            protected PowerManager getPowerManager() {
+                return powerManager;
+            }
+
+            @Override
+            protected void writeStringSystemProperty(String key, String value) {
+                // do nothing
+            }
+
+            @Override
+            protected HdmiCecConfig getHdmiCecConfig() {
+                return hdmiCecConfig;
+            }
+        };
+
+        Looper looper = mTestLooper.getLooper();
+        mHdmiControlService.setIoLooper(looper);
+        mNativeWrapper = new FakeNativeWrapper();
+        HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
+                this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+        mHdmiControlService.setCecController(hdmiCecController);
+        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+        mHdmiControlService.initService();
+        mPhysicalAddress = 0x2000;
+        mNativeWrapper.setPhysicalAddress(mPhysicalAddress);
+        mPlaybackDevice = new HdmiCecLocalDevicePlayback(
+                mHdmiControlService);
+        mPlaybackDevice.init();
+        mLocalDevices.add(mPlaybackDevice);
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mDevicePowerStatusAction = DevicePowerStatusAction.create(mPlaybackDevice, ADDR_TV,
+                mCallbackMock);
+        mTestLooper.dispatchAll();
+    }
+
+    @Test
+    public void queryDisplayStatus_sendsRequestAndHandlesResponse() throws Exception {
+        mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+                mPlaybackDevice.mAddress, ADDR_TV);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+
+        HdmiCecMessage response = HdmiCecMessageBuilder.buildReportPowerStatus(
+                ADDR_TV, mPlaybackDevice.mAddress, HdmiControlManager.POWER_STATUS_STANDBY);
+        mNativeWrapper.onCecMessage(response);
+        mTestLooper.dispatchAll();
+
+        verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_STANDBY);
+    }
+
+    @Test
+    public void queryDisplayStatus_sendsRequest_nack() throws Exception {
+        mNativeWrapper.setMessageSendResult(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS,
+                SendMessageResult.NACK);
+
+        mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+        mTestLooper.dispatchAll();
+
+        verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_UNKNOWN);
+    }
+
+    @Test
+    public void queryDisplayStatus_sendsRequest_timeout_retriesSuccessfully() throws Exception {
+        mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+
+        HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+                mPlaybackDevice.mAddress, ADDR_TV);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+
+        HdmiCecMessage response = HdmiCecMessageBuilder.buildReportPowerStatus(
+                ADDR_TV, mPlaybackDevice.mAddress, HdmiControlManager.POWER_STATUS_STANDBY);
+        mNativeWrapper.onCecMessage(response);
+        mTestLooper.dispatchAll();
+
+        verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_STANDBY);
+    }
+
+    @Test
+    public void queryDisplayStatus_sendsRequest_timeout_retriesFailure() throws Exception {
+        mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+                mPlaybackDevice.mAddress, ADDR_TV);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(TIMEOUT_MS);
+        mTestLooper.dispatchAll();
+
+        verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_UNKNOWN);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
index 227e8c7..e5bcedb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
@@ -77,6 +77,15 @@
                     + "    </allowed-values>"
                     + "    <default-value int-value=\"1\" />"
                     + "  </setting>"
+                    + "  <setting name=\"hdmi_cec_enabled\""
+                    + "           value-type=\"int\""
+                    + "           user-configurable=\"true\">"
+                    + "    <allowed-values>"
+                    + "      <value int-value=\"0\" />"
+                    + "      <value int-value=\"1\" />"
+                    + "    </allowed-values>"
+                    + "    <default-value int-value=\"1\" />"
+                    + "  </setting>"
                     + "</cec-settings>";
 
     FakeHdmiCecConfig(@NonNull Context context) {
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..2f2e97c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -30,6 +30,8 @@
 import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
 
 import android.content.Context;
 import android.hardware.hdmi.HdmiControlManager;
@@ -79,7 +81,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() {
@@ -257,4 +259,19 @@
         mTestLooper.dispatchAll();
         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
     }
+
+    @Test
+    public void testIsLanguage() {
+        assertTrue(HdmiCecController.isLanguage("en"));
+        assertTrue(HdmiCecController.isLanguage("eng"));
+        assertTrue(HdmiCecController.isLanguage("ger"));
+        assertTrue(HdmiCecController.isLanguage("zh"));
+        assertTrue(HdmiCecController.isLanguage("zhi"));
+        assertTrue(HdmiCecController.isLanguage("zho"));
+
+        assertFalse(HdmiCecController.isLanguage(null));
+        assertFalse(HdmiCecController.isLanguage(""));
+        assertFalse(HdmiCecController.isLanguage("e"));
+        assertFalse(HdmiCecController.isLanguage("一")); // language code must be ASCII
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index f7d52b6..7aea4ff 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -1334,4 +1334,31 @@
         assertThat(mNativeWrapper.getResultMessages()).contains(userControlReleased);
         assertThat(mStandby).isFalse();
     }
+
+    @Test
+    public void shouldHandleTvPowerKey_CecDisabled() {
+        mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+        assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+    }
+
+    @Test
+    public void shouldHandleTvPowerKey_PowerControlModeNone() {
+        mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+                HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+                HdmiControlManager.POWER_CONTROL_MODE_NONE);
+        assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+    }
+
+    @Test
+    public void shouldHandleTvPowerKey_CecEnabled_PowerControlModeTv() {
+        mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+        mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+                HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+                HdmiControlManager.POWER_CONTROL_MODE_TV);
+        assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isTrue();
+    }
 }
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 2f49fb7..ae59609 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -25,6 +25,8 @@
 import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
 import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -110,6 +112,7 @@
     private HdmiCecMessageValidator mMessageValidator;
     private static byte[] param;
     private boolean mStandbyMessageReceived;
+    private boolean mWakeupMessageReceived;
     private boolean isControlEnabled;
     private int mPowerStatus;
 
@@ -129,9 +132,21 @@
                     }
 
                     @Override
+                    boolean isPowerStandbyOrTransient() {
+                        return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY
+                                || mPowerStatus
+                                == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+                    }
+
+                    @Override
                     void standby() {
                         mStandbyMessageReceived = true;
                     }
+
+                    @Override
+                    void wakeUp() {
+                        mWakeupMessageReceived = true;
+                    }
                 };
         mHdmiControlService.setIoLooper(mTestLooper.getLooper());
         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
@@ -264,4 +279,109 @@
 
         assertFalse(result);
     }
+
+    @Test
+    public void handleCecVersion_isHandled() {
+        boolean result = mHdmiLocalDevice.onMessage(
+                HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress,
+                        HdmiControlManager.HDMI_CEC_VERSION_1_4_B));
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void handleUserControlPressed_power_localDeviceInStandby_shouldTurnOn() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isTrue();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_power_localDeviceOn_shouldNotChangePowerStatus() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isFalse();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerToggleFunction_localDeviceInStandby_shouldTurnOn() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isTrue();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerToggleFunction_localDeviceOn_shouldTurnOff() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isFalse();
+        assertThat(mStandbyMessageReceived).isTrue();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerOnFunction_localDeviceInStandby_shouldTurnOn() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isTrue();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerOnFunction_localDeviceOn_noPowerStatusChange() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isFalse();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerOffFunction_localDeviceStandby_noPowerStatusChange() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isFalse();
+        assertThat(mStandbyMessageReceived).isFalse();
+    }
+
+    @Test
+    public void handleUserControlPressed_powerOffFunction_localDeviceOn_shouldTurnOff() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
+                        HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION));
+
+        assertThat(result).isTrue();
+        assertThat(mWakeupMessageReceived).isFalse();
+        assertThat(mStandbyMessageReceived).isTrue();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index d24b376..81f55d8 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -192,4 +192,15 @@
         assertThat(mHdmiControlService.getActiveSource().getPhysicalAddress()).isEqualTo(
                 externalDevice.getPhysicalAddress());
     }
+
+    @Test
+    public void shouldHandleTvPowerKey_CecEnabled_PowerControlModeTv() {
+        mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+        mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setStringValue(
+                HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+                HdmiControlManager.POWER_CONTROL_MODE_TV);
+        assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+    }
 }
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/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index 6285f58..5b01920 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -121,6 +121,16 @@
     }
 
     @Test
+    public void isValid_systemAudioModeRequest() {
+        assertMessageValidity("40:70:00:00").isEqualTo(OK);
+        assertMessageValidity("40:70").isEqualTo(OK);
+
+        assertMessageValidity("F0:70").isEqualTo(ERROR_SOURCE);
+        // Invalid physical address
+        assertMessageValidity("40:70:10:10").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
     public void isValid_setSystemAudioMode() {
         assertMessageValidity("40:72:00").isEqualTo(OK);
         assertMessageValidity("4F:72:01:03").isEqualTo(OK);
@@ -340,6 +350,8 @@
         assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER);
         // Invalid External PLug
         assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER);
+        // Invalid Physical Address
+        assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:10").isEqualTo(ERROR_PARAMETER);
     }
 
     @Test
@@ -494,6 +506,51 @@
     }
 
     @Test
+    public void isValid_tunerDeviceStatus() {
+        // Displaying digital tuner
+        assertMessageValidity("40:07:00:00:11:CE:90:0F:00:78").isEqualTo(OK);
+        assertMessageValidity("40:07:80:10:13:0B:34:38").isEqualTo(OK);
+        assertMessageValidity("40:07:00:9A:06:F9:D3:E6").isEqualTo(OK);
+        assertMessageValidity("40:07:00:91:09:F4:40:C8").isEqualTo(OK);
+        // Not displaying tuner
+        assertMessageValidity("40:07:01").isEqualTo(OK);
+        assertMessageValidity("40:07:81:07:64:B9:02").isEqualTo(OK);
+        // Displaying analogue tuner
+        assertMessageValidity("40:07:02:00:13:0F:00:96").isEqualTo(OK);
+        assertMessageValidity("40:07:82:02:EA:60:1F").isEqualTo(OK);
+
+        assertMessageValidity("4F:07:00:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:07:82:02:EA:60:1F").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:07").isEqualTo(ERROR_PARAMETER_SHORT);
+
+        // Invalid display info
+        assertMessageValidity("40:07:09:A1:8C:17:51").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:07:A7:0C:29").isEqualTo(ERROR_PARAMETER);
+        // Invalid Digital Broadcast System
+        assertMessageValidity("40:07:00:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER);
+        // Invalid Digital Broadcast System
+        assertMessageValidity("40:07:80:A0:07:95:F1").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for ARIB Broadcast system
+        assertMessageValidity("40:07:00:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for ATSC Broadcast system
+        assertMessageValidity("40:07:80:10:13:0B:34").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for DVB Broadcast system
+        assertMessageValidity("40:07:00:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER);
+        // Invalid channel number format
+        assertMessageValidity("40:07:80:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for 1 part channel number
+        assertMessageValidity("40:07:00:90:04:F7").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for 2 part channel number
+        assertMessageValidity("40:07:80:91:09:F4:40").isEqualTo(ERROR_PARAMETER);
+        // Invalid Analogue Broadcast type
+        assertMessageValidity("40:07:02:03:EA:60:1F").isEqualTo(ERROR_PARAMETER);
+        // Invalid Analogue Frequency
+        assertMessageValidity("40:07:82:00:FF:FF:00").isEqualTo(ERROR_PARAMETER);
+        // Invalid Broadcast system
+        assertMessageValidity("40:07:02:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
     public void isValid_UserControlPressed() {
         assertMessageValidity("40:44:07").isEqualTo(OK);
         assertMessageValidity("40:44:52:A7").isEqualTo(OK);
@@ -536,6 +593,59 @@
         assertMessageValidity("40:44:57:40").isEqualTo(ERROR_PARAMETER);
     }
 
+    @Test
+    public void isValid_physicalAddress() {
+        assertMessageValidity("4F:82:10:00").isEqualTo(OK);
+        assertMessageValidity("4F:82:12:34").isEqualTo(OK);
+        assertMessageValidity("0F:82:00:00").isEqualTo(OK);
+        assertMessageValidity("40:9D:14:00").isEqualTo(OK);
+        assertMessageValidity("40:9D:10:00").isEqualTo(OK);
+        assertMessageValidity("0F:81:44:20").isEqualTo(OK);
+        assertMessageValidity("4F:81:13:10").isEqualTo(OK);
+        assertMessageValidity("4F:86:14:14").isEqualTo(OK);
+        assertMessageValidity("0F:86:15:24").isEqualTo(OK);
+
+        assertMessageValidity("4F:82:10").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:9D:14").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("0F:81:44").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("0F:86:15").isEqualTo(ERROR_PARAMETER_SHORT);
+
+        assertMessageValidity("4F:82:10:10").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("4F:82:10:06").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:9D:14:04").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:9D:10:01").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("0F:81:44:02").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("4F:81:13:05").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("4F:86:10:14").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("0F:86:10:24").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_reportPhysicalAddress() {
+        assertMessageValidity("4F:84:10:00:04").isEqualTo(OK);
+        assertMessageValidity("0F:84:00:00:00").isEqualTo(OK);
+
+        assertMessageValidity("4F:84:10:00").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("0F:84:00").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:84:10:00:04").isEqualTo(ERROR_DESTINATION);
+        // Invalid Physical Address
+        assertMessageValidity("4F:84:10:10:04").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("0F:84:00:30:00").isEqualTo(ERROR_PARAMETER);
+        // Invalid Device Type
+        assertMessageValidity("4F:84:12:34:08").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_routingChange() {
+        assertMessageValidity("0F:80:10:00:40:00").isEqualTo(OK);
+        assertMessageValidity("4F:80:12:00:50:00").isEqualTo(OK);
+
+        assertMessageValidity("0F:80:10:00:40").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:80:12:00:50:00").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("0F:80:10:01:40:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("4F:80:12:00:50:50").isEqualTo(ERROR_PARAMETER);
+    }
+
     private IntegerSubject assertMessageValidity(String message) {
         return assertThat(mHdmiCecMessageValidator.isValid(HdmiUtils.buildMessage(message)));
     }
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 080b52b..b1998f5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
@@ -36,6 +36,7 @@
 import org.junit.runners.JUnit4;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -313,6 +314,7 @@
         int powerStatus = HdmiControlManager.POWER_STATUS_ON;
         String osdName = "Test Device";
         int vendorId = 1234;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
 
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress,
@@ -325,6 +327,8 @@
                         Constants.ADDR_BROADCAST, osdName));
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildDeviceVendorIdCommand(logicalAddress, vendorId));
+        mHdmiCecNetwork.handleCecMessage(HdmiCecMessageBuilder.buildCecVersion(logicalAddress,
+                Constants.ADDR_BROADCAST, cecVersion));
 
         assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
 
@@ -335,6 +339,7 @@
         assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName);
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
     }
 
     @Test
@@ -374,16 +379,18 @@
 
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
-                        Constants.ADDR_BROADCAST, powerStatus));
+                        Constants.ADDR_TV, powerStatus));
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
-                        Constants.ADDR_BROADCAST, updatedPowerStatus));
+                        Constants.ADDR_TV, updatedPowerStatus));
 
         assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
 
         HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
@@ -428,6 +435,8 @@
         assertThat(cecDeviceInfo.getVendorId()).isEqualTo(updatedVendorId);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
@@ -446,4 +455,91 @@
                 HdmiControlManager.DEVICE_EVENT_ADD_DEVICE,
                 HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
     }
+
+    @Test
+    public void cecDevices_tracking_reportPowerStatus_broadcast_infersCec2() {
+        int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int powerStatus = HdmiControlManager.POWER_STATUS_ON;
+        mHdmiCecNetwork.handleCecMessage(
+                HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress,
+                        Constants.ADDR_BROADCAST, powerStatus));
+
+        assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+
+        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+        assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+        assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(
+                Constants.INVALID_PHYSICAL_ADDRESS);
+        assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED);
+        assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID);
+        assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(
+                HdmiUtils.getDefaultDeviceName(logicalAddress));
+        assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
+                HdmiControlManager.HDMI_CEC_VERSION_2_0);
+    }
+
+    @Test
+    public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() {
+        int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
+        mHdmiCecNetwork.handleCecMessage(
+                HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
+                        cecVersion));
+
+        assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+
+        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+        assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
+    }
+
+    @Test
+    public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec20() {
+        int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
+        mHdmiCecNetwork.handleCecMessage(
+                HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
+                        cecVersion));
+
+        assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+
+        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+        assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
+    }
+
+    @Test
+    public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() {
+        int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
+        mHdmiCecNetwork.handleCecMessage(
+                HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
+                        cecVersion, Collections.emptyList(),
+                        Constants.RC_PROFILE_SOURCE, Collections.emptyList(),
+                        Collections.emptyList()));
+
+        assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+
+        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+        assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
+    }
+
+    @Test
+    public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec20() {
+        int logicalAddress = Constants.ADDR_PLAYBACK_1;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
+        mHdmiCecNetwork.handleCecMessage(
+                HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
+                        cecVersion, Collections.emptyList(),
+                        Constants.RC_PROFILE_SOURCE, Collections.emptyList(),
+                        Collections.emptyList()));
+
+        assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1);
+
+        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
+        assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
+        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
+    }
 }
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/hdmi/OWNERS b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS
new file mode 100644
index 0000000..c3c47ed
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/hdmi/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/input/OWNERS b/services/tests/servicestests/src/com/android/server/input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/integrity/OWNERS b/services/tests/servicestests/src/com/android/server/integrity/OWNERS
new file mode 100644
index 0000000..653d1c9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/integrity/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/job/OWNERS b/services/tests/servicestests/src/com/android/server/job/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/job/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/lights/OWNERS b/services/tests/servicestests/src/com/android/server/lights/OWNERS
new file mode 100644
index 0000000..cb46a80
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/lights/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/lights/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
index 00cef8f..dc81237 100644
--- a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
@@ -15,17 +15,16 @@
  */
 package com.android.server.location.timezone;
 
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
 import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_DISABLED;
 import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
 import static com.android.server.location.timezone.TestSupport.USER2_CONFIG_GEO_DETECTION_ENABLED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.createPermanentFailureEvent;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.createUncertainEvent;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -37,9 +36,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.platform.test.annotations.Presubmit;
+import android.service.timezone.TimeZoneProviderSuggestion;
 import android.util.IndentingPrintWriter;
 
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
 import com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
 import com.android.server.timezonedetector.ConfigurationInternal;
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
@@ -61,14 +60,14 @@
 
     private static final long ARBITRARY_TIME_MILLIS = 12345L;
 
-    private static final LocationTimeZoneEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
-            createLocationTimeZoneEvent(EVENT_TYPE_SUCCESS, asList("Europe/London"));
-    private static final LocationTimeZoneEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
-            createLocationTimeZoneEvent(EVENT_TYPE_SUCCESS, asList("Europe/Paris"));
-    private static final LocationTimeZoneEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
-            createLocationTimeZoneEvent(EVENT_TYPE_UNCERTAIN, null);
-    private static final LocationTimeZoneEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
-            createLocationTimeZoneEvent(EVENT_TYPE_PERMANENT_FAILURE, null);
+    private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
+            createSuggestionEvent(asList("Europe/London"));
+    private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
+            createSuggestionEvent(asList("Europe/Paris"));
+    private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
+            createUncertainEvent();
+    private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
+            createPermanentFailureEvent("Test");
 
     private TestThreadingDomain mTestThreadingDomain;
     private TestCallback mTestCallback;
@@ -89,7 +88,7 @@
     }
 
     @Test
-    public void initialState_enabled() {
+    public void initialState_started() {
         ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
                 mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
         TestEnvironment testEnvironment = new TestEnvironment(
@@ -98,16 +97,16 @@
                 .plus(testEnvironment.getProviderInitializationTimeoutFuzz());
 
         // Initialize. After initialization the providers must be initialized and one should be
-        // enabled.
+        // started.
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -120,14 +119,14 @@
                 mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
 
         // Initialize. After initialization the providers must be initialized but neither should be
-        // enabled.
+        // started.
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -143,8 +142,8 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -152,11 +151,11 @@
         mTestThreadingDomain.executeNext();
 
         // The primary should have reported uncertainty, which should trigger the controller to
-        // start the uncertainty timeout and enable the secondary.
+        // start the uncertainty timeout and start the secondary.
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
@@ -167,9 +166,9 @@
         // Now both initialization timeouts should have triggered. The uncertainty timeout should
         // still not be triggered.
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
@@ -178,9 +177,9 @@
         mTestThreadingDomain.executeNext();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -196,21 +195,21 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -225,8 +224,8 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -234,22 +233,22 @@
         mTestThreadingDomain.executeNext();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made and the secondary to be shut down.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -264,8 +263,8 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -273,23 +272,23 @@
         mTestThreadingDomain.executeNext();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -304,42 +303,42 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // A second, identical event should not cause another suggestion.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // And a third, different event should cause another suggestion.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -354,8 +353,8 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -363,46 +362,46 @@
         mTestThreadingDomain.executeNext();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // A second, identical event should not cause another suggestion.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // And a third, different event should cause another suggestion.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -417,60 +416,60 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made and ensure the primary is considered initialized.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event being received from the primary provider. This should not
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
-        // started and the secondary should be enabled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made, cancel the uncertainty timeout and ensure the secondary is
         // considered initialized.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event being received from the secondary provider. This should not
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
-        // started. Both providers are now enabled, with no initialization timeout set.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // started. Both providers are now started, with no initialization timeout set.
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
@@ -479,9 +478,9 @@
         mTestThreadingDomain.executeNext();
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -497,46 +496,46 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
-        // timeout should be started and the secondary should be enabled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // timeout should be started and the secondary should be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // And a success event from the primary provider should cause the controller to make another
         // suggestion, the uncertainty timeout should be cancelled and the secondary should be
-        // disabled again.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // stopped again.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -550,8 +549,8 @@
         // Initialize and check initial state.
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -559,16 +558,16 @@
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is disabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -583,8 +582,8 @@
         // Initialize and check initial state.
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -592,20 +591,20 @@
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a success event being received from the primary provider.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is disabled.
@@ -614,8 +613,8 @@
         // of the time zone.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -631,35 +630,35 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate the primary provider suggesting a time zone.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         // Receiving a "success" provider event should cause a suggestion to be made synchronously,
         // and also clear the scheduled uncertainty suggestion.
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate the user change (but geo detection still enabled).
         testEnvironment.simulateConfigChange(USER2_CONFIG_GEO_DETECTION_ENABLED);
 
-        // We expect the provider to end up in PROVIDER_STATE_ENABLED, but it should have been
-        // disabled when the user changed.
+        // We expect the provider to end up in PROVIDER_STATE_STARTED_INITIALIZING, but it should
+        // have been stopped when the user changed.
         int[] expectedStateTransitions =
-                { PROVIDER_STATE_DISABLED, PROVIDER_STATE_ENABLED_INITIALIZING };
+                { PROVIDER_STATE_STOPPED, PROVIDER_STATE_STARTED_INITIALIZING };
         mTestPrimaryLocationTimeZoneProvider.assertStateChangesAndCommit(expectedStateTransitions);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
 
@@ -674,51 +673,51 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a failure location event being received from the primary provider. This should
-        // cause the secondary to be enabled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // cause the secondary to be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate uncertainty from the secondary.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // And a success event from the secondary provider should cause the controller to make
         // another suggestion, the uncertainty timeout should be cancelled.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate uncertainty from the secondary.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
     }
@@ -734,19 +733,19 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate a failure location event being received from the primary provider. This should
-        // cause the secondary to be enabled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // cause the secondary to be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -754,7 +753,7 @@
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
@@ -763,7 +762,7 @@
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
     }
@@ -779,52 +778,52 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
-        // Simulate an uncertain event from the primary. This will enable the secondary, which will
+        // Simulate an uncertain event from the primary. This will start the secondary, which will
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate failure event from the secondary. This should just affect the secondary's state.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // And a success event from the primary provider should cause the controller to make
         // a suggestion, the uncertainty timeout should be cancelled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertSuggestionMadeAndCommit(
-                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+                USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
-        // Simulate uncertainty from the primary. The secondary cannot be enabled.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // Simulate uncertainty from the primary. The secondary cannot be started.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -841,30 +840,30 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
-        // Simulate an uncertain event from the primary. This will enable the secondary, which will
+        // Simulate an uncertain event from the primary. This will start the secondary, which will
         // give this test the opportunity to simulate its failure. Then it will be possible to
         // demonstrate controller behavior with only the primary working.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
 
         // Simulate failure event from the secondary. This should just affect the secondary's state.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -872,17 +871,17 @@
         // Now signal a config change so that geo detection is disabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
-        mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+        mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is enabled. Only the primary can be
-        // enabled.
+        // started.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -899,23 +898,23 @@
         controllerImpl.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
-        mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
-        // Simulate a failure event from the primary. This will enable the secondary.
-        mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        // Simulate a failure event from the primary. This will start the secondary.
+        mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
-                PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestCallback.assertNoSuggestionMade();
         assertFalse(controllerImpl.isUncertaintyTimeoutSet());
 
         // Simulate failure event from the secondary.
-        mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+        mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -932,18 +931,14 @@
                 controller.getUncertaintyTimeoutDelayMillis());
     }
 
-    private static LocationTimeZoneEvent createLocationTimeZoneEvent(
-            int eventType, @Nullable List<String> timeZoneIds) {
-        LocationTimeZoneEvent.Builder builder = new LocationTimeZoneEvent.Builder()
-                .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
-                .setEventType(eventType);
-        if (timeZoneIds != null) {
-            builder.setTimeZoneIds(timeZoneIds);
-        }
-        return builder.build();
+    private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) {
+        return TimeZoneProviderEvent.createSuggestionEvent(
+                new TimeZoneProviderSuggestion.Builder()
+                        .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+                        .setTimeZoneIds(timeZoneIds)
+                        .build());
     }
 
-
     private static class TestEnvironment extends LocationTimeZoneProviderController.Environment {
 
         // These timeouts are set deliberately so that:
@@ -1048,12 +1043,12 @@
         }
 
         @Override
-        void onEnable(Duration initializationTimeout) {
+        void onStartUpdates(Duration initializationTimeout) {
             // Nothing needed for tests.
         }
 
         @Override
-        void onDisable() {
+        void onStopUpdates() {
             // Nothing needed for tests.
         }
 
@@ -1078,9 +1073,9 @@
             mTestProviderState.commitLatest();
         }
 
-        void assertIsDisabledAndCommit() {
-            // A disabled provider doesn't hold config.
-            assertStateEnumAndConfig(PROVIDER_STATE_DISABLED, null /* config */);
+        void assertIsStoppedAndCommit() {
+            // A stopped provider doesn't hold config.
+            assertStateEnumAndConfig(PROVIDER_STATE_STOPPED, null /* config */);
             mTestProviderState.commitLatest();
         }
 
@@ -1107,7 +1102,7 @@
 
             // If and only if the controller is initializing, the initialization timeout must be
             // set.
-            assertEquals(expectedStateEnum == PROVIDER_STATE_ENABLED_INITIALIZING,
+            assertEquals(expectedStateEnum == PROVIDER_STATE_STARTED_INITIALIZING,
                     isInitializationTimeoutSet());
 
             assertConfig(expectedConfig);
@@ -1123,8 +1118,8 @@
             assertEquals(expectedTimeout, getInitializationTimeoutDelay());
         }
 
-        void simulateLocationTimeZoneEvent(@NonNull LocationTimeZoneEvent event) {
-            handleLocationTimeZoneEvent(event);
+        void simulateTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent event) {
+            handleTimeZoneProviderEvent(event);
         }
 
         /**
diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
index 5403a65..e4a3ebd 100644
--- a/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
@@ -15,9 +15,9 @@
  */
 package com.android.server.location.timezone;
 
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
 import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
 import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
 
 import static org.junit.Assert.assertEquals;
@@ -61,14 +61,14 @@
         provider.initialize(providerState -> mTestController.onProviderStateChange(providerState));
 
         ProviderState currentState = provider.getCurrentState();
-        assertEquals(PROVIDER_STATE_DISABLED, currentState.stateEnum);
+        assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
         assertNull(currentState.currentUserConfiguration);
         assertSame(provider, currentState.provider);
         mTestThreadingDomain.assertQueueEmpty();
     }
 
     @Test
-    public void enableSchedulesPermFailure() {
+    public void startSchedulesPermFailure() {
         String providerName = "primary";
         NullLocationTimeZoneProvider provider =
                 new NullLocationTimeZoneProvider(mTestThreadingDomain, providerName);
@@ -77,13 +77,14 @@
         ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
         Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
         Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
-        provider.enable(config, arbitraryInitializationTimeout, arbitraryInitializationTimeoutFuzz);
+        provider.startUpdates(config, arbitraryInitializationTimeout,
+                arbitraryInitializationTimeoutFuzz);
 
         // The NullProvider should enter the enabled state, but have schedule an immediate runnable
         // to switch to perm failure.
         ProviderState currentState = provider.getCurrentState();
         assertSame(provider, currentState.provider);
-        assertEquals(PROVIDER_STATE_ENABLED_INITIALIZING, currentState.stateEnum);
+        assertEquals(PROVIDER_STATE_STARTED_INITIALIZING, currentState.stateEnum);
         assertEquals(config, currentState.currentUserConfiguration);
         mTestThreadingDomain.assertNextQueueItemIsImmediate();
         // Entering enabled() does not trigger an onProviderStateChanged() as it is requested by the
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 2205694..25dbc6b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.locksettings;
 
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
@@ -277,6 +280,94 @@
         verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
     }
 
+    @Test
+    public void testSetPin_nonCompliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
+
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
+    public void testSetPin_compliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
+
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4231" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPin("4231"),
+                LockscreenCredential.createPin("1234"),
+                mUserId);
+    }
+
+    @Test
+    public void testSetPattern_nonCompliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_HIGH);
+
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
+    public void testSetPattern_compliantWithComplexity() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
+        when(mLockPatternUtils.getRequestedPasswordComplexity(mUserId))
+                .thenReturn(PASSWORD_COMPLEXITY_LOW);
+
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPattern(stringToPattern("4321")),
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId);
+    }
+
     private List<LockPatternView.Cell> stringToPattern(String str) {
         return LockPatternUtils.byteArrayToPattern(str.getBytes());
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/OWNERS b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS
new file mode 100644
index 0000000..0a8dc8c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/locksettings/OWNERS
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/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
index 7767a28..9d300a6 100644
--- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
@@ -20,11 +20,11 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import android.net.InetAddresses;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
 import android.util.ArrayMap;
@@ -79,8 +79,8 @@
 
         StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
         staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1);
-        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1));
-        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2));
+        staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1));
+        staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2));
 
         ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2");
 
diff --git a/services/tests/servicestests/src/com/android/server/net/OWNERS b/services/tests/servicestests/src/com/android/server/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/om/OWNERS b/services/tests/servicestests/src/com/android/server/om/OWNERS
new file mode 100644
index 0000000..afb98d4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/om/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 20f9b70..e3e7768 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -28,7 +28,6 @@
 import android.content.om.OverlayInfo;
 import android.text.TextUtils;
 import android.util.TypedXmlPullParser;
-import android.util.TypedXmlSerializer;
 import android.util.Xml;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -40,7 +39,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.StringReader;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -287,7 +286,7 @@
     public void testPersistEmpty() throws Exception {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mSettings.persist(os);
-        String xml = new String(os.toByteArray(), "utf-8");
+        ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
 
         assertEquals(1, countXmlTags(xml, "overlays"));
         assertEquals(0, countXmlTags(xml, "item"));
@@ -300,7 +299,7 @@
 
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mSettings.persist(os);
-        final String xml = new String(os.toByteArray(), "utf-8");
+        ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
 
         assertEquals(1, countXmlTags(xml, "overlays"));
         assertEquals(2, countXmlTags(xml, "item"));
@@ -319,7 +318,7 @@
 
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mSettings.persist(os);
-        String xml = new String(os.toByteArray(), "utf-8");
+        ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
 
         assertEquals(1, countXmlTags(xml, "overlays"));
         assertEquals(2, countXmlTags(xml, "item"));
@@ -338,7 +337,7 @@
 
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mSettings.persist(os);
-        String xml = new String(os.toByteArray(), "utf-8");
+        ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
 
         assertEquals(1, countXmlAttributesWhere(xml, "item", "isEnabled", "true"));
     }
@@ -391,8 +390,7 @@
 
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mSettings.persist(os);
-        String xml = new String(os.toByteArray(), "utf-8");
-        ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
+        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
         OverlayManagerSettings newSettings = new OverlayManagerSettings();
         newSettings.restore(is);
 
@@ -403,10 +401,10 @@
         assertEquals(OVERLAY_B1, b);
     }
 
-    private int countXmlTags(String xml, String tagToLookFor) throws Exception {
+    private int countXmlTags(InputStream in, String tagToLookFor) throws Exception {
+        in.reset();
         int count = 0;
-        TypedXmlPullParser parser = Xml.newFastPullParser();
-        parser.setInput(new StringReader(xml));
+        TypedXmlPullParser parser = Xml.resolvePullParser(in);
         int event = parser.getEventType();
         while (event != XmlPullParser.END_DOCUMENT) {
             if (event == XmlPullParser.START_TAG && tagToLookFor.equals(parser.getName())) {
@@ -417,11 +415,11 @@
         return count;
     }
 
-    private int countXmlAttributesWhere(String xml, String tag, String attr, String value)
+    private int countXmlAttributesWhere(InputStream in, String tag, String attr, String value)
             throws Exception {
+        in.reset();
         int count = 0;
-        TypedXmlPullParser parser = Xml.newFastPullParser();
-        parser.setInput(new StringReader(xml));
+        TypedXmlPullParser parser = Xml.resolvePullParser(in);
         int event = parser.getEventType();
         while (event != XmlPullParser.END_DOCUMENT) {
             if (event == XmlPullParser.START_TAG && tag.equals(parser.getName())) {
diff --git a/services/tests/servicestests/src/com/android/server/people/OWNERS b/services/tests/servicestests/src/com/android/server/people/OWNERS
new file mode 100644
index 0000000..3198a5e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/OWNERS
@@ -0,0 +1 @@
+include /services/people/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index eec7d12..205548c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -52,6 +52,7 @@
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.utils.WatchableTester;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -884,6 +885,104 @@
                 contains(hasProviderAppId, queriesProviderAppId));
     }
 
+    @Test
+    public void testOnChangeReport() throws Exception {
+        final AppsFilter appsFilter =
+                new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+                        mMockExecutor);
+        final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
+        watcher.register();
+        simulateAddBasicAndroid(appsFilter);
+        watcher.verifyChangeReported("addBasic");
+        appsFilter.onSystemReady();
+        watcher.verifyChangeReported("systemReady");
+
+        final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
+        final int seesNothingAppId = Process.FIRST_APPLICATION_UID;
+        final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
+        final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
+
+        PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
+        watcher.verifyChangeReported("addPackage");
+        PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                seesNothingAppId);
+        watcher.verifyChangeReported("addPackage");
+        PackageSetting hasProvider = simulateAddPackage(appsFilter,
+                pkgWithProvider("com.some.other.package", "com.some.authority"), hasProviderAppId);
+        watcher.verifyChangeReported("addPackage");
+        PackageSetting queriesProvider = simulateAddPackage(appsFilter,
+                pkgQueriesProvider("com.yet.some.other.package", "com.some.authority"),
+                queriesProviderAppId);
+        watcher.verifyChangeReported("addPackage");
+
+        final SparseArray<int[]> systemFilter =
+                appsFilter.getVisibilityAllowList(system, USER_ARRAY, mExisting);
+        assertThat(toList(systemFilter.get(SYSTEM_USER)),
+                contains(seesNothingAppId, hasProviderAppId, queriesProviderAppId));
+        watcher.verifyNoChangeReported("get");
+
+        final SparseArray<int[]> seesNothingFilter =
+                appsFilter.getVisibilityAllowList(seesNothing, USER_ARRAY, mExisting);
+        assertThat(toList(seesNothingFilter.get(SYSTEM_USER)),
+                contains(seesNothingAppId));
+        assertThat(toList(seesNothingFilter.get(SECONDARY_USER)),
+                contains(seesNothingAppId));
+        watcher.verifyNoChangeReported("get");
+
+        final SparseArray<int[]> hasProviderFilter =
+                appsFilter.getVisibilityAllowList(hasProvider, USER_ARRAY, mExisting);
+        assertThat(toList(hasProviderFilter.get(SYSTEM_USER)),
+                contains(hasProviderAppId, queriesProviderAppId));
+        watcher.verifyNoChangeReported("get");
+
+        SparseArray<int[]> queriesProviderFilter =
+                appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
+        assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
+                contains(queriesProviderAppId));
+        watcher.verifyNoChangeReported("get");
+
+        // provider read
+        appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
+        watcher.verifyChangeReported("grantImplicitAccess");
+
+        // ensure implicit access is included in the filter
+        queriesProviderFilter =
+                appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
+        assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
+                contains(hasProviderAppId, queriesProviderAppId));
+        watcher.verifyNoChangeReported("get");
+
+        // remove a package
+        appsFilter.removePackage(seesNothing);
+        watcher.verifyChangeReported("removePackage");
+    }
+
+    @Test
+    public void testOnChangeReportedFilter() throws Exception {
+        final AppsFilter appsFilter =
+                new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+                        mMockExecutor);
+        simulateAddBasicAndroid(appsFilter);
+        appsFilter.onSystemReady();
+        final WatchableTester watcher = new WatchableTester(appsFilter, "onChange filter");
+        watcher.register();
+
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_APPID);
+        PackageSetting instrumentation = simulateAddPackage(appsFilter,
+                pkgWithInstrumentation("com.some.other.package", "com.some.package"),
+                DUMMY_CALLING_APPID);
+        watcher.verifyChangeReported("addPackage");
+
+        assertFalse(
+                appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+                        SYSTEM_USER));
+        assertFalse(
+                appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, target, instrumentation,
+                        SYSTEM_USER));
+        watcher.verifyNoChangeReported("shouldFilterApplication");
+    }
+
     private List<Integer> toList(int[] array) {
         ArrayList<Integer> ret = new ArrayList<>(array.length);
         for (int i = 0; i < array.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
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/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 4b90a5c..282047a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -62,6 +62,7 @@
 import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.permission.LegacyPermissionDataProvider;
+import com.android.server.utils.WatchableTester;
 
 import com.google.common.truth.Truth;
 
@@ -178,6 +179,12 @@
         PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
         assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
+
+        // Verify that the snapshot passes the same test
+        Settings snapshot = settings.snapshot();
+        ps = snapshot.getPackageLPr(PACKAGE_NAME_2);
+        assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
+        assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
     }
 
     private static PersistableBundle createPersistableBundle(String packageName, long longVal,
@@ -197,21 +204,41 @@
         final Context context = InstrumentationRegistry.getTargetContext();
         final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
                 lock);
+        final WatchableTester watcher =
+                new WatchableTester(settingsUnderTest, "noSuspendingPackage");
+        watcher.register();
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+        watcher.verifyChangeReported("put package 1");
+        // Collect a snapshot at the midway point (package 2 has not been added)
+        final Settings snapshot = settingsUnderTest.snapshot();
+        watcher.verifyNoChangeReported("snapshot");
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
+        watcher.verifyChangeReported("put package 2");
         settingsUnderTest.readPackageRestrictionsLPr(0);
 
-        final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
-        final PackageUserState packageUserState1 = ps1.readUserState(0);
+        PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
+        PackageUserState packageUserState1 = ps1.readUserState(0);
         assertThat(packageUserState1.suspended, is(true));
         assertThat(packageUserState1.suspendParams.size(), is(1));
         assertThat(packageUserState1.suspendParams.keyAt(0), is("android"));
         assertThat(packageUserState1.suspendParams.valueAt(0), is(nullValue()));
 
-        final PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
-        final PackageUserState packageUserState2 = ps2.readUserState(0);
+        // Verify that the snapshot returns the same answers
+        ps1 = snapshot.mPackages.get(PACKAGE_NAME_1);
+        packageUserState1 = ps1.readUserState(0);
+        assertThat(packageUserState1.suspended, is(true));
+        assertThat(packageUserState1.suspendParams.size(), is(1));
+        assertThat(packageUserState1.suspendParams.keyAt(0), is("android"));
+        assertThat(packageUserState1.suspendParams.valueAt(0), is(nullValue()));
+
+        PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
+        PackageUserState packageUserState2 = ps2.readUserState(0);
         assertThat(packageUserState2.suspended, is(false));
         assertThat(packageUserState2.suspendParams, is(nullValue()));
+
+        // Verify that the snapshot returns different answers
+        ps2 = snapshot.mPackages.get(PACKAGE_NAME_2);
+        assertTrue(ps2 == null);
     }
 
     @Test
@@ -221,15 +248,23 @@
         final Context context = InstrumentationRegistry.getTargetContext();
         final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
                 lock);
+        final WatchableTester watcher =
+                new WatchableTester(settingsUnderTest, "noSuspendParamsMap");
+        watcher.register();
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+        watcher.verifyChangeReported("put package 1");
         settingsUnderTest.readPackageRestrictionsLPr(0);
+        watcher.verifyChangeReported("readPackageRestrictions");
 
         final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
+        watcher.verifyNoChangeReported("get package 1");
         final PackageUserState packageUserState1 = ps1.readUserState(0);
+        watcher.verifyNoChangeReported("readUserState");
         assertThat(packageUserState1.suspended, is(true));
         assertThat(packageUserState1.suspendParams.size(), is(1));
         assertThat(packageUserState1.suspendParams.keyAt(0), is(PACKAGE_NAME_3));
         final PackageUserState.SuspendParams params = packageUserState1.suspendParams.valueAt(0);
+        watcher.verifyNoChangeReported("fetch user state");
         assertThat(params, is(notNullValue()));
         assertThat(params.appExtras.size(), is(1));
         assertThat(params.appExtras.getString("app_extra_string"), is("value"));
@@ -249,6 +284,8 @@
         final Context context = InstrumentationRegistry.getTargetContext();
         final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
                 new Object());
+        final WatchableTester watcher = new WatchableTester(settingsUnderTest, "suspendInfo");
+        watcher.register();
         final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
         final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
         final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
@@ -283,33 +320,46 @@
         ps1.addOrUpdateSuspension("suspendingPackage2", dialogInfo2, appExtras2, launcherExtras2,
                 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
+        watcher.verifyChangeReported("put package 1");
 
         ps2.addOrUpdateSuspension("suspendingPackage3", null, appExtras1, null, 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
+        watcher.verifyChangeReported("put package 2");
 
         ps3.removeSuspension("irrelevant", 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
+        watcher.verifyChangeReported("put package 3");
 
         settingsUnderTest.writePackageRestrictionsLPr(0);
+        watcher.verifyChangeReported("writePackageRestrictions");
 
         settingsUnderTest.mPackages.clear();
+        watcher.verifyChangeReported("clear packages");
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+        watcher.verifyChangeReported("put package 1");
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
+        watcher.verifyChangeReported("put package 2");
         settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
+        watcher.verifyChangeReported("put package 3");
         // now read and verify
         settingsUnderTest.readPackageRestrictionsLPr(0);
+        watcher.verifyChangeReported("readPackageRestrictions");
         final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
                 .readUserState(0);
+        watcher.verifyNoChangeReported("package get 1");
         assertThat(readPus1.suspended, is(true));
         assertThat(readPus1.suspendParams.size(), is(2));
+        watcher.verifyNoChangeReported("read package param");
 
         assertThat(readPus1.suspendParams.keyAt(0), is("suspendingPackage1"));
         final PackageUserState.SuspendParams params11 = readPus1.suspendParams.valueAt(0);
+        watcher.verifyNoChangeReported("read package param");
         assertThat(params11, is(notNullValue()));
         assertThat(params11.dialogInfo, is(dialogInfo1));
         assertThat(BaseBundle.kindofEquals(params11.appExtras, appExtras1), is(true));
         assertThat(BaseBundle.kindofEquals(params11.launcherExtras, launcherExtras1),
                 is(true));
+        watcher.verifyNoChangeReported("read package param");
 
         assertThat(readPus1.suspendParams.keyAt(1), is("suspendingPackage2"));
         final PackageUserState.SuspendParams params12 = readPus1.suspendParams.valueAt(1);
@@ -318,6 +368,7 @@
         assertThat(BaseBundle.kindofEquals(params12.appExtras, appExtras2), is(true));
         assertThat(BaseBundle.kindofEquals(params12.launcherExtras, launcherExtras2),
                 is(true));
+        watcher.verifyNoChangeReported("read package param");
 
         final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
                 .readUserState(0);
@@ -329,11 +380,13 @@
         assertThat(params21.dialogInfo, is(nullValue()));
         assertThat(BaseBundle.kindofEquals(params21.appExtras, appExtras1), is(true));
         assertThat(params21.launcherExtras, is(nullValue()));
+        watcher.verifyNoChangeReported("read package param");
 
         final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
                 .readUserState(0);
         assertThat(readPus3.suspended, is(false));
         assertThat(readPus3.suspendParams, is(nullValue()));
+        watcher.verifyNoChangeReported("package get 3");
     }
 
     @Test
@@ -467,14 +520,23 @@
         final Object lock = new Object();
         Settings settings = new Settings(context.getFilesDir(),
                 mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
+        final WatchableTester watcher = new WatchableTester(settings, "testEnableDisable");
+        watcher.register();
         assertThat(settings.readLPw(createFakeUsers()), is(true));
+        watcher.verifyChangeReported("readLPw");
 
         // Enable/Disable a package
         PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1);
+        watcher.verifyNoChangeReported("getPackageLPr");
+        assertThat(ps.getEnabled(0), is(not(COMPONENT_ENABLED_STATE_DISABLED)));
+        assertThat(ps.getEnabled(1), is(not(COMPONENT_ENABLED_STATE_ENABLED)));
         ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
+        watcher.verifyChangeReported("setEnabled DISABLED");
         ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null);
+        watcher.verifyChangeReported("setEnabled ENABLED");
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED));
         assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_ENABLED));
+        watcher.verifyNoChangeReported("getEnabled");
 
         // Enable/Disable a component
         ArraySet<String> components = new ArraySet<String>();
@@ -1152,7 +1214,8 @@
 
     private void verifyKeySetMetaData(Settings settings)
             throws ReflectiveOperationException, IllegalAccessException {
-        ArrayMap<String, PackageSetting> packages = settings.mPackages;
+        ArrayMap<String, PackageSetting> packages =
+                settings.mPackages.untrackedMap();
         KeySetManagerService ksms = settings.mKeySetManagerService;
 
         /* verify keyset and public key ref counts */
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
index 583c3d4..7546c43 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -25,8 +25,16 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Xml;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
 
     private static Bundle sIntentExtras = makeBundle(
@@ -99,7 +107,10 @@
             "x2", "value{?}"
     );
 
+    @Test
     public void testPersistingWeirdCharacters() {
+        Assume.assumeFalse(Xml.ENABLE_BINARY_DEFAULT);
+
         final Intent intent = new Intent(Intent.ACTION_MAIN)
                 .putExtras(sIntentExtras);
 
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..79935c2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.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 java.util.function.Predicate;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+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
+        StagingManager.StagedSession session1 = createSession(111, "com.foo", 1);
+        StagingManager.StagedSession 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 StagingManager.StagedSession 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");
+
+        StagingManager.StagedSession stagedSession = spy(session.mStagedSession);
+        doReturn(packageName).when(stagedSession).getPackageName();
+        doAnswer(invocation -> {
+            Predicate<StagingManager.StagedSession> filter = invocation.getArgument(0);
+            return filter.test(stagedSession);
+        }).when(stagedSession).sessionContains(any());
+        return stagedSession;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
new file mode 100644
index 0000000..4f6441f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.permission;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class LegacyPermissionManagerServiceTest {
+    private static final int SYSTEM_UID = 1000;
+    private static final int SYSTEM_PID = 1234;
+    private static final int APP_UID = Process.FIRST_APPLICATION_UID;
+    private static final int APP_PID = 5678;
+
+    private LegacyPermissionManagerService mLegacyPermissionManagerService;
+    private Context mContext;
+
+    @Mock
+    private LegacyPermissionManagerService.Injector mInjector;
+
+    @Mock
+    private AppOpsManager mAppOpsManager;
+
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = InstrumentationRegistry.getContext();
+        mLegacyPermissionManagerService = new LegacyPermissionManagerService(mContext, mInjector);
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_callingAppUidMismatch_throwsException() {
+        // An application should only be able to query its own device identifier access, querying
+        // of any other UIDs should result in a SecurityException.
+        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
+
+        assertThrows(SecurityException.class,
+                () -> mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                        mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null,
+                        APP_PID, SYSTEM_UID));
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_callingAppPidMismatch_throwsException() {
+        // Similar to above an app can only specify its own pid, a mismatch should result in a
+        // SecurityException.
+        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
+
+        assertThrows(SecurityException.class,
+                () -> mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                        mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null,
+                        SYSTEM_PID, APP_UID));
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_callingAppIdWithoutAccess_returnsDenied() {
+        // An application can query its own device identifier access; this test verifies that all
+        // checks can run through completion and return denied.
+        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
+
+        int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
+                APP_UID);
+
+        assertEquals(PackageManager.PERMISSION_DENIED, result);
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_systemUid_returnsGranted() {
+        // The system UID should always have access to device identifiers.
+        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
+        int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, SYSTEM_PID,
+                SYSTEM_UID);
+
+        assertEquals(PackageManager.PERMISSION_GRANTED, result);
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_hasPrivilegedPermission_returnsGranted() {
+        // Apps with the READ_PRIVILEGED_PHONE_STATE permission should have access to device
+        // identifiers.
+        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
+        when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+                APP_PID, APP_UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
+
+        int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
+                APP_UID);
+
+        assertEquals(PackageManager.PERMISSION_GRANTED, result);
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_hasAppOp_returnsGranted() {
+        // Apps that have been granted the READ_DEVICE_IDENTIFIERS appop should have access to
+        // device identifiers.
+        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
+        when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS),
+                eq(APP_UID), eq(mContext.getPackageName()), any(), any())).thenReturn(
+                AppOpsManager.MODE_ALLOWED);
+
+        int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
+                APP_UID);
+
+        assertEquals(PackageManager.PERMISSION_GRANTED, result);
+    }
+
+    @Test
+    public void checkDeviceIdentifierAccess_hasDpmAccess_returnsGranted() {
+        // Apps that pass a DevicePolicyManager device / profile owner check should have access to
+        // device identifiers.
+        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
+        when(mDevicePolicyManager.hasDeviceIdentifierAccess(mContext.getPackageName(), APP_PID,
+                APP_UID)).thenReturn(true);
+
+        int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess(
+                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
+                APP_UID);
+
+        assertEquals(PackageManager.PERMISSION_GRANTED, result);
+    }
+
+    private void setupCheckDeviceIdentifierAccessTest(int callingPid, int callingUid) {
+        when(mInjector.getCallingPid()).thenReturn(callingPid);
+        when(mInjector.getCallingUid()).thenReturn(callingUid);
+
+        // Configure the checkDeviceIdentifierAccess tests to fail all access checks, then each test
+        // can individually set the access check to pass for verification.
+        when(mInjector.checkPermission(anyString(), anyInt(), anyInt())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        when(mAppOpsManager.noteOpNoThrow(anyString(), anyInt(), anyString(), any(),
+                any())).thenReturn(AppOpsManager.MODE_DEFAULT);
+        when(mInjector.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOpsManager);
+
+        when(mDevicePolicyManager.hasDeviceIdentifierAccess(anyString(), anyInt(),
+                anyInt())).thenReturn(false);
+        when(mInjector.getSystemService(eq(Context.DEVICE_POLICY_SERVICE))).thenReturn(
+                mDevicePolicyManager);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
deleted file mode 100644
index 6cea928..0000000
--- a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm.permission;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertThrows;
-
-import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Process;
-import android.permission.PermissionManagerInternal;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.LocalServices;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class PermissionManagerServiceTest {
-    private static final String TAG = "PermissionManagerServiceTag";
-
-    private static final int SYSTEM_UID = 1000;
-    private static final int SYSTEM_PID = 1234;
-    private static final int APP_UID = Process.FIRST_APPLICATION_UID;
-    private static final int APP_PID = 5678;
-
-    private PermissionManagerService mPermissionManagerService;
-    private Context mContext;
-
-    @Mock
-    private PermissionManagerService.Injector mInjector;
-
-    @Mock
-    private AppOpsManager mAppOpsManager;
-
-    @Mock
-    private DevicePolicyManager mDevicePolicyManager;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = InstrumentationRegistry.getContext();
-        mPermissionManagerService = new PermissionManagerService(mContext, mInjector);
-    }
-
-    @After
-    public void tearDown() {
-        // The LocalServices added by the constructor of the PermissionManagerService can either be
-        // removed here after each test when tests are run serially, or to run them in parallel
-        // the Injector can provide methods to add these that can be ignored by the mock.
-        LocalServices.removeServiceForTest(PermissionManagerServiceInternal.class);
-        LocalServices.removeServiceForTest(PermissionManagerInternal.class);
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_callingAppUidMismatch_throwsException() {
-        // An application should only be able to query its own device identifier access, querying
-        // of any other UIDs should result in a SecurityException.
-        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
-
-        assertThrows(SecurityException.class,
-                () -> mPermissionManagerService.checkDeviceIdentifierAccess(
-                        mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null,
-                        APP_PID, SYSTEM_UID));
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_callingAppPidMismatch_throwsException() {
-        // Similar to above an app can only specify its own pid, a mismatch should result in a
-        // SecurityException.
-        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
-
-        assertThrows(SecurityException.class,
-                () -> mPermissionManagerService.checkDeviceIdentifierAccess(
-                        mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null,
-                        SYSTEM_PID, APP_UID));
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_callingAppIdWithoutAccess_returnsDenied() {
-        // An application can query its own device identifier access; this test verifies that all
-        // checks can run through completion and return denied.
-        setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID);
-
-        int result = mPermissionManagerService.checkDeviceIdentifierAccess(
-                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
-                APP_UID);
-
-        assertEquals(PackageManager.PERMISSION_DENIED, result);
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_systemUid_returnsGranted() {
-        // The system UID should always have access to device identifiers.
-        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
-        int result = mPermissionManagerService.checkDeviceIdentifierAccess(
-                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, SYSTEM_PID,
-                SYSTEM_UID);
-
-        assertEquals(PackageManager.PERMISSION_GRANTED, result);
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_hasPrivilegedPermission_returnsGranted() {
-        // Apps with the READ_PRIVILEGED_PHONE_STATE permission should have access to device
-        // identifiers.
-        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
-        when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
-                APP_PID, APP_UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
-
-        int result = mPermissionManagerService.checkDeviceIdentifierAccess(
-                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
-                APP_UID);
-
-        assertEquals(PackageManager.PERMISSION_GRANTED, result);
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_hasAppOp_returnsGranted() {
-        // Apps that have been granted the READ_DEVICE_IDENTIFIERS appop should have access to
-        // device identifiers.
-        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
-        when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS),
-                eq(APP_UID), eq(mContext.getPackageName()), any(), any())).thenReturn(
-                AppOpsManager.MODE_ALLOWED);
-
-        int result = mPermissionManagerService.checkDeviceIdentifierAccess(
-                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
-                APP_UID);
-
-        assertEquals(PackageManager.PERMISSION_GRANTED, result);
-    }
-
-    @Test
-    public void checkDeviceIdentifierAccess_hasDpmAccess_returnsGranted() {
-        // Apps that pass a DevicePolicyManager device / profile owner check should have access to
-        // device identifiers.
-        setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID);
-        when(mDevicePolicyManager.hasDeviceIdentifierAccess(mContext.getPackageName(), APP_PID,
-                APP_UID)).thenReturn(true);
-
-        int result = mPermissionManagerService.checkDeviceIdentifierAccess(
-                mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID,
-                APP_UID);
-
-        assertEquals(PackageManager.PERMISSION_GRANTED, result);
-    }
-
-    private void setupCheckDeviceIdentifierAccessTest(int callingPid, int callingUid) {
-        when(mInjector.getCallingPid()).thenReturn(callingPid);
-        when(mInjector.getCallingUid()).thenReturn(callingUid);
-
-        // Configure the checkDeviceIdentifierAccess tests to fail all access checks, then each test
-        // can individually set the access check to pass for verification.
-        when(mInjector.checkPermission(anyString(), anyInt(), anyInt())).thenReturn(
-                PackageManager.PERMISSION_DENIED);
-
-        when(mAppOpsManager.noteOpNoThrow(anyString(), anyInt(), anyString(), any(),
-                any())).thenReturn(AppOpsManager.MODE_DEFAULT);
-        when(mInjector.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOpsManager);
-
-        when(mDevicePolicyManager.hasDeviceIdentifierAccess(anyString(), anyInt(),
-                anyInt())).thenReturn(false);
-        when(mInjector.getSystemService(eq(Context.DEVICE_POLICY_SERVICE))).thenReturn(
-                mDevicePolicyManager);
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/policy/OWNERS b/services/tests/servicestests/src/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/power/OWNERS b/services/tests/servicestests/src/com/android/server/power/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/powerstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
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/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
index 035a2f1..b07b8fa 100644
--- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
@@ -33,6 +34,7 @@
 
 import android.content.Context;
 import android.content.IntentSender;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.IPowerManager;
 import android.os.IRecoverySystemProgressListener;
@@ -67,6 +69,9 @@
     private FileWriter mUncryptUpdateFileWriter;
     private LockSettingsInternal mLockSettingsInternal;
 
+    private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package";
+    private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package";
+
     @Before
     public void setup() {
         mContext = mock(Context.class);
@@ -209,65 +214,99 @@
 
     @Test(expected = SecurityException.class)
     public void requestLskf_protected() {
-        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.RECOVERY), any());
-        mRecoverySystemService.requestLskf("test", null);
-    }
-
-
-    @Test
-    public void requestLskf_nullToken_failure() {
-        assertThat(mRecoverySystemService.requestLskf(null, null), is(false));
+        when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+        mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null);
     }
 
     @Test
     public void requestLskf_success() throws Exception {
         IntentSender intentSender = mock(IntentSender.class);
-        assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
         mRecoverySystemService.onPreparedForReboot(true);
         verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
     }
 
     @Test
-    public void requestLskf_subsequentRequestClearsPrepared() throws Exception {
+    public void requestLskf_subsequentRequestNotClearPrepared() throws Exception {
         IntentSender intentSender = mock(IntentSender.class);
-        assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
         mRecoverySystemService.onPreparedForReboot(true);
         verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
 
-        assertThat(mRecoverySystemService.requestLskf("test2", null), is(true));
-        assertThat(mRecoverySystemService.rebootWithLskf("test", null), is(false));
-        assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(false));
-
-        mRecoverySystemService.onPreparedForReboot(true);
-        assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(true));
-        verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true),
+                is(true));
         verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean());
     }
 
-
     @Test
     public void requestLskf_requestedButNotPrepared() throws Exception {
         IntentSender intentSender = mock(IntentSender.class);
-        assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
         verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any());
     }
 
+    @Test
+    public void isLskfCaptured_requestedButNotPrepared() throws Exception {
+        IntentSender intentSender = mock(IntentSender.class);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
+        assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(false));
+    }
+
+    @Test
+    public void isLskfCaptured_Prepared() throws Exception {
+        IntentSender intentSender = mock(IntentSender.class);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
+        mRecoverySystemService.onPreparedForReboot(true);
+        verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
+        assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(true));
+    }
+
     @Test(expected = SecurityException.class)
     public void clearLskf_protected() {
-        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.RECOVERY), any());
-        mRecoverySystemService.clearLskf();
+        when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+        mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME);
     }
 
     @Test
     public void clearLskf_requestedThenCleared() throws Exception {
         IntentSender intentSender = mock(IntentSender.class);
-        assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
         mRecoverySystemService.onPreparedForReboot(true);
         verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
 
-        assertThat(mRecoverySystemService.clearLskf(), is(true));
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+        verify(mLockSettingsInternal).clearRebootEscrow();
+    }
+
+    @Test
+    public void clearLskf_callerNotRequested_Success() throws Exception {
+        IntentSender intentSender = mock(IntentSender.class);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+        verify(mLockSettingsInternal, never()).clearRebootEscrow();
+    }
+
+    @Test
+    public void clearLskf_multiClient_BothClientsClear() throws Exception {
+        IntentSender intentSender = mock(IntentSender.class);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+                is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, intentSender),
+                is(true));
+
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+        verify(mLockSettingsInternal, never()).clearRebootEscrow();
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
         verify(mLockSettingsInternal).clearRebootEscrow();
     }
 
@@ -279,27 +318,84 @@
 
     @Test(expected = SecurityException.class)
     public void rebootWithLskf_protected() {
-        doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
-                eq(android.Manifest.permission.RECOVERY), any());
-        mRecoverySystemService.rebootWithLskf("test1", null);
+        when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+        mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true);
     }
 
     @Test
     public void rebootWithLskf_Success() throws Exception {
-        assertThat(mRecoverySystemService.requestLskf("test", null), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
         mRecoverySystemService.onPreparedForReboot(true);
-        assertThat(mRecoverySystemService.rebootWithLskf("test", "ab-update"), is(true));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
+                is(true));
         verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
     }
 
     @Test
     public void rebootWithLskf_withoutPrepare_Failure() throws Exception {
-        assertThat(mRecoverySystemService.rebootWithLskf("test1", null), is(false));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+                is(false));
     }
 
     @Test
-    public void rebootWithLskf_withNullUpdateToken_Failure() throws Exception {
-        assertThat(mRecoverySystemService.rebootWithLskf(null, null), is(false));
+    public void rebootWithLskf_withNullCallerId_Failure() throws Exception {
+        assertThat(mRecoverySystemService.rebootWithLskf(null, null, true), is(false));
         verifyNoMoreInteractions(mIPowerManager);
     }
+
+    @Test
+    public void rebootWithLskf_multiClient_ClientASuccess() throws Exception {
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+        mRecoverySystemService.onPreparedForReboot(true);
+
+        // Client B's clear won't affect client A's preparation.
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
+                is(true));
+        verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+    }
+
+
+    @Test
+    public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception {
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+        mRecoverySystemService.onPreparedForReboot(true);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+                is(false));
+        verifyNoMoreInteractions(mIPowerManager);
+
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+        assertThat(
+                mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
+                is(true));
+        verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+    }
+
+    @Test
+    public void rebootWithLskf_multiClient_BothClientsClear_Failure() throws Exception {
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+        mRecoverySystemService.onPreparedForReboot(true);
+        assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+
+        // Client A clears
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+        assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+                is(false));
+        verifyNoMoreInteractions(mIPowerManager);
+
+        // Client B clears
+        assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+        verify(mLockSettingsInternal).clearRebootEscrow();
+        assertThat(
+                mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
+                is(false));
+        verifyNoMoreInteractions(mIPowerManager);
+    }
+
+    // TODO(xunchang) add more multi client tests
 }
diff --git a/services/tests/servicestests/src/com/android/server/rollback/OWNERS b/services/tests/servicestests/src/com/android/server/rollback/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/stats/OWNERS b/services/tests/servicestests/src/com/android/server/stats/OWNERS
new file mode 100644
index 0000000..ee865b1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/stats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/stats/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/storage/OWNERS b/services/tests/servicestests/src/com/android/server/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 4a44005..5276ac4 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
@@ -174,6 +175,36 @@
         mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion);
     }
 
+    @Test(expected = SecurityException.class)
+    public void testSuggestGnssTime_withoutPermission() {
+        doThrow(new SecurityException("Mock"))
+                .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+        GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
+
+        try {
+            mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion);
+            fail();
+        } finally {
+            verify(mMockContext).enforceCallingOrSelfPermission(
+                    eq(android.Manifest.permission.SET_TIME), anyString());
+        }
+    }
+
+    @Test
+    public void testSuggestGnssTime() throws Exception {
+        doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+
+        GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
+        mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion);
+        mTestHandler.assertTotalMessagesEnqueued(1);
+
+        verify(mMockContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.SET_TIME), anyString());
+
+        mTestHandler.waitForMessagesToBeProcessed();
+        mStubbedTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion);
+    }
+
     @Test
     public void testDump() {
         when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
@@ -219,12 +250,18 @@
         return new NetworkTimeSuggestion(timeValue);
     }
 
+    private static GnssTimeSuggestion createGnssTimeSuggestion() {
+        TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
+        return new GnssTimeSuggestion(timeValue);
+    }
+
     private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
 
         // Call tracking.
         private TelephonyTimeSuggestion mLastTelephonySuggestion;
         private ManualTimeSuggestion mLastManualSuggestion;
         private NetworkTimeSuggestion mLastNetworkSuggestion;
+        private GnssTimeSuggestion mLastGnssSuggestion;
         private boolean mHandleAutoTimeDetectionChangedCalled;
         private boolean mDumpCalled;
 
@@ -245,6 +282,11 @@
         }
 
         @Override
+        public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
+            mLastGnssSuggestion = timeSuggestion;
+        }
+
+        @Override
         public void handleAutoTimeConfigChanged() {
             mHandleAutoTimeDetectionChangedCalled = true;
         }
@@ -258,6 +300,7 @@
             mLastTelephonySuggestion = null;
             mLastManualSuggestion = null;
             mLastNetworkSuggestion = null;
+            mLastGnssSuggestion = null;
             mHandleAutoTimeDetectionChangedCalled = false;
             mDumpCalled = false;
         }
@@ -274,6 +317,10 @@
             assertEquals(expectedSuggestion, mLastNetworkSuggestion);
         }
 
+        void verifySuggestGnssTimeCalled(GnssTimeSuggestion expectedSuggestion) {
+            assertEquals(expectedSuggestion, mLastGnssSuggestion);
+        }
+
         void verifyHandleAutoTimeDetectionChangedCalled() {
             assertTrue(mHandleAutoTimeDetectionChangedCalled);
         }
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 21396fd..b1adb0b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.timedetector;
 
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS;
 import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
 import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
 
@@ -25,6 +26,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.app.timedetector.GnssTimeSuggestion;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.NetworkTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
@@ -569,7 +571,53 @@
     }
 
     @Test
-    public void highPrioritySuggestionsShouldBeatLowerPrioritySuggestions() {
+    public void testSuggestGnssTime_autoTimeEnabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_GNSS)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        GnssTimeSuggestion timeSuggestion =
+                mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+        mScript.simulateTimePassing();
+
+        long expectedSystemClockMillis =
+                mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+        mScript.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+    }
+
+    @Test
+    public void testSuggestGnssTime_autoTimeDisabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_GNSS)
+                .pokeAutoTimeDetectionEnabled(false);
+
+        GnssTimeSuggestion timeSuggestion =
+                mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+        mScript.simulateTimePassing()
+                .simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void gnssTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_GNSS)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+        GnssTimeSuggestion timeSuggestion = mScript
+                .generateGnssTimeSuggestion(suggestedTime);
+
+        mScript.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestGnssSuggestion(null);
+    }
+
+    @Test
+    public void highPrioritySuggestionsBeatLowerPrioritySuggestions_telephonyNetworkOrigins() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(true)
                 .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
@@ -672,22 +720,130 @@
     }
 
     @Test
+    public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkGnssOrigins() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_GNSS);
+
+        // Three obviously different times that could not be mistaken for each other.
+        Instant gnssTime1 = ARBITRARY_TEST_TIME;
+        Instant gnssTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+        Instant networkTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
+        // A small increment used to simulate the passage of time, but not enough to interfere with
+        // macro-level time changes associated with suggestion age.
+        final long smallTimeIncrementMillis = 101;
+
+        // A gnss suggestion is made. It should be used because there is no network suggestion.
+        GnssTimeSuggestion gnssTimeSuggestion1 =
+                mScript.generateGnssTimeSuggestion(gnssTime1);
+        mScript.simulateTimePassing(smallTimeIncrementMillis)
+                .simulateGnssTimeSuggestion(gnssTimeSuggestion1)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        mScript.calculateTimeInMillisForNow(gnssTimeSuggestion1.getUtcTime()));
+
+        // Check internal state.
+        mScript.assertLatestNetworkSuggestion(null)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion1);
+        assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
+        assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion());
+
+        // Simulate a little time passing.
+        mScript.simulateTimePassing(smallTimeIncrementMillis)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+
+        // Now a network suggestion is made. Network suggestions are prioritized over gnss
+        // suggestions so it should "win".
+        NetworkTimeSuggestion networkTimeSuggestion =
+                mScript.generateNetworkTimeSuggestion(networkTime);
+        mScript.simulateTimePassing(smallTimeIncrementMillis)
+                .simulateNetworkTimeSuggestion(networkTimeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime()));
+
+        // Check internal state.
+        mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion1);
+        assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
+        assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+
+        // Simulate some significant time passing: half the time allowed before a time signal
+        // becomes "too old to use".
+        mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+
+        // Now another gnss suggestion is made. Network suggestions are prioritized over
+        // gnss suggestions so the latest network suggestion should still "win".
+        GnssTimeSuggestion gnssTimeSuggestion2 =
+                mScript.generateGnssTimeSuggestion(gnssTime2);
+        mScript.simulateTimePassing(smallTimeIncrementMillis)
+                .simulateGnssTimeSuggestion(gnssTimeSuggestion2)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+
+        // Check internal state.
+        mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+        assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+        assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+
+        // Simulate some significant time passing: half the time allowed before a time signal
+        // becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
+        // be used but networkTimeSuggestion2 is not.
+        mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+
+        // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
+        // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
+        // to re-run the detection logic. This may change in future but until then we rely on a
+        // steady stream of suggestions to re-evaluate.
+        mScript.verifySystemClockWasNotSetAndResetCallTracking();
+
+        // Check internal state.
+        mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+        assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+        assertNull(
+                "Network suggestion should be expired:",
+                mScript.peekLatestValidNetworkSuggestion());
+
+        // Toggle auto-time off and on to force the detection logic to run.
+        mScript.simulateAutoTimeDetectionToggle()
+                .simulateTimePassing(smallTimeIncrementMillis)
+                .simulateAutoTimeDetectionToggle();
+
+        // Verify the latest gnss time now wins.
+        mScript.verifySystemClockWasSetAndResetCallTracking(
+                mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUtcTime()));
+
+        // Check internal state.
+        mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+        assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+        assertNull(
+                "Network suggestion should still be expired:",
+                mScript.peekLatestValidNetworkSuggestion());
+    }
+
+    @Test
     public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(true)
-                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
 
         Instant networkTime = ARBITRARY_TEST_TIME;
-        Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+        Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+        Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
 
         NetworkTimeSuggestion networkTimeSuggestion =
                 mScript.generateNetworkTimeSuggestion(networkTime);
+        GnssTimeSuggestion gnssTimeSuggestion =
+                mScript.generateGnssTimeSuggestion(gnssTime);
         TelephonyTimeSuggestion telephonyTimeSuggestion =
                 mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
 
         mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+                .simulateGnssTimeSuggestion(gnssTimeSuggestion)
                 .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
                 .assertLatestNetworkSuggestion(networkTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion)
                 .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
                 .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
     }
@@ -696,20 +852,25 @@
     public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(true)
-                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
 
         Instant networkTime = ARBITRARY_TEST_TIME;
         Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+        Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
 
         NetworkTimeSuggestion networkTimeSuggestion =
                 mScript.generateNetworkTimeSuggestion(networkTime);
         TelephonyTimeSuggestion telephonyTimeSuggestion =
                 mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+        GnssTimeSuggestion gnssTimeSuggestion =
+                mScript.generateGnssTimeSuggestion(gnssTime);
 
         mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
                 .simulateNetworkTimeSuggestion(networkTimeSuggestion)
+                .simulateGnssTimeSuggestion(gnssTimeSuggestion)
                 .assertLatestNetworkSuggestion(networkTimeSuggestion)
                 .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+                .assertLatestGnssSuggestion(gnssTimeSuggestion)
                 .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
     }
 
@@ -728,7 +889,37 @@
     }
 
     @Test
-    public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() {
+    public void whenHigherPrioritySuggestionsAreNotAvailable_fallbacksToNext() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
+
+        GnssTimeSuggestion timeSuggestion =
+                mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+        mScript.simulateGnssTimeSuggestion(timeSuggestion)
+                .assertLatestGnssSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
+    }
+
+    @Test
+    public void suggestionsFromTelephonyOriginNotInPriorityList_areIgnored() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_NETWORK);
+
+        int slotIndex = ARBITRARY_SLOT_INDEX;
+        Instant testTime = ARBITRARY_TEST_TIME;
+        TelephonyTimeSuggestion timeSuggestion =
+                mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+
+        mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+                .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(true)
                 .pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
@@ -742,6 +933,20 @@
     }
 
     @Test
+    public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
+
+        GnssTimeSuggestion timeSuggestion = mScript.generateGnssTimeSuggestion(
+                ARBITRARY_TEST_TIME);
+
+        mScript.simulateGnssTimeSuggestion(timeSuggestion)
+                .assertLatestGnssSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
     public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(false)
@@ -945,6 +1150,11 @@
             return this;
         }
 
+        Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) {
+            mTimeDetectorStrategy.suggestGnssTime(timeSuggestion);
+            return this;
+        }
+
         Script simulateAutoTimeDetectionToggle() {
             mFakeCallback.simulateAutoTimeZoneDetectionToggle();
             mTimeDetectorStrategy.handleAutoTimeConfigChanged();
@@ -995,6 +1205,14 @@
         }
 
         /**
+         * White box test info: Asserts the latest gnss suggestion is as expected.
+         */
+        Script assertLatestGnssSuggestion(GnssTimeSuggestion expected) {
+            assertEquals(expected, mTimeDetectorStrategy.getLatestGnssSuggestion());
+            return this;
+        }
+
+        /**
          * White box test info: Returns the telephony suggestion that would be used, if any, given
          * the current elapsed real time clock and regardless of origin prioritization.
          */
@@ -1011,6 +1229,14 @@
         }
 
         /**
+         * White box test info: Returns the gnss suggestion that would be used, if any, given the
+         * current elapsed real time clock and regardless of origin prioritization.
+         */
+        GnssTimeSuggestion peekLatestValidGnssSuggestion() {
+            return mTimeDetectorStrategy.findLatestValidGnssSuggestionForTests();
+        }
+
+        /**
          * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
          * reference time.
          */
@@ -1057,6 +1283,18 @@
         }
 
         /**
+         * Generates a GnssTimeSuggestion using the current elapsed realtime clock for the
+         * reference time.
+         */
+        GnssTimeSuggestion generateGnssTimeSuggestion(Instant suggestedTime) {
+            TimestampedValue<Long> utcTime =
+                    new TimestampedValue<>(
+                            mFakeCallback.peekElapsedRealtimeMillis(),
+                            suggestedTime.toEpochMilli());
+            return new GnssTimeSuggestion(utcTime);
+        }
+
+        /**
          * Calculates what the supplied time would be when adjusted for the movement of the fake
          * elapsed realtime clock.
          */
diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/tv/OWNERS b/services/tests/servicestests/src/com/android/server/tv/OWNERS
new file mode 100644
index 0000000..305027c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/tv/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/tv/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/uri/OWNERS b/services/tests/servicestests/src/com/android/server/uri/OWNERS
new file mode 100644
index 0000000..ca5d5f98
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/uri/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/uri/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/usage/OWNERS b/services/tests/servicestests/src/com/android/server/usage/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index fa8e367..ac93ff6 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -44,6 +44,7 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -89,6 +90,11 @@
                 mContextSpy, new Handler(mTestLooper.getLooper()));
     }
 
+    @After
+    public void tearDown() throws Exception {
+        InputManager.clearInstance();
+    }
+
     @Test
     public void onInputDeviceAdded_withSettingsDisabled_ignoresNewDevice() throws Exception {
         when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
@@ -286,6 +292,6 @@
 
     private InputDevice createInputDevice(int id, boolean hasVibrator) {
         return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
-                null, hasVibrator, false, false);
+                null, hasVibrator, false, false, false /* hasSensor */);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/OWNERS b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS
new file mode 100644
index 0000000..cc63ceb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/vibrator/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
index fa171fd..1a4ac07 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -28,6 +28,7 @@
 import android.content.ContextWrapper;
 import android.os.Handler;
 import android.os.IExternalVibratorService;
+import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
@@ -40,7 +41,9 @@
 
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
+import com.android.server.LocalServices;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -62,6 +65,7 @@
 
     // TODO(b/131311651): replace with a FakeVibrator instead.
     @Mock private Vibrator mVibratorMock;
+    @Mock private PowerManagerInternal mPowerManagerInternalMock;
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
@@ -77,11 +81,19 @@
         when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
         when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock);
 
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
+        LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
+
         mVibrationSettings = new VibrationSettings(
                 mContextSpy, new Handler(mTestLooper.getLooper()));
         mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings);
     }
 
+    @After
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
+    }
+
     @Test
     public void testGetExternalVibrationScale() {
         when(mVibratorMock.getDefaultHapticFeedbackIntensity())
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 04c2cb3..ecdb8bc 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -20,7 +20,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -32,6 +34,9 @@
 import android.content.ContextWrapper;
 import android.media.AudioManager;
 import android.os.Handler;
+import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
@@ -44,6 +49,7 @@
 
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
+import com.android.server.LocalServices;
 
 import org.junit.After;
 import org.junit.Before;
@@ -62,17 +68,24 @@
 @Presubmit
 public class VibrationSettingsTest {
 
+    private static final int UID = 1;
+    private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
+    private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
+            .setBatterySaverEnabled(true).build();
+
     @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
     // TODO(b/131311651): replace with a FakeVibrator instead.
     @Mock private Vibrator mVibratorMock;
     @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
+    @Mock private PowerManagerInternal mPowerManagerInternalMock;
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
     private AudioManager mAudioManager;
     private VibrationSettings mVibrationSettings;
+    private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
 
     @Before
     public void setUp() throws Exception {
@@ -83,10 +96,17 @@
         when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
         when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock);
         when(mVibratorMock.hasVibrator()).thenReturn(true);
+        doAnswer(invocation -> {
+            mRegisteredPowerModeListener = invocation.getArgument(0);
+            return null;
+        }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
+
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
+        LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
 
         mAudioManager = mContextSpy.getSystemService(AudioManager.class);
-        mVibrationSettings = new VibrationSettings(
-                mContextSpy, new Handler(mTestLooper.getLooper()));
+        mVibrationSettings = new VibrationSettings(mContextSpy,
+                new Handler(mTestLooper.getLooper()));
 
         setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0);
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
@@ -96,7 +116,7 @@
 
     @After
     public void tearDown() throws Exception {
-        FakeSettingsProvider.clearSettingsProvider();
+        LocalServices.removeServiceForTest(PowerManagerInternal.class);
     }
 
     @Test
@@ -118,6 +138,17 @@
     }
 
     @Test
+    public void addListener_lowPowerModeChangeTriggerListener() {
+        mVibrationSettings.addListener(mListenerMock);
+
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+        mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
+        mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change.
+
+        verify(mListenerMock, times(2)).onChange();
+    }
+
+    @Test
     public void removeListener_noMoreCallbacksToListener() {
         mVibrationSettings.addListener(mListenerMock);
 
@@ -132,56 +163,103 @@
     }
 
     @Test
-    public void shouldVibrateForRingtones_withVibrateWhenRinging_onlyIgnoreSettingsForSilentMode() {
-        setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
-
-        setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingtone());
-
-        setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
-
-        setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
-
-        setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
+    public void shouldVibrateForRingerMode_withoutRingtoneUsage_returnsTrue() {
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
+                VibrationAttributes.USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
+                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
     }
 
     @Test
-    public void shouldVibrateForRingtones_withApplyRampingRinger_onlyIgnoreSettingsForSilentMode() {
+    public void shouldVibrateForRingerMode_withVibrateWhenRinging_ignoreSettingsForSilentMode() {
+        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
+        setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
+
+        setRingerMode(AudioManager.RINGER_MODE_SILENT);
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+
+        setRingerMode(AudioManager.RINGER_MODE_MAX);
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+
+        setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+
+        setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+    }
+
+    @Test
+    public void shouldVibrateForRingerMode_withApplyRampingRinger_ignoreSettingsForSilentMode() {
+        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
         setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
 
         setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingtone());
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
     }
 
     @Test
-    public void shouldVibrateForRingtones_withAllSettingsOff_onlyVibratesForVibrateMode() {
+    public void shouldVibrateForRingerMode_withAllSettingsOff_onlyVibratesForVibrateMode() {
+        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
         setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
 
         setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingtone());
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingtone());
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertFalse(mVibrationSettings.shouldVibrateForRingtone());
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertFalse(mVibrationSettings.shouldVibrateForRingtone());
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+    }
+
+    @Test
+    public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() throws RemoteException {
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
+                VibrationAttributes.USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE));
+    }
+
+    @Test
+    public void shouldVibrateForPowerMode_withLowPowerAndAllowedUsage_returnTrue() {
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
+                VibrationAttributes.USAGE_RINGTONE));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
+                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+    }
+
+    @Test
+    public void shouldVibrateForPowerMode_withRestrictedUsage_returnsFalseWhileInLowPowerMode() {
+        mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
+
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
+                VibrationAttributes.USAGE_NOTIFICATION));
+
+        mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+
+        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
+        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(
+                VibrationAttributes.USAGE_NOTIFICATION));
     }
 
     @Test
@@ -299,4 +377,5 @@
         mAudioManager.setRingerModeInternal(ringerMode);
         assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
     }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
index 1f163bd..815aa8e 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.vibrator;
 
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -38,7 +37,6 @@
 import android.os.IBinder;
 import android.os.IVibratorStateListener;
 import android.os.VibrationEffect;
-import android.os.Vibrator;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
 
@@ -100,7 +98,7 @@
     public void createController_initializesNativeWrapper() {
         int vibratorId = 13;
         VibratorController controller = createController(vibratorId);
-        assertEquals(vibratorId, controller.getVibratorId());
+        assertEquals(vibratorId, controller.getVibratorInfo().getId());
         verify(mNativeWrapperMock).init(eq(vibratorId), notNull());
     }
 
@@ -132,59 +130,6 @@
     }
 
     @Test
-    public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() {
-        when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null);
-        assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN},
-                createController().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}));
-    }
-
-    @Test
-    public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() {
-        int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK};
-
-        when(mNativeWrapperMock.getSupportedEffects())
-                .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
-        assertArrayEquals(
-                new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
-                        Vibrator.VIBRATION_EFFECT_SUPPORT_NO},
-                createController().areEffectsSupported(effects));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() {
-        assertArrayEquals(new boolean[]{false, false},
-                createController().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_TICK
-                }));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() {
-        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
-        when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null);
-
-        assertArrayEquals(new boolean[]{false, false},
-                createController().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
-                }));
-    }
-
-    @Test
-    public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() {
-        mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
-        when(mNativeWrapperMock.getSupportedPrimitives())
-                .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
-
-        assertArrayEquals(new boolean[]{true, false},
-                createController().arePrimitivesSupported(new int[]{
-                        VibrationEffect.Composition.PRIMITIVE_CLICK,
-                        VibrationEffect.Composition.PRIMITIVE_QUICK_RISE
-                }));
-    }
-
-    @Test
     public void setExternalControl_withCapability_enablesExternalControl() {
         mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
         VibratorController controller = createController();
diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS
new file mode 100644
index 0000000..8ff0f74
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wallpaper/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/wallpaper/OWNERS
diff --git a/services/tests/servicestests/test-apps/JobTestApp/OWNERS b/services/tests/servicestests/test-apps/JobTestApp/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/services/tests/servicestests/test-apps/JobTestApp/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/OWNERS b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParsingTestManifests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/OWNERS b/services/tests/uiservicestests/src/com/android/server/OWNERS
new file mode 100644
index 0000000..05944c0
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file UiModeManagerServiceTest.java = file:/packages/SystemUI/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index 824c05e..18ca09b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -127,6 +127,6 @@
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
                 "action",
                 PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED)).build();
+                    PendingIntent.FLAG_IMMUTABLE)).build();
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
index a9a3b2b..ac9a77b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
@@ -58,10 +58,8 @@
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
         final Notification.Builder builder = new Notification.Builder(getContext())
                 .setContentTitle("foo")
-                // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 .setFullScreenIntent(PendingIntent.getActivity(
-                        getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED),
+                        getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE),
                         true)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
 
@@ -79,10 +77,8 @@
         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
         final Notification.Builder builder = new Notification.Builder(getContext())
                 .setContentTitle("foo")
-                // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below
-                // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
                 .setFullScreenIntent(PendingIntent.getActivity(
-                        getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED),
+                        getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE),
                         true)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index c634706..be489c3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -357,13 +357,11 @@
     private ArrayList<Notification.Action> getSmartActions(String key, int index) {
         ArrayList<Notification.Action> actions = new ArrayList<>();
         for (int i = 0; i < index; i++) {
-            // TODO(b/174935955) Please replace FLAG_MUTABLE_UNAUDITED below
-            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
             PendingIntent intent = PendingIntent.getBroadcast(
                     getContext(),
                     index /*requestCode*/,
                     new Intent("ACTION_" + key),
-                    PendingIntent.FLAG_MUTABLE_UNAUDITED /*flags*/);
+                    PendingIntent.FLAG_IMMUTABLE /*flags*/);
             actions.add(new Notification.Action.Builder(null /*icon*/, key, intent).build());
         }
         return actions;
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 849477c..a18bce7 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -111,9 +111,9 @@
 import android.content.ComponentName;
 import android.content.ContentUris;
 import android.content.Context;
-import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IIntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -305,6 +305,8 @@
     @Mock
     StatusBarManagerInternal mStatusBar;
 
+    private NotificationManagerService.WorkerHandler mWorkerHandler;
+
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
         int countSystemChecks = 0;
@@ -482,14 +484,13 @@
 
         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
 
-        mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()),
-                mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager,
-                mListeners, mAssistants, mConditionProviders,
-                mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
-                mGroupHelper, mAm, mAtm, mAppUsageStats,
-                mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
-                mAppOpsManager, mUm, mHistoryManager, mStatsManager,
-                mock(TelephonyManager.class), mAmi, mToastRateLimiter);
+        mWorkerHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
+        mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
+                mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
+                mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm,
+                mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
+                mAppOpsManager, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class),
+                mAmi, mToastRateLimiter);
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
 
         mService.setAudioManager(mAudioManager);
@@ -575,6 +576,10 @@
 
         InstrumentationRegistry.getInstrumentation()
                 .getUiAutomation().dropShellPermissionIdentity();
+        // Remove scheduled messages that would be processed when the test is already done, and
+        // could cause issues, for example, messages that remove/cancel shown toasts (this causes
+        // problematic interactions with mocks when they're no longer working as expected).
+        mWorkerHandler.removeCallbacksAndMessages(null);
     }
 
     private void simulatePackageSuspendBroadcast(boolean suspend, String pkg,
@@ -790,10 +795,8 @@
                 .setName("bubblebot")
                 .build();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_MUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
@@ -4980,6 +4983,40 @@
     }
 
     @Test
+    public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground()
+            throws Exception {
+        final String testPackage = "testPackageName";
+        assertEquals(0, mService.mToastQueue.size());
+        mService.isSystemUid = false;
+        setToastRateIsWithinQuota(true);
+
+        // package is not suspended
+        when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+                .thenReturn(false);
+
+        setAppInForegroundForToasts(mUid, true);
+
+        Binder token1 = new Binder();
+        Binder token2 = new Binder();
+        ITransientNotification callback1 = mock(ITransientNotification.class);
+        ITransientNotification callback2 = mock(ITransientNotification.class);
+        INotificationManager nmService = (INotificationManager) mService.mService;
+
+        nmService.enqueueToast(testPackage, token1, callback1, 2000, 0);
+        nmService.enqueueToast(testPackage, token2, callback2, 2000, 0);
+
+        assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued.
+        verify(callback1, times(1)).show(any()); // First toast shown.
+
+        setAppInForegroundForToasts(mUid, false);
+
+        mService.cancelToastLocked(0); // Remove the first toast, and show next.
+
+        assertEquals(0, mService.mToastQueue.size()); // Both toasts processed.
+        verify(callback2, never()).show(any()); // Second toast was never shown.
+    }
+
+    @Test
     public void testAllowForegroundTextToasts() throws Exception {
         final String testPackage = "testPackageName";
         assertEquals(0, mService.mToastQueue.size());
@@ -7369,10 +7406,8 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_IMMUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
@@ -7402,10 +7437,8 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         ArrayList<Notification.Action> extraAction = new ArrayList<>();
         RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
-        // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                PendingIntent.FLAG_MUTABLE);
         Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
         Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                 inputIntent).addRemoteInput(remoteInput)
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/OWNERS b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/OWNERS b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS
new file mode 100644
index 0000000..3d0859f
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/slice/OWNERS
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 4ca5b9e..1ecf850 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -47,7 +47,6 @@
         "testables",
         "ub-uiautomator",
         "hamcrest-library",
-        "compatibility-device-util-axt",
     ],
 
     libs: [
diff --git a/services/tests/wmtests/OWNERS b/services/tests/wmtests/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/services/tests/wmtests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 99bd0d7..801a27d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -248,7 +248,7 @@
         int topPosition = taskDisplayArea.getRootTaskCount() - 1;
         // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
         // existing alwaysOnTop stack.
-        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 1));
+        assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
 
         final Task nonAlwaysOnTopStack = taskDisplayArea.createRootTask(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -256,7 +256,7 @@
         topPosition = taskDisplayArea.getRootTaskCount() - 1;
         // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
         // existing other non-alwaysOnTop stacks.
-        assertEquals(nonAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 3));
+        assertEquals(topPosition - 3, taskDisplayArea.getTaskIndexOf(nonAlwaysOnTopStack));
 
         anotherAlwaysOnTopStack.setAlwaysOnTop(false);
         taskDisplayArea.positionChildAt(POSITION_TOP, anotherAlwaysOnTopStack,
@@ -264,16 +264,16 @@
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
-        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 2));
+        assertEquals(topPosition - 2, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
 
         // Ensure always on top state changes properly when windowing mode changes.
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 2));
+        assertEquals(topPosition - 2, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 1));
+        assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
 
         final Task dreamStack = taskDisplayArea.createRootTask(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM, true /* onTop */);
@@ -282,7 +282,7 @@
         topPosition = taskDisplayArea.getRootTaskCount() - 1;
         // Ensure dream shows above all activities, including PiP
         assertEquals(dreamStack, taskDisplayArea.getTopRootTask());
-        assertEquals(pinnedStack, taskDisplayArea.getRootTaskAt(topPosition - 1));
+        assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(pinnedStack));
 
         final Task assistStack = taskDisplayArea.createRootTask(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
@@ -294,8 +294,8 @@
         // is false and on top of everything when true.
         final boolean isAssistantOnTop = mContext.getResources()
                 .getBoolean(com.android.internal.R.bool.config_assistantOnTopOfDream);
-        assertEquals(assistStack, taskDisplayArea.getRootTaskAt(
-                    isAssistantOnTop ? topPosition : topPosition - 4));
+        assertEquals(isAssistantOnTop ? topPosition : topPosition - 4,
+                taskDisplayArea.getTaskIndexOf(assistStack));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 2f34f70..95a1b61 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -75,7 +75,6 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
 
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
@@ -102,6 +101,7 @@
 import android.view.RemoteAnimationTarget;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.window.TaskSnapshot;
 
 import androidx.test.filters.MediumTest;
 
@@ -1051,7 +1051,7 @@
         final ActivityRecord nextTop = nextStack.getTopNonFinishingActivity();
         nextTop.setState(STOPPED, "test");
 
-        task.mPausingActivity = currentTop;
+        task.setPausingActivity(currentTop);
         currentTop.finishing = true;
         currentTop.setState(PAUSED, "test");
         currentTop.completeFinishing("completePauseLocked");
@@ -1211,7 +1211,7 @@
         focusedActivity.nowVisible = true;
         focusedActivity.mVisibleRequested = true;
         focusedActivity.setState(RESUMED, "test");
-        stack.mResumedActivity = focusedActivity;
+        stack.setResumedActivity(focusedActivity, "test");
 
         topActivity.completeFinishing("test");
 
@@ -1662,7 +1662,8 @@
                     any() /* requestedVisibility */, any() /* outFrame */,
                     any() /* outDisplayCutout */, any() /* outInputChannel */,
                     any() /* outInsetsState */, any() /* outActiveControls */);
-            TaskSnapshotSurface.create(mAtm.mWindowManager, activity, snapshot);
+            mAtm.mWindowManager.mStartingSurfaceController
+                    .createTaskSnapshotSurface(activity, snapshot);
         } catch (RemoteException ignored) {
         } finally {
             reset(session);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 8e3e668..8ea95ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -167,7 +167,7 @@
                 null /* task */);
 
         // Assert that stack is at the bottom.
-        assertEquals(0, mDefaultTaskDisplayArea.getIndexOf(primarySplitScreen));
+        assertEquals(0, mDefaultTaskDisplayArea.getTaskIndexOf(primarySplitScreen));
 
         // Ensure no longer in splitscreen.
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
@@ -748,10 +748,10 @@
         doReturn(false).when(fullscreenStack).isTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
-        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
         assertEquals(fullscreenStack, getRootTaskAbove(homeStack));
         mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
-        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
     }
 
     @Test
@@ -766,10 +766,10 @@
         doReturn(true).when(fullscreenStack).isTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
-        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
         assertEquals(fullscreenStack, getRootTaskAbove(homeStack));
         mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
-        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
     }
 
     @Test
@@ -784,10 +784,10 @@
         doReturn(false).when(fullscreenStack).isTranslucent(any());
 
         // Ensure we don't move the home stack if it is already on top
-        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
         assertNull(getRootTaskAbove(homeStack));
         mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
-        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
     }
 
     @Test
@@ -853,9 +853,9 @@
         doReturn(false).when(fullscreenStack2).isTranslucent(any());
 
         // Ensure we don't move the home stack behind itself
-        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
         mDefaultTaskDisplayArea.moveRootTaskBehindRootTask(homeStack, homeStack);
-        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
     }
 
     @Test
@@ -1014,7 +1014,7 @@
         final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task).build();
         firstActivity.setState(STOPPED, "testFinishDisabledPackageActivities");
         secondActivity.setState(RESUMED, "testFinishDisabledPackageActivities");
-        task.mResumedActivity = secondActivity;
+        task.setResumedActivity(secondActivity, "test");
 
         // Note the activities have non-null ActivityRecord.app, so it won't remove directly.
         mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process(
@@ -1140,8 +1140,8 @@
         final Task task = new TaskBuilder(mSupervisor).build();
         final ActivityRecord bottomActivity = new ActivityBuilder(mAtm).setTask(task).build();
         doReturn(true).when(bottomActivity).attachedToProcess();
-        task.mPausingActivity = null;
-        task.mResumedActivity = bottomActivity;
+        task.setPausingActivity(null);
+        task.setResumedActivity(bottomActivity, "test");
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
         topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ef2e889..cde866b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -422,7 +422,7 @@
         // verify that values are passed to the modifier. Values are passed thrice -- two for
         // setting initial state, another when task is created.
         verify(modifier, times(3)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options),
-                anyInt(), any(), any(), any());
+                any(), anyInt(), any(), any());
     }
 
     /**
@@ -512,11 +512,8 @@
     }
 
     private void assertNoTasks(DisplayContent display) {
-        display.forAllTaskDisplayAreas(taskDisplayArea -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                assertFalse(stack.hasChild());
-            }
+        display.forAllRootTasks(rootTask -> {
+            assertFalse(rootTask.hasChild());
         });
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 080f04ef..285d887 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -98,7 +98,7 @@
         doReturn(mockLifecycleManager).when(mAtm).getLifecycleManager();
         doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
 
-        mAtm.requestPictureInPictureMode(activity.token);
+        mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
         verify(mockLifecycleManager).scheduleTransaction(mClientTransactionCaptor.capture());
         final ClientTransaction transaction = mClientTransactionCaptor.getValue();
@@ -117,7 +117,7 @@
         doReturn(false).when(activity).inPinnedWindowingMode();
         doReturn(false).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
 
-        mAtm.requestPictureInPictureMode(activity.token);
+        mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
         // Check enter no transactions with enter pip requests are made.
         verify(lifecycleManager, times(0)).scheduleTransaction(any());
@@ -130,7 +130,7 @@
         ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager();
         doReturn(true).when(activity).inPinnedWindowingMode();
 
-        mAtm.requestPictureInPictureMode(activity.token);
+        mAtm.mActivityClientController.requestPictureInPictureMode(activity);
 
         // Check that no transactions with enter pip requests are made.
         verify(lifecycleManager, times(0)).scheduleTransaction(any());
@@ -219,7 +219,7 @@
         //mock other operations
         doReturn(true).when(record)
                 .checkEnterPictureInPictureState("enterPictureInPictureMode", false);
-        doReturn(false).when(mAtm).isInPictureInPictureMode(any());
+        doReturn(false).when(record).inPinnedWindowingMode();
         doReturn(false).when(mAtm).isKeyguardLocked();
 
         //to simulate NPE
@@ -247,7 +247,7 @@
         activity.finishing = true;
         activity.mVisibleRequested = false;
         activity.setVisible(false);
-        activity.getRootTask().mPausingActivity = activity;
+        activity.getTask().setPausingActivity(activity);
         homeActivity.setState(Task.ActivityState.PAUSED, "test");
 
         // Even the visibility states are invisible, the next activity should be resumed because
@@ -262,8 +262,8 @@
     public void testUpdateSleep() {
         doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
         mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
-        final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
-                .setTask(mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask()).build();
+        final Task rootHomeTask = mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
+        final ActivityRecord homeActivity = new ActivityBuilder(mAtm).setTask(rootHomeTask).build();
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
         topActivity.setState(Task.ActivityState.RESUMED, "test");
 
@@ -277,6 +277,9 @@
         // Sleep all displays.
         mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep());
         mAtm.updateSleepIfNeededLocked();
+        // Simulate holding sleep wake lock if it is acquired.
+        verify(mSupervisor.mGoingToSleepWakeLock).acquire();
+        doReturn(true).when(mSupervisor.mGoingToSleepWakeLock).isHeld();
 
         assertEquals(Task.ActivityState.PAUSING, topActivity.getState());
         assertTrue(mAtm.mInternal.isSleeping());
@@ -285,8 +288,17 @@
         // The top app should not change while sleeping.
         assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
 
+        // If all activities are stopped, the sleep wake lock must be released.
+        final Task topRootTask = topActivity.getRootTask();
+        doReturn(true).when(rootHomeTask).goToSleepIfPossible(anyBoolean());
+        doReturn(true).when(topRootTask).goToSleepIfPossible(anyBoolean());
+        topActivity.setState(Task.ActivityState.STOPPING, "test");
+        topActivity.activityStopped(null /* newIcicle */, null /* newPersistentState */,
+                null /* description */);
+        verify(mSupervisor.mGoingToSleepWakeLock).release();
+
         // Move the current top to back, the top app should update to the next activity.
-        topActivity.getRootTask().moveToBack("test", null /* self */);
+        topRootTask.moveToBack("test", null /* self */);
         assertEquals(homeActivity.app, mAtm.mInternal.getTopApp());
 
         // Wake all displays.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 8cad56a..295c50b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -20,7 +20,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
@@ -111,7 +111,7 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
         translucentOpening.setVisible(false);
-        mDisplayContent.prepareAppTransition(TRANSIT_CHANGE_WINDOWING_MODE);
+        mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
         mDisplayContent.mOpeningApps.add(behind);
         mDisplayContent.mOpeningApps.add(translucentOpening);
         assertEquals(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index f7beb74..3beb7f2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -199,7 +199,7 @@
         mHost.addChild(child, 0);
 
         final float alpha = 0.8f;
-        mDimmer.dimBelow(mTransaction, child, alpha);
+        mDimmer.dimBelow(mTransaction, child, alpha, 0);
         SurfaceControl dimLayer = getDimLayer();
 
         assertNotNull("Dimmer should have created a surface", dimLayer);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
index 1198ee2..5597be9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
 import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
@@ -117,7 +118,7 @@
     }
 
     @Test
-    public void testCreateTaskDisplayArea() {
+    public void testCreateTaskDisplayArea_topBelowRoot() {
         final String newTdaName = "testTda";
         final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
         final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea(
@@ -142,6 +143,30 @@
     }
 
     @Test
+    public void testCreateTaskDisplayArea_topBelowAnotherTaskDisplayArea() {
+        final String newTdaName = "testTda";
+        final TaskDisplayArea parentTda = mDisplayContent.getDefaultTaskDisplayArea();
+        final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
+        final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea(
+                organizer, DEFAULT_DISPLAY, FEATURE_DEFAULT_TASK_CONTAINER, newTdaName);
+
+        final WindowContainer wc = parentTda.getChildAt(parentTda.getChildCount() - 1);
+
+        // A new TaskDisplayArea is created on the top.
+        assertThat(wc).isInstanceOf(TaskDisplayArea.class);
+        assertThat(tdaInfo.getDisplayAreaInfo().displayId).isEqualTo(DEFAULT_DISPLAY);
+        assertThat(tdaInfo.getDisplayAreaInfo().token)
+                .isEqualTo(wc.mRemoteToken.toWindowContainerToken());
+
+        final TaskDisplayArea tda = wc.asTaskDisplayArea();
+
+        assertThat(tda.getName()).isEqualTo(newTdaName);
+        assertThat(tda.mFeatureId).isEqualTo(tdaInfo.getDisplayAreaInfo().featureId);
+        assertThat(tda.mCreatedByOrganizer).isTrue();
+        assertThat(tda.mOrganizer).isEqualTo(organizer);
+    }
+
+    @Test
     public void testCreateTaskDisplayArea_incrementalTdaFeatureId() {
         final String newTdaName = "testTda";
         final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index e47913f..b33bb7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -667,6 +668,15 @@
         assertThat(token2.isDescendantOf(mGroupRoot2)).isTrue();
     }
 
+    @Test
+    public void testFeatureNotThrowArrayIndexOutOfBoundsException() {
+        final Feature feature1 = new Feature.Builder(mWms.mPolicy, "feature1",
+                FEATURE_VENDOR_FIRST + 5)
+                .all()
+                .except(TYPE_POINTER)
+                .build();
+    }
+
     private static Resources resourcesWithProvider(String provider) {
         Resources mock = mock(Resources.class);
         when(mock.getString(
@@ -690,7 +700,7 @@
     private Map<DisplayArea<?>, Set<Integer>> calculateZSets(
             DisplayAreaPolicyBuilder.Result policy,
             DisplayArea.Tokens ime,
-            DisplayArea<Task> tasks) {
+            TaskDisplayArea taskDisplayArea) {
         Map<DisplayArea<?>, Set<Integer>> zSets = new HashMap<>();
         int[] types = {TYPE_STATUS_BAR, TYPE_NAVIGATION_BAR, TYPE_PRESENTATION,
                 TYPE_APPLICATION_OVERLAY};
@@ -698,7 +708,7 @@
             WindowToken token = tokenOfType(type);
             recordLayer(policy.findAreaForToken(token), token.getWindowLayerFromType(), zSets);
         }
-        recordLayer(tasks, APPLICATION_LAYER, zSets);
+        recordLayer(taskDisplayArea, APPLICATION_LAYER, zSets);
         recordLayer(ime, mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD), zSets);
         return zSets;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 2053bfb..b451d9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -62,6 +62,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
@@ -168,7 +170,7 @@
         final WindowState imeAppTarget =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
 
-        mDisplayContent.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.setImeLayeringTarget(imeAppTarget);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -187,7 +189,7 @@
     @UseTestDisplay(addAllCommonWindows = true)
     @Test
     public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
-        mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
+        mDisplayContent.setImeLayeringTarget(mChildAppWindowAbove);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -205,7 +207,7 @@
     @UseTestDisplay(addAllCommonWindows = true)
     @Test
     public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
-        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
+        mDisplayContent.setImeLayeringTarget(mStatusBarWindow);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -223,7 +225,7 @@
     @UseTestDisplay(addAllCommonWindows = true)
     @Test
     public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception {
-        mDisplayContent.mInputMethodTarget = mNotificationShadeWindow;
+        mDisplayContent.setImeLayeringTarget(mNotificationShadeWindow);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -855,15 +857,17 @@
         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
         newDisplay.setInputMethodWindowLocked(null);
         assertEquals("appWin should be IME target window",
-                appWin, mDisplayContent.mInputMethodTarget);
-        assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
+                appWin, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
+        assertNull("newDisplay Ime target: ", newDisplay.getImeTarget(IME_TARGET_LAYERING));
 
         // Switch input method window on new display & make sure the input method target also
         // switched as expected.
         newDisplay.setInputMethodWindowLocked(mImeWindow);
         mDisplayContent.setInputMethodWindowLocked(null);
-        assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
-        assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
+        assertEquals("appWin1 should be IME target window", appWin1,
+                newDisplay.getImeTarget(IME_TARGET_LAYERING));
+        assertNull("default display Ime target: ",
+                mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
     }
 
     @Test
@@ -937,17 +941,17 @@
     @Test
     public void testComputeImeParent_app() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
-        dc.mInputMethodInputTarget = dc.mInputMethodTarget;
-        assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
-                dc.computeImeParent());
+        dc.setImeLayeringTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+        dc.setImeInputTarget(dc.getImeTarget(IME_TARGET_LAYERING).getWindow());
+        assertEquals(dc.getImeTarget(IME_TARGET_LAYERING).getWindow()
+                        .mActivityRecord.getSurfaceControl(), dc.computeImeParent());
     }
 
     @Test
     public void testComputeImeParent_app_notFullscreen() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
-        dc.mInputMethodTarget.setWindowingMode(
+        dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "app"));
+        dc.getImeTarget(IME_TARGET_LAYERING).getWindow().setWindowingMode(
                 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
     }
@@ -957,7 +961,7 @@
     public void testComputeImeParent_app_notMatchParentBounds() {
         spyOn(mAppWindow.mActivityRecord);
         doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
-        mDisplayContent.mInputMethodTarget = mAppWindow;
+        mDisplayContent.setImeLayeringTarget(mAppWindow);
         // The surface parent of IME should be the display instead of app window.
         assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(),
                 mDisplayContent.computeImeParent());
@@ -966,7 +970,7 @@
     @Test
     public void testComputeImeParent_noApp() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
+        dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "statusBar"));
         assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
     }
 
@@ -976,12 +980,12 @@
 
         WindowState app = createWindow(null, TYPE_BASE_APPLICATION, dc, "app");
 
-        dc.mInputMethodInputTarget = app;
+        dc.setImeInputTarget(app);
         assertEquals(app, dc.computeImeControlTarget());
 
         app.removeImmediately();
 
-        assertNull(dc.mInputMethodInputTarget);
+        assertNull(dc.getImeTarget(IME_TARGET_INPUT));
         assertNull(dc.computeImeControlTarget());
     }
 
@@ -989,20 +993,21 @@
     public void testComputeImeControlTarget() throws Exception {
         final DisplayContent dc = createNewDisplay();
         dc.setRemoteInsetsController(createDisplayWindowInsetsController());
-        dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
-        dc.mInputMethodTarget = dc.mInputMethodInputTarget;
-        assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
+        dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+        dc.setImeLayeringTarget(dc.getImeTarget(IME_TARGET_INPUT).getWindow());
+        assertEquals(dc.getImeTarget(IME_TARGET_INPUT).getWindow(), dc.computeImeControlTarget());
     }
 
     @Test
     public void testComputeImeControlTarget_splitscreen() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
-        dc.mInputMethodInputTarget.setWindowingMode(
+        dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+        dc.getImeTarget(IME_TARGET_INPUT).getWindow().setWindowingMode(
                 WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        dc.mInputMethodTarget = dc.mInputMethodInputTarget;
+        dc.setImeLayeringTarget(dc.getImeTarget(IME_TARGET_INPUT).getWindow());
         dc.setRemoteInsetsController(createDisplayWindowInsetsController());
-        assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
+        assertNotEquals(dc.getImeTarget(IME_TARGET_INPUT).getWindow(),
+                dc.computeImeControlTarget());
     }
 
     @UseTestDisplay(addWindows = W_ACTIVITY)
@@ -1010,8 +1015,9 @@
     public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
         spyOn(mAppWindow.mActivityRecord);
         doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
-        mDisplayContent.mInputMethodInputTarget = mAppWindow;
-        mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
+        mDisplayContent.setImeInputTarget(mAppWindow);
+        mDisplayContent.setImeLayeringTarget(
+                mDisplayContent.getImeTarget(IME_TARGET_INPUT).getWindow());
         mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
         assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
     }
@@ -1637,7 +1643,7 @@
                 TYPE_BASE_APPLICATION, "nextImeTargetApp");
         spyOn(child1);
         doReturn(true).when(child1).inSplitScreenWindowingMode();
-        mDisplayContent.mInputMethodTarget = child1;
+        mDisplayContent.setImeLayeringTarget(child1);
 
         spyOn(nextImeTargetApp);
         spyOn(mAppWindow);
@@ -1648,7 +1654,7 @@
         child1.removeImmediately();
 
         verify(mDisplayContent).computeImeTarget(true);
-        assertNull(mDisplayContent.mInputMethodInputTarget);
+        assertNull(mDisplayContent.getImeTarget(IME_TARGET_INPUT));
         verify(child1, never()).needsRelativeLayeringToIme();
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
index 7c4f7db..33e8fc0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
@@ -312,8 +312,7 @@
     private String getStoredDisplayAttributeValue(TestStorage storage, String attr)
             throws Exception {
         try (InputStream stream = storage.openRead()) {
-            TypedXmlPullParser parser = Xml.newFastPullParser();
-            parser.setInput(stream, StandardCharsets.UTF_8.name());
+            TypedXmlPullParser parser = Xml.resolvePullParser(stream);
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
                     && type != XmlPullParser.END_DOCUMENT) {
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/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
index 59d195b..5f96267 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
@@ -52,19 +52,19 @@
     public void testTransparentControlTargetWindowCanShowIme() {
         final WindowState appWin = createWindow(null, TYPE_APPLICATION, "app");
         final WindowState popup = createWindow(appWin, TYPE_APPLICATION, "popup");
-        mDisplayContent.mInputMethodControlTarget = popup;
-        mDisplayContent.mInputMethodTarget = appWin;
+        mDisplayContent.setImeControlTarget(popup);
+        mDisplayContent.setImeLayeringTarget(appWin);
         popup.mAttrs.format = PixelFormat.TRANSPARENT;
         mImeProvider.scheduleShowImePostLayout(appWin);
-        assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame());
+        assertTrue(mImeProvider.isReadyToShowIme());
     }
 
     @Test
     public void testInputMethodInputTargetCanShowIme() {
         WindowState target = createWindow(null, TYPE_APPLICATION, "app");
-        mDisplayContent.mInputMethodTarget = target;
+        mDisplayContent.setImeLayeringTarget(target);
         mImeProvider.scheduleShowImePostLayout(target);
-        assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame());
+        assertTrue(mImeProvider.isReadyToShowIme());
     }
 
     @Test
@@ -74,8 +74,8 @@
         mImeProvider.setWindow(ime, null, null);
 
         WindowState target = createWindow(null, TYPE_APPLICATION, "app");
-        mDisplayContent.mInputMethodTarget = target;
-        mDisplayContent.mInputMethodControlTarget = target;
+        mDisplayContent.setImeLayeringTarget(target);
+        mDisplayContent.setImeControlTarget(target);
 
         mImeProvider.scheduleShowImePostLayout(target);
         assertFalse(mImeProvider.isImeShowing());
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 90caf35..2766438 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -31,6 +31,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -181,16 +182,18 @@
         // This can be the IME z-order target while app cannot be the IME z-order target.
         // This is also the only IME control target in this test, so IME won't be invisible caused
         // by the control-target change.
-        mDisplayContent.mInputMethodInputTarget = createWindow(null, TYPE_APPLICATION, "base");
+        mDisplayContent.updateImeInputAndControlTarget(
+                createWindow(null, TYPE_APPLICATION, "base"));
 
         // Make IME and stay visible during the test.
         mImeWindow.setHasSurface(true);
         getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
-        getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget);
+        getController().onImeControlTargetChanged(mDisplayContent.getImeTarget(IME_TARGET_INPUT));
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_IME).setVisible(true);
-        mDisplayContent.mInputMethodInputTarget.updateRequestedVisibility(requestedState);
-        getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget);
+        mDisplayContent.getImeTarget(IME_TARGET_INPUT).getWindow()
+                .updateRequestedVisibility(requestedState);
+        getController().onInsetsModified(mDisplayContent.getImeTarget(IME_TARGET_INPUT));
 
         // Send our spy window (app) into the system so that we can detect the invocation.
         final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index a99e40c..089fd20 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -95,10 +95,10 @@
         final ActivityOptions options = mock(ActivityOptions.class);
         final Request request = new Request();
 
-        mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS,
-                new LaunchParams(), request);
+        mController.calculate(record.getTask(), layout, record, source, options, request,
+                PHASE_BOUNDS, new LaunchParams());
         verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
-                eq(source), eq(options), anyInt(), any(), any(), eq(request));
+                eq(source), eq(options), eq(request), anyInt(), any(), any());
     }
 
     /**
@@ -121,9 +121,9 @@
         mPersister.putLaunchParams(userId, name, expected);
 
         mController.calculate(activity.getTask(), null /*layout*/, activity, null /*source*/,
-                null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */);
-        verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                eq(expected), any(), any());
+                null /*options*/, null /*request*/, PHASE_BOUNDS, new LaunchParams());
+        verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), eq(expected), any());
     }
 
     /**
@@ -141,10 +141,10 @@
         mController.registerModifier(earlyExitPositioner);
 
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
-                null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
-                null /* request */);
-        verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                any(), any(), any());
+                null /*source*/, null /*options*/, null /*request*/,
+                PHASE_BOUNDS, new LaunchParams());
+        verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), any(), any());
     }
 
     /**
@@ -160,22 +160,22 @@
         mController.registerModifier(firstPositioner);
 
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
-                null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
-                null /* request */);
-        verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                any(), any(), any());
+                null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS,
+                new LaunchParams());
+        verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), any(), any());
 
         final LaunchParamsModifier secondPositioner = spy(earlyExitPositioner);
 
         mController.registerModifier(secondPositioner);
 
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
-                null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
-                null /* request */);
-        verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                any(), any(), any());
-        verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                any(), any(), any());
+                null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS,
+                new LaunchParams());
+        verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), any(), any());
+        verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), any(), any());
     }
 
     /**
@@ -197,10 +197,10 @@
         mController.registerModifier(positioner2);
 
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
-                null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */);
+                null /*options*/, null /*request*/, PHASE_BOUNDS, new LaunchParams());
 
-        verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
-                eq(positioner2.getLaunchParams()), any(), any());
+        verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+                anyInt(), eq(positioner2.getLaunchParams()), any());
     }
 
     /**
@@ -223,7 +223,7 @@
         final LaunchParams result = new LaunchParams();
 
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
-                null /*options*/, PHASE_BOUNDS, result, null /* request */);
+                null /*options*/, null /*request*/, PHASE_BOUNDS, result);
 
         assertEquals(result, positioner2.getLaunchParams());
     }
@@ -242,17 +242,17 @@
 
         // VR activities should always land on default display.
         mController.calculate(null /*task*/, null /*layout*/, vrActivity /*activity*/,
-                null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */);
+                null /*source*/, null /*options*/, null/*request*/, PHASE_BOUNDS, result);
         assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
                 result.mPreferredTaskDisplayArea);
 
         // Otherwise, always lands on VR 2D display.
         final ActivityRecord vr2dActivity = new ActivityBuilder(mAtm).build();
         mController.calculate(null /*task*/, null /*layout*/, vr2dActivity /*activity*/,
-                null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */);
+                null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS, result);
         assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea);
         mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
-                null /*options*/, PHASE_BOUNDS, result, null /* request */);
+                null /*options*/, null /*request*/, PHASE_BOUNDS, result);
         assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea);
 
         mAtm.mVr2dDisplayId = INVALID_DISPLAY;
@@ -273,10 +273,10 @@
         final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
         final ActivityOptions options = mock(ActivityOptions.class);
 
-        mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS,
-                new LaunchParams(), null /* request */);
+        mController.calculate(record.getTask(), layout, record, source, options, null/*request*/,
+                PHASE_BOUNDS, new LaunchParams());
         verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
-                eq(source), eq(options), eq(PHASE_BOUNDS), any(), any(), any());
+                eq(source), eq(options), any(), eq(PHASE_BOUNDS), any(), any());
     }
 
     /**
@@ -408,9 +408,8 @@
 
         @Override
         public int onCalculate(Task task, WindowLayout layout, ActivityRecord activity,
-                ActivityRecord source, ActivityOptions options, int phase,
-                LaunchParams currentParams, LaunchParams outParams,
-                Request request) {
+                ActivityRecord source, ActivityOptions options, Request request, int phase,
+                LaunchParams currentParams, LaunchParams outParams) {
             outParams.set(mParams);
             return mReturnVal;
         }
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..4dce451 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -49,7 +49,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.os.Binder;
@@ -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/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 9af2b96..171aa76 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -91,10 +91,9 @@
     @Test
     public void testAllPausedActivitiesComplete() {
         DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
-        TaskDisplayArea taskDisplayArea = displayContent.getDefaultTaskDisplayArea();
-        Task stack = taskDisplayArea.getRootTaskAt(0);
         ActivityRecord activity = createActivityRecord(displayContent);
-        stack.mPausingActivity = activity;
+        Task task = activity.getTask();
+        task.setPausingActivity(activity);
 
         activity.setState(PAUSING, "test PAUSING");
         assertThat(mWm.mRoot.allPausedActivitiesComplete()).isFalse();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 6821d47..e2be39b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -34,6 +34,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Build/Install/Run:
@@ -70,9 +71,12 @@
 
         final int numTasks = 10;
         int activeTime = 0;
+        final List<Task> rootTasks = new ArrayList<>();
+        display.getDefaultTaskDisplayArea().forAllRootTasks(task -> {
+            rootTasks.add(task);
+        }, false /* traverseTopToBottom */);
         for (int i = 0; i < numTasks; i++) {
-            createTask(display.getDefaultTaskDisplayArea().getRootTaskAt(i % numStacks),
-                    ".Task" + i, i, activeTime++, null);
+            createTask(rootTasks.get(i % numStacks), ".Task" + i, i, activeTime++, null);
         }
 
         // Ensure that the latest tasks were returned in order of decreasing last active time,
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index dd6e490..c7175a0c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -30,6 +30,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.Task.ActivityState.STOPPED;
 
 import static org.junit.Assert.assertEquals;
@@ -270,7 +271,7 @@
         // The position should be horizontal centered.
         assertEquals((displayWidth - bounds.width()) / 2, bounds.left);
 
-        mActivity.mDisplayContent.mInputMethodTarget = addWindowToActivity(mActivity);
+        mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
         // Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
         assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
 
@@ -290,9 +291,9 @@
         assertFitted();
 
         rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
-        mActivity.mDisplayContent.mInputMethodTarget = addWindowToActivity(mActivity);
-        mActivity.mDisplayContent.mInputMethodInputTarget =
-                mActivity.mDisplayContent.mInputMethodTarget;
+        mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
+        mActivity.mDisplayContent.setImeInputTarget(
+                mActivity.mDisplayContent.getImeTarget(IME_TARGET_LAYERING).getWindow());
         // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity.
         // The activity should still fill its parent container and IME can attach to the activity.
         assertTrue(mActivity.matchParentBounds());
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index ecbfac8..eff6919 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -136,6 +136,11 @@
     }
 
     @Override
+    public SurfaceControl.Transaction setBackgroundBlurRadius(SurfaceControl sc, int radius) {
+        return this;
+    }
+
+    @Override
     public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
         return this;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 269ce5d..99bdf9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -36,6 +36,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.ActivityStarter.Request;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
 
@@ -60,6 +61,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.server.wm.LaunchParamsController.LaunchParams;
+import com.android.server.wm.LaunchParamsController.LaunchParamsModifier.Result;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -108,8 +110,7 @@
     @Test
     public void testReturnsSkipWithEmptyActivity() {
         final Task task = new TaskBuilder(mSupervisor).build();
-        assertEquals(RESULT_SKIP, mTarget.onCalculate(task, /* layout */ null,
-                /* activity */ null, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setActivity(null).calculate());
     }
 
     // =============================
@@ -119,8 +120,7 @@
     public void testDefaultToPrimaryDisplayArea() {
         createNewDisplayContent(WINDOWING_MODE_FREEFORM);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -133,8 +133,7 @@
 
         mCurrent.mPreferredTaskDisplayArea = display.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(display.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
     }
@@ -150,8 +149,7 @@
 
         ActivityRecord source = createSourceActivity(fullscreenDisplay);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setSource(source).calculate());
 
         assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -170,8 +168,8 @@
         ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -191,8 +189,8 @@
         options.setLaunchTaskDisplayArea(fullscreenDisplay.getDefaultTaskDisplayArea()
                 .mRemoteToken.toWindowContainerToken());
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -209,8 +207,11 @@
         ActivityRecord reusableActivity = createSourceActivity(fullscreenDisplay);
         ActivityRecord source = createSourceActivity(freeformDisplay);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
-                /* layout */ null, mActivity, source, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder()
+                        .setTask(reusableActivity.getTask())
+                        .setSource(source)
+                        .calculate());
 
         assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -222,8 +223,10 @@
                 WINDOWING_MODE_FREEFORM);
         ActivityRecord source = createSourceActivity(freeformDisplay);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(source.getTask(), null /* layout */,
-                null /* activity */, null /* source */, null /* options */, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder()
+                        .setTask(source.getTask())
+                        .calculate());
 
         assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -242,8 +245,11 @@
         source.mHandoverLaunchDisplayId = freeformDisplay.mDisplayId;
         source.noDisplay = true;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
-                null /* layout */, mActivity, source, null /* options */, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder()
+                        .setTask(reusableActivity.getTask())
+                        .setSource(source)
+                        .calculate());
 
         assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -262,8 +268,11 @@
         source.mHandoverTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
         source.noDisplay = true;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
-                null /* layout */, mActivity, source, null /* options */, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder()
+                        .setTask(reusableActivity.getTask())
+                        .setSource(source)
+                        .calculate());
 
         assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
                 mResult.mPreferredTaskDisplayArea);
@@ -273,7 +282,6 @@
     public void testUsesDisplayAreaFromTopMostActivityInApplicationIfAvailable() {
         final String processName = "processName";
         final int uid = 124214;
-        final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
         final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
         final TaskDisplayArea expectedDisplayArea = secondScreen.getDefaultTaskDisplayArea();
         final WindowProcessController controller = mock(WindowProcessController.class);
@@ -286,17 +294,7 @@
                 .when(mSupervisor.mService)
                 .getProcessController(processName, uid);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
-                null /* task */,
-                null /* layout */,
-                mActivity /* activity */,
-                null /* source */,
-                null /* options */,
-                -1 /* phase */,
-                mCurrent,
-                mResult,
-                null /* request */
-        ));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(expectedDisplayArea, mResult.mPreferredTaskDisplayArea);
     }
@@ -305,7 +303,6 @@
     public void testUsesDisplayAreaFromLaunchingActivityIfApplicationLaunching() {
         final String processName = "processName";
         final int uid = 124214;
-        final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
         final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
         final TaskDisplayArea expectedTaskDisplayArea = secondScreen.getDefaultTaskDisplayArea();
         final WindowProcessController controller = mock(WindowProcessController.class);
@@ -322,17 +319,7 @@
                 .when(mSupervisor.mService)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
-                null /* task */,
-                null /* layout */,
-                mActivity /* activity */,
-                null /* source */,
-                null /* options */,
-                -1 /* phase */,
-                mCurrent,
-                mResult,
-                null /* request */
-        ));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
     }
@@ -363,17 +350,7 @@
                 .when(mSupervisor.mService)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
-                null /* task */,
-                null /* layout */,
-                mActivity /* activity */,
-                null /* source */,
-                null /* options */,
-                -1 /* phase */,
-                mCurrent,
-                mResult,
-                null /* request */
-        ));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
     }
@@ -403,17 +380,8 @@
                 .when(mSupervisor.mService)
                 .getProcessController(request.realCallingPid, request.realCallingUid);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
-                null /* task */,
-                null /* layout */,
-                mActivity /* activity */,
-                null /* source */,
-                null /* options */,
-                -1 /* phase */,
-                mCurrent,
-                mResult,
-                request
-        ));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setRequest(request).calculate());
 
         assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
     }
@@ -428,17 +396,7 @@
                 .when(mSupervisor.mService)
                 .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
-                null /* task */,
-                null /* layout */,
-                mActivity /* activity */,
-                null /* source */,
-                null /* options */,
-                -1 /* phase */,
-                mCurrent,
-                mResult,
-                null /* request */
-        ));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId());
     }
@@ -456,8 +414,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -470,8 +428,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -484,8 +442,8 @@
         final ActivityRecord source = createSourceActivity(fullscreenDisplay);
         source.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -501,8 +459,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -519,8 +477,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -533,8 +491,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -550,8 +508,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -567,8 +525,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.LEFT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -581,8 +539,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -594,8 +552,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -609,8 +566,7 @@
         mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
         mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -625,8 +581,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -648,8 +603,8 @@
 
         mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -673,8 +628,8 @@
 
         mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(expectedLaunchBounds, mResult.mBounds);
 
@@ -694,8 +649,8 @@
 
         mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -706,8 +661,8 @@
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(DEFAULT_DISPLAY);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -722,8 +677,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -737,8 +692,8 @@
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -754,8 +709,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
                 WINDOWING_MODE_FREEFORM);
@@ -768,8 +723,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
                 WINDOWING_MODE_FULLSCREEN);
@@ -791,8 +746,8 @@
 
         mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(expected, mResult.mBounds);
     }
@@ -808,8 +763,8 @@
         final Rect expected = new Rect(0, 0, 150, 150);
         options.setLaunchBounds(expected);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         assertEquals(expected, mResult.mBounds);
     }
@@ -824,8 +779,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.LEFT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
     }
@@ -840,8 +795,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.TOP).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
     }
@@ -856,8 +811,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.TOP | Gravity.LEFT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
         assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
@@ -873,8 +828,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.RIGHT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
     }
@@ -889,8 +844,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.BOTTOM).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
     }
@@ -905,8 +860,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
         assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
@@ -922,8 +877,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(800, 400, 920, 480), mResult.mBounds);
     }
@@ -938,8 +893,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.LEFT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(100, 400, 220, 480), mResult.mBounds);
     }
@@ -954,8 +909,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.TOP).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(800, 200, 920, 280), mResult.mBounds);
     }
@@ -970,8 +925,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.TOP | Gravity.LEFT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(100, 200, 220, 280), mResult.mBounds);
     }
@@ -986,8 +941,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.RIGHT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(1500, 400, 1620, 480), mResult.mBounds);
     }
@@ -1002,8 +957,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(800, 600, 920, 680), mResult.mBounds);
     }
@@ -1018,8 +973,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(1500, 600, 1620, 680), mResult.mBounds);
     }
@@ -1034,8 +989,8 @@
         final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
                 .setWidthFraction(0.125f).setHeightFraction(0.1f).build();
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).calculate());
 
         assertEquals(new Rect(765, 416, 955, 464), mResult.mBounds);
     }
@@ -1049,8 +1004,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
     }
@@ -1064,8 +1018,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
     }
@@ -1081,8 +1034,8 @@
 
         mActivity.info.screenOrientation = SCREEN_ORIENTATION_NOSENSOR;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         final int orientationForDisplay = orientationFromBounds(freeformDisplay.getBounds());
         final int orientationForTask = orientationFromBounds(mResult.mBounds);
@@ -1105,8 +1058,8 @@
 
         mActivity.info.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, orientationFromBounds(mResult.mBounds));
     }
@@ -1122,8 +1075,8 @@
 
         mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, orientationFromBounds(mResult.mBounds));
     }
@@ -1138,8 +1091,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         final int resultWidth = mResult.mBounds.width();
         final int displayWidth = freeformDisplay.getBounds().width();
@@ -1162,8 +1115,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals("Distance to left and right should be equal.",
                 mResult.mBounds.left - DISPLAY_STABLE_BOUNDS.left,
@@ -1186,8 +1139,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         final Rect displayBounds = freeformDisplay.getBounds();
         assertTrue("Left bounds should be larger than 0.", mResult.mBounds.left > 0);
@@ -1213,8 +1166,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         final Rect displayBounds = freeformDisplay.getBounds();
         assertTrue("display bounds doesn't contain result. display bounds: "
@@ -1235,8 +1188,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
 
         final Rect displayBounds = freeformDisplay.getBounds();
         assertTrue("display bounds doesn't contain result. display bounds: "
@@ -1257,8 +1210,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertTrue("Result bounds should start from app bounds's origin, but it's "
                         + mResult.mBounds,
@@ -1284,8 +1237,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertTrue("Result bounds should start from top-right corner of app bounds, but "
                         + "it's " + mResult.mBounds,
@@ -1311,8 +1264,8 @@
 
         mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
-                /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setLayout(layout).setOptions(options).calculate());
 
         assertEquals(500, mResult.mBounds.width());
         assertEquals(800, mResult.mBounds.height());
@@ -1329,8 +1282,8 @@
 
         mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(200, 0, 400, 400), mResult.mBounds);
     }
@@ -1346,8 +1299,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(50, 50, 500, 300));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(170, 50, 620, 300), mResult.mBounds);
     }
@@ -1363,8 +1316,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(1720, 50, 1850, 300));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(1600, 50, 1730, 300), mResult.mBounds);
     }
@@ -1380,8 +1333,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(0, 0, 1800, 200));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(120, 0, 1920, 200), mResult.mBounds);
     }
@@ -1397,8 +1350,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(120, 0, 1860, 200));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(0, 0, 1740, 200), mResult.mBounds);
     }
@@ -1414,8 +1367,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(120, 0, 1800, 1013));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(240, 67, 1920, 1080), mResult.mBounds);
     }
@@ -1431,8 +1384,8 @@
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
         options.setLaunchBounds(new Rect(120, 67, 1800, 1020));
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(0, 0, 1680, 953), mResult.mBounds);
     }
@@ -1443,8 +1396,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         // Returned bounds with in fullscreen mode will be set to last non-fullscreen bounds.
         assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
@@ -1462,8 +1414,8 @@
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, options, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE,
+                new CalculateRequestBuilder().setOptions(options).calculate());
 
         assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds);
     }
@@ -1479,8 +1431,7 @@
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
         mCurrent.mBounds.set(0, 0, 200, 100);
 
-        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
 
         assertEquals(new Rect(120, 0, 320, 100), mResult.mBounds);
     }
@@ -1510,8 +1461,7 @@
 
         try {
             mAtm.mSupportsMultiDisplay = false;
-            assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                    mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+            assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
             assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
                     mResult.mPreferredTaskDisplayArea);
         } finally {
@@ -1592,6 +1542,53 @@
                 : SCREEN_ORIENTATION_PORTRAIT;
     }
 
+    private class CalculateRequestBuilder {
+        private Task mTask;
+        private ActivityInfo.WindowLayout mLayout;
+        private ActivityRecord mActivity = TaskLaunchParamsModifierTests.this.mActivity;
+        private ActivityRecord mSource;
+        private ActivityOptions mOptions;
+        private Request mRequest;
+        private int mPhase = PHASE_BOUNDS;
+        private LaunchParams mCurrentParams = mCurrent;
+        private LaunchParams mOutParams = mResult;
+
+        private CalculateRequestBuilder setTask(Task task) {
+            mTask = task;
+            return this;
+        }
+
+        private CalculateRequestBuilder setLayout(ActivityInfo.WindowLayout layout) {
+            mLayout = layout;
+            return this;
+        }
+
+        private CalculateRequestBuilder setActivity(ActivityRecord activity) {
+            mActivity = activity;
+            return this;
+        }
+
+        private CalculateRequestBuilder setSource(ActivityRecord source) {
+            mSource = source;
+            return this;
+        }
+
+        private CalculateRequestBuilder setOptions(ActivityOptions options) {
+            mOptions = options;
+            return this;
+        }
+
+        private CalculateRequestBuilder setRequest(Request request) {
+            mRequest = request;
+            return this;
+        }
+
+        private @Result int calculate() {
+            return mTarget.onCalculate(mTask, mLayout, mActivity, mSource, mOptions, mRequest,
+                    mPhase, mCurrentParams, mOutParams);
+        }
+    }
+
     private static class WindowLayoutBuilder {
         private int mWidth = -1;
         private int mHeight = -1;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index f9f161a..98dee38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -23,7 +23,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 0bb2867..4d37eb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -30,8 +30,9 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
 
-import android.app.ActivityManager;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.res.Configuration;
@@ -42,6 +43,7 @@
 import android.hardware.HardwareBuffer;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
+import android.window.TaskSnapshot;
 
 import androidx.test.filters.SmallTest;
 
@@ -143,8 +145,8 @@
         final Point taskSize = new Point(5, 6);
 
         try {
-            ActivityManager.TaskSnapshot.Builder builder =
-                    new ActivityManager.TaskSnapshot.Builder();
+            TaskSnapshot.Builder builder =
+                    new TaskSnapshot.Builder();
             builder.setId(id);
             builder.setTopActivityComponent(activityComponent);
             builder.setAppearance(appearance);
@@ -161,7 +163,7 @@
             // Not part of TaskSnapshot itself, used in screenshot process
             assertEquals(pixelFormat, builder.getPixelFormat());
 
-            ActivityManager.TaskSnapshot snapshot = builder.build();
+            TaskSnapshot snapshot = builder.build();
             assertEquals(id, snapshot.getId());
             assertEquals(activityComponent, snapshot.getTopActivityComponent());
             assertEquals(appearance, snapshot.getAppearance());
@@ -183,6 +185,24 @@
         }
     }
 
+    @UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
+    @Test
+    public void testCreateTaskSnapshotWithExcludingIme() {
+        Task task = mAppWindow.mActivityRecord.getTask();
+        spyOn(task);
+        spyOn(mDisplayContent);
+        when(task.getDisplayContent().isImeAttachedToApp()).thenReturn(false);
+        // Intentionally set the SurfaceControl of input method window as null.
+        mDisplayContent.mInputMethodWindow.setSurfaceControl(null);
+        // Verify no NPE happens when calling createTaskSnapshot.
+        try {
+            mWm.mTaskSnapshotController.createTaskSnapshot(mAppWindow.mActivityRecord.getTask(),
+                    1f /* scaleFraction */, PixelFormat.UNKNOWN, null /* outTaskSize */);
+        } catch (NullPointerException e) {
+            fail("There should be no exception when calling createTaskSnapshot");
+        }
+    }
+
     @UseTestDisplay(addWindows = W_ACTIVITY)
     @Test
     public void testPrepareTaskSnapshot() {
@@ -191,8 +211,8 @@
         doReturn(true).when(mAppWindow.mWinAnimator).getShown();
         doReturn(true).when(mAppWindow.mActivityRecord).isSurfaceShowing();
 
-        final ActivityManager.TaskSnapshot.Builder builder =
-                new ActivityManager.TaskSnapshot.Builder();
+        final TaskSnapshot.Builder builder =
+                new TaskSnapshot.Builder();
         boolean success = mWm.mTaskSnapshotController.prepareTaskSnapshot(
                 mAppWindow.mActivityRecord.getTask(), PixelFormat.UNKNOWN, builder);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
index 8f913dd..ec0ca01 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
@@ -22,7 +22,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 8b90824..70d71bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -31,7 +31,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.SystemClock;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index fcd46a3..d9a794a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -28,7 +28,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.ComponentName;
 import android.content.ContextWrapper;
 import android.content.res.Resources;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 5ea73b8..aa638690 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -36,9 +36,8 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
 import android.content.ComponentName;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -93,8 +92,8 @@
                 ACTIVITY_TYPE_STANDARD, new InsetsState());
     }
 
-    private ActivityManager.TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
-            Rect contentInsets) {
+    private TaskSnapshot createTaskSnapshot(int width, int height,
+            Point taskSize, Rect contentInsets) {
         final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
                 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
         return new TaskSnapshot(
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 788ef5a..6046c9b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -20,20 +20,19 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static com.android.server.wm.utils.CommonUtils.runWithShellPermissionIdentity;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.ActivityView;
-import android.app.IActivityManager;
 import android.app.ITaskStackListener;
-import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.app.TaskStackListener;
 import android.content.ComponentName;
@@ -44,7 +43,6 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.view.Display;
 import android.view.ViewGroup;
@@ -52,10 +50,7 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 
-import com.android.compatibility.common.util.SystemUtil;
-
 import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 
 import java.util.concurrent.ArrayBlockingQueue;
@@ -70,17 +65,11 @@
 @MediumTest
 public class TaskStackChangedListenerTest {
 
-    private IActivityManager mService;
     private ITaskStackListener mTaskStackListener;
 
     private static final int WAIT_TIMEOUT_MS = 5000;
     private static final Object sLock = new Object();
 
-    @Before
-    public void setUp() throws Exception {
-        mService = ActivityManager.getService();
-    }
-
     @After
     public void tearDown() throws Exception {
         ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener);
@@ -374,7 +363,7 @@
         final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), null, false);
         getInstrumentation().addMonitor(monitor);
         final Context context = getInstrumentation().getContext();
-        SystemUtil.runWithShellPermissionIdentity(() -> context.startActivity(
+        runWithShellPermissionIdentity(() -> context.startActivity(
                 new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                 options.toBundle()));
         final TestActivity activity =
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/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index b78d6bb..001afe3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -116,10 +116,6 @@
     }
 
     @Override
-    public void dispatchPointerCaptureChanged(boolean hasCapture) {
-    }
-
-    @Override
     public void requestScrollCapture(IScrollCaptureCallbacks callbacks) throws RemoteException {
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index eb5f1f9..ccf2394 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -372,6 +372,11 @@
     }
 
     @Override
+    public int applyKeyguardOcclusionChange() {
+        return 0;
+    }
+
+    @Override
     public void setPipVisibilityLw(boolean visible) {
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 4909b1d..00c2aa5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -20,8 +20,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.window.TransitionInfo.TRANSIT_HIDE;
-import static android.window.TransitionInfo.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -74,21 +74,22 @@
         closing.mVisibleRequested = false;
         opening.mVisibleRequested = true;
 
-        int transitType = TRANSIT_OLD_TASK_OPEN;
+        int transit = TRANSIT_OLD_TASK_OPEN;
+        int flags = 0;
 
         // Check basic both tasks participating
         participants.add(oldTask);
         participants.add(newTask);
         ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
-        TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
-        assertEquals(transitType, info.getType());
+        assertEquals(transit, info.getType());
 
         // Check that children are pruned
         participants.add(opening);
         participants.add(closing);
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
         assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken()));
@@ -96,7 +97,7 @@
         // Check combined prune and promote
         participants.remove(newTask);
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
         assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken()));
@@ -104,7 +105,7 @@
         // Check multi promote
         participants.remove(oldTask);
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
         assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken()));
@@ -138,23 +139,24 @@
         opening.mVisibleRequested = true;
         opening2.mVisibleRequested = true;
 
-        int transitType = TRANSIT_OLD_TASK_OPEN;
+        int transit = TRANSIT_OLD_TASK_OPEN;
+        int flags = 0;
 
         // Check full promotion from leaf
         participants.add(oldTask);
         participants.add(opening);
         participants.add(opening2);
         ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
-        TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
-        assertEquals(transitType, info.getType());
+        assertEquals(transit, info.getType());
         assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken()));
 
         // Check that unchanging but visible descendant of sibling prevents promotion
         participants.remove(opening2);
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
         assertNotNull(info.getChange(newNestedTask.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken()));
@@ -184,29 +186,30 @@
         showing.mVisibleRequested = true;
         showing2.mVisibleRequested = true;
 
-        int transitType = TRANSIT_OLD_TASK_OPEN;
+        int transit = TRANSIT_OLD_TASK_OPEN;
+        int flags = 0;
 
         // Check promotion to DisplayArea
         participants.add(showing);
         participants.add(showing2);
         ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes);
-        TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(1, info.getChanges().size());
-        assertEquals(transitType, info.getType());
+        assertEquals(transit, info.getType());
         assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken()));
 
         ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
         // Check that organized tasks get reported even if not top
         showTask.mTaskOrganizer = mockOrg;
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
         assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken()));
         assertNotNull(info.getChange(showTask.mRemoteToken.toWindowContainerToken()));
         // Even if DisplayArea explicitly participating
         participants.add(tda);
         targets = Transition.calculateTargets(participants, changes);
-        info = Transition.calculateTransitionInfo(transitType, targets, changes);
+        info = Transition.calculateTransitionInfo(transit, flags, targets, changes);
         assertEquals(2, info.getChanges().size());
     }
 
@@ -231,13 +234,14 @@
 
         ArraySet<WindowContainer> targets = Transition.calculateTargets(
                 transition.mParticipants, transition.mChanges);
-        TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges);
+        TransitionInfo info = Transition.calculateTransitionInfo(
+                0, 0, targets, transition.mChanges);
         assertEquals(2, info.getChanges().size());
         // There was an existence change on open, so it should be OPEN rather than SHOW
         assertEquals(TRANSIT_OPEN,
                 info.getChange(openTask.mRemoteToken.toWindowContainerToken()).getMode());
         // No exestence change on closing, so HIDE rather than CLOSE
-        assertEquals(TRANSIT_HIDE,
+        assertEquals(TRANSIT_TO_BACK,
                 info.getChange(closeTask.mRemoteToken.toWindowContainerToken()).getMode());
     }
 
@@ -267,7 +271,8 @@
 
         ArraySet<WindowContainer> targets = Transition.calculateTargets(
                 transition.mParticipants, transition.mChanges);
-        TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges);
+        TransitionInfo info = Transition.calculateTransitionInfo(
+                0, 0, targets, transition.mChanges);
         assertEquals(taskCount, info.getChanges().size());
         // verify order is top-to-bottem
         for (int i = 0; i < taskCount; ++i) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 78e873e..f138475 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -56,7 +56,7 @@
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
                 TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
 
-        mDisplayContent.mInputMethodTarget = splitScreenWindow;
+        mDisplayContent.setImeLayeringTarget(splitScreenWindow);
 
         Consumer<WindowState> c = mock(Consumer.class);
         mDisplayContent.forAllWindows(c, false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index d2be50d..4a6906b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -292,7 +292,7 @@
 
         // Make IME attach to the window and can produce insets.
         final DisplayContent dc = mTestDisplayContent;
-        dc.mInputMethodTarget = w;
+        dc.setImeLayeringTarget(w);
         WindowState mockIme = mock(WindowState.class);
         Mockito.doReturn(true).when(mockIme).isVisibleNow();
         dc.mInputMethodWindow = mockIme;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index f123bc1..b7101c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -74,6 +74,7 @@
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.IWindowContainerTransactionCallback;
+import android.window.StartingWindowInfo;
 import android.window.TaskAppearedInfo;
 import android.window.WindowContainerTransaction;
 
@@ -506,12 +507,12 @@
     public void testTileAddRemoveChild() {
         ITaskOrganizer listener = new ITaskOrganizer.Stub() {
             @Override
-            public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+            public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
 
             }
 
             @Override
-            public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+            public void removeStartingWindow(int taskId) { }
 
             @Override
             public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -571,12 +572,12 @@
         final boolean[] called = {false};
         ITaskOrganizer listener = new ITaskOrganizer.Stub() {
             @Override
-            public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+            public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
 
             }
 
             @Override
-            public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+            public void removeStartingWindow(int taskId) { }
 
             @Override
             public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -642,12 +643,12 @@
         final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
         ITaskOrganizer listener = new ITaskOrganizer.Stub() {
             @Override
-            public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+            public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
 
             }
 
             @Override
-            public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+            public void removeStartingWindow(int taskId) { }
 
             @Override
             public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -741,11 +742,10 @@
     }
 
     private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) {
-        ArrayList<Task> out = new ArrayList<>();
-        dc.forAllTaskDisplayAreas(taskDisplayArea -> {
-            for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                final Task t = taskDisplayArea.getRootTaskAt(sNdx);
-                if (t.mCreatedByOrganizer) out.add(t);
+        final ArrayList<Task> out = new ArrayList<>();
+        dc.forAllRootTasks(task -> {
+            if (task.mCreatedByOrganizer) {
+                out.add(task);
             }
         });
         return out;
@@ -787,9 +787,9 @@
         RunningTaskInfo mInfo;
 
         @Override
-        public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) { }
+        public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { }
         @Override
-        public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+        public void removeStartingWindow(int taskId) { }
         @Override
         public void onTaskAppeared(RunningTaskInfo info, SurfaceControl leash) {
             mInfo = info;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index a57de09..76f8207 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -789,7 +789,7 @@
     public void testNeedsRelativeLayeringToIme_notAttached() {
         WindowState sameTokenWindow = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken,
                 "SameTokenWindow");
-        mDisplayContent.mInputMethodTarget = mAppWindow;
+        mDisplayContent.setImeLayeringTarget(mAppWindow);
         sameTokenWindow.mActivityRecord.getStack().setWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         assertTrue(sameTokenWindow.needsRelativeLayeringToIme());
@@ -802,7 +802,7 @@
     public void testNeedsRelativeLayeringToIme_startingWindow() {
         WindowState sameTokenWindow = createWindow(null, TYPE_APPLICATION_STARTING,
                 mAppWindow.mToken, "SameTokenWindow");
-        mDisplayContent.mInputMethodTarget = mAppWindow;
+        mDisplayContent.setImeLayeringTarget(mAppWindow);
         sameTokenWindow.mActivityRecord.getStack().setWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         assertFalse(sameTokenWindow.needsRelativeLayeringToIme());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index d64b46d..0d31d38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -84,6 +84,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.DisplayImePolicy;
 import android.window.ITaskOrganizer;
+import android.window.StartingWindowInfo;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.server.AttributeCache;
@@ -1090,10 +1091,10 @@
             mMoveToSecondaryOnEnter = move;
         }
         @Override
-        public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+        public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
         }
         @Override
-        public void removeStartingWindow(ActivityManager.RunningTaskInfo info) {
+        public void removeStartingWindow(int taskId) {
         }
         @Override
         public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) {
@@ -1121,12 +1122,9 @@
             mService.mTaskOrganizerController.setLaunchRoot(mDisplayId,
                     mSecondary.mRemoteToken.toWindowContainerToken());
             DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
-            dc.forAllTaskDisplayAreas(taskDisplayArea -> {
-                for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) {
-                    final Task stack = taskDisplayArea.getRootTaskAt(sNdx);
-                    if (!WindowConfiguration.isSplitScreenWindowingMode(stack.getWindowingMode())) {
-                        stack.reparent(mSecondary, POSITION_BOTTOM);
-                    }
+            dc.forAllRootTasks(rootTask -> {
+                if (!WindowConfiguration.isSplitScreenWindowingMode(rootTask.getWindowingMode())) {
+                    rootTask.reparent(mSecondary, POSITION_BOTTOM);
                 }
             });
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index e44d47a..811a146 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -218,7 +218,7 @@
 
     @Test
     public void testAssignWindowLayers_ForImeWithNoTarget() {
-        mDisplayContent.mInputMethodTarget = null;
+        mDisplayContent.setImeLayeringTarget(null);
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The Ime has an higher base layer than app windows and lower base layer than system
@@ -236,7 +236,7 @@
     @Test
     public void testAssignWindowLayers_ForImeWithAppTarget() {
         final WindowState imeAppTarget = createWindow("imeAppTarget");
-        mDisplayContent.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.setImeLayeringTarget(imeAppTarget);
 
         mDisplayContent.assignChildLayers(mTransaction);
 
@@ -262,7 +262,7 @@
                 TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
                 "imeAppTargetChildBelowWindow");
 
-        mDisplayContent.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.setImeLayeringTarget(imeAppTarget);
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for child windows that are z-ordered above it
@@ -284,7 +284,7 @@
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
 
-        mDisplayContent.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.setImeLayeringTarget(imeAppTarget);
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for non-fullscreen app window above it and
@@ -307,7 +307,7 @@
                 mDisplayContent, "imeSystemOverlayTarget",
                 true /* ownerCanAddInternalSystemWindow */);
 
-        mDisplayContent.mInputMethodTarget = imeSystemOverlayTarget;
+        mDisplayContent.setImeLayeringTarget(imeSystemOverlayTarget);
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The IME target base layer is higher than all window except for the nav bar window, so the
@@ -330,7 +330,7 @@
 
     @Test
     public void testAssignWindowLayers_ForStatusBarImeTarget() {
-        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
+        mDisplayContent.setImeLayeringTarget(mStatusBarWindow);
         mDisplayContent.assignChildLayers(mTransaction);
 
         assertWindowHigher(mImeWindow, mChildAppWindowAbove);
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java
new file mode 100644
index 0000000..99d73cf
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java
@@ -0,0 +1,37 @@
+/*
+ * 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.wm.utils;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.app.UiAutomation;
+
+/** Provides common utility functions. */
+public class CommonUtils {
+    public static UiAutomation getUiAutomation() {
+        return getInstrumentation().getUiAutomation();
+    }
+
+    public static void runWithShellPermissionIdentity(Runnable runnable) {
+        getUiAutomation().adoptShellPermissionIdentity();
+        try {
+            runnable.run();
+        } finally {
+            getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+}
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/OWNERS b/services/voiceinteraction/OWNERS
new file mode 100644
index 0000000..ef1061b
--- /dev/null
+++ b/services/voiceinteraction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/voice/OWNERS
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/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b5bb2a8..ec371bf 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -420,8 +420,9 @@
                         + interactorInfo + ")");
             }
 
-            // Initializing settings, look for an interactor first (but only on non-svelte).
-            if (curInteractorInfo == null && mEnableService) {
+            // Initializing settings. Look for an interactor first, but only on non-svelte and only
+            // if the user hasn't explicitly unset it.
+            if (curInteractorInfo == null && mEnableService && !"".equals(curInteractorStr)) {
                 curInteractorInfo = findAvailInteractor(userHandle, null);
             }
 
@@ -1751,8 +1752,13 @@
                 if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) {
                     return;
                 }
+                final String curInteractorStr = Settings.Secure.getStringForUser(
+                        mContext.getContentResolver(),
+                        Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
                 final ComponentName curInteractor = getCurInteractor(mCurUser);
-                if (curInteractor == null) {
+                // If there's no interactor and the user hasn't explicitly unset it, check if the
+                // modified package offers one.
+                if (curInteractor == null && !"".equals(curInteractorStr)) {
                     final VoiceInteractionServiceInfo availInteractorInfo
                             = findAvailInteractor(mCurUser, pkgName);
                     if (availInteractorInfo != null) {
diff --git a/services/wifi/OWNERS b/services/wifi/OWNERS
new file mode 100644
index 0000000..2ae7065
--- /dev/null
+++ b/services/wifi/OWNERS
@@ -0,0 +1 @@
+include /wifi/OWNERS
diff --git a/services/wifi/java/com/android/server/wifi/SupplicantManager.java b/services/wifi/java/com/android/server/wifi/SupplicantManager.java
index 5ed1ab3..e2e5b2b 100644
--- a/services/wifi/java/com/android/server/wifi/SupplicantManager.java
+++ b/services/wifi/java/com/android/server/wifi/SupplicantManager.java
@@ -18,6 +18,9 @@
 
 import android.annotation.SystemApi;
 import android.os.SystemService;
+import android.util.Log;
+
+import java.util.NoSuchElementException;
 
 /**
  * Wrapper to start/stop supplicant daemon using init system.
@@ -25,6 +28,8 @@
  */
 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
 public class SupplicantManager {
+    private static final String TAG = "SupplicantManager";
+
     private static final String WPA_SUPPLICANT_DAEMON_NAME = "wpa_supplicant";
 
     private SupplicantManager() {}
@@ -32,9 +37,16 @@
     /**
      * Start the wpa_supplicant daemon.
      * Note: This uses the init system to start the "wpa_supplicant" service.
+     *
+     * @throws NoSuchElementException if supplicant daemon failed to start
      */
     public static void start() {
-        SystemService.start(WPA_SUPPLICANT_DAEMON_NAME);
+        try {
+            SystemService.start(WPA_SUPPLICANT_DAEMON_NAME);
+        } catch (RuntimeException e) {
+            // likely a "failed to set system property" runtime exception
+            throw new NoSuchElementException("Failed to start Supplicant");
+        }
     }
 
     /**
@@ -42,6 +54,11 @@
      * Note: This uses the init system to stop the "wpa_supplicant" service.
      */
     public static void stop() {
-        SystemService.stop(WPA_SUPPLICANT_DAEMON_NAME);
+        try {
+            SystemService.stop(WPA_SUPPLICANT_DAEMON_NAME);
+        } catch (RuntimeException e) {
+            // likely a "failed to set system property" runtime exception
+            Log.w(TAG, "Failed to stop Supplicant", e);
+        }
     }
 }
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
index b77c03c..2e7bafe 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
@@ -36,15 +36,15 @@
  */
 public class SystemServiceUserEvent implements Parcelable {
 
-    /** @see com.android.server.SystemService#onStartUser */
+    /** @see com.android.server.SystemService#onUserStarting */
     public static final int TYPE_START_USER = 0;
-    /** @see com.android.server.SystemService#onUnlockUser */
+    /** @see com.android.server.SystemService#onUserUnlocking */
     public static final int TYPE_UNLOCK_USER = 1;
-    /** @see com.android.server.SystemService#onSwitchUser*/
+    /** @see com.android.server.SystemService#onUserSwitching*/
     public static final int TYPE_SWITCH_USER = 2;
-    /** @see com.android.server.SystemService#onStopUser */
+    /** @see com.android.server.SystemService#onUserStopping */
     public static final int TYPE_STOP_USER = 3;
-    /** @see com.android.server.SystemService#onCleanupUser */
+    /** @see com.android.server.SystemService#onUserStopped */
     public static final int TYPE_CLEANUP_USER = 4;
     private static final int TYPE_MAX = TYPE_CLEANUP_USER;
 
diff --git a/telecomm/java/android/telecom/OWNERS b/telecomm/java/android/telecom/OWNERS
new file mode 100644
index 0000000..6656a01
--- /dev/null
+++ b/telecomm/java/android/telecom/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
+hallliu@google.com
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 7629163..8531b50 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -26,7 +26,7 @@
 import android.os.CarrierAssociatedAppEntry;
 import android.os.SystemConfigManager;
 import android.os.UserHandle;
-import android.permission.PermissionManager;
+import android.permission.LegacyPermissionManager;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
@@ -141,8 +141,8 @@
             Map<String, List<CarrierAssociatedAppEntry>>
             systemCarrierAssociatedAppsDisabledUntilUsed, Context context) {
         PackageManager packageManager = context.getPackageManager();
-        PermissionManager permissionManager =
-                (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE);
+        LegacyPermissionManager permissionManager = (LegacyPermissionManager)
+                context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
         List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(
                 userId, systemCarrierAppsDisabledUntilUsed, context);
         if (candidates == null || candidates.isEmpty()) {
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 96996a1..32533cb 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -17,8 +17,10 @@
 package com.android.internal.telephony;
 
 import android.Manifest.permission;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -38,17 +40,20 @@
 import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.PackageChangeReceiver;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -86,6 +91,8 @@
 
     private static SmsPackageMonitor sSmsPackageMonitor = null;
 
+    private static SmsRoleListener sSmsRoleListener = null;
+
     public static class SmsApplicationData {
         /**
          * Name of this SMS app for display.
@@ -686,7 +693,7 @@
      * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
      * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
      */
-    public static void broadcastSmsAppChange(Context context,
+    private static void broadcastSmsAppChange(Context context,
             UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
         Collection<SmsApplicationData> apps = getApplicationCollection(context);
 
@@ -845,9 +852,51 @@
         }
     }
 
+    /**
+     * Tracks SMS role changes and sends broadcasts for default SMS app change.
+     */
+    private static final class SmsRoleListener implements OnRoleHoldersChangedListener {
+        private final Context mContext;
+        private final RoleManager mRoleManager;
+        private final SparseArray<String> mSmsPackageNames = new SparseArray<>();
+
+        public SmsRoleListener(@NonNull Context context) {
+            mContext = context;
+            mRoleManager = context.getSystemService(RoleManager.class);
+            final List<UserHandle> users = context.getSystemService(UserManager.class)
+                    .getUserHandles(true);
+            final int usersSize = users.size();
+            for (int i = 0; i < usersSize; i++) {
+                final UserHandle user = users.get(i);
+                mSmsPackageNames.put(user.getIdentifier(), getSmsPackageName(user));
+            }
+            mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(), this,
+                    UserHandle.ALL);
+        }
+
+        @Override
+        public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+            if (!Objects.equals(roleName, RoleManager.ROLE_SMS)) {
+                return;
+            }
+            final int userId = user.getIdentifier();
+            final String newSmsPackageName = getSmsPackageName(user);
+            broadcastSmsAppChange(mContext, user, mSmsPackageNames.get(userId), newSmsPackageName);
+            mSmsPackageNames.put(userId, newSmsPackageName);
+        }
+
+        @Nullable
+        private String getSmsPackageName(@NonNull UserHandle user) {
+            final List<String> roleHolders = mRoleManager.getRoleHoldersAsUser(
+                    RoleManager.ROLE_SMS, user);
+            return !roleHolders.isEmpty() ? roleHolders.get(0) : null;
+        }
+    }
+
     public static void initSmsPackageMonitor(Context context) {
         sSmsPackageMonitor = new SmsPackageMonitor(context);
         sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL);
+        sSmsRoleListener = new SmsRoleListener(context);
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 0c46394..515d329 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -27,7 +27,7 @@
 import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
-import android.permission.PermissionManager;
+import android.permission.LegacyPermissionManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
@@ -244,7 +244,9 @@
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
-     *       access check, or the calling package has carrier privileges on any active subscription.
+     *       access check, or the calling package has carrier privileges on any active
+     *       subscription, or the calling package has the {@link
+     *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
      *       or carrier privileges of any active subscription.
@@ -256,6 +258,10 @@
      */
     public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
             String callingPackage, @Nullable String callingFeatureId, String message) {
+        if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+                callingFeatureId, message)) {
+            return true;
+        }
         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
                 context, subId, callingPackage, callingFeatureId, message, true);
     }
@@ -267,7 +273,9 @@
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
-     *       access check, or the calling package has carrier privileges on specified subscription.
+     *       access check, or the calling package has carrier privileges on specified subscription,
+     *       or the calling package has the {@link
+     *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -278,6 +286,10 @@
      */
     public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
             String callingPackage, @Nullable String callingFeatureId, String message) {
+        if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
+                callingFeatureId, message)) {
+            return true;
+        }
         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
                 context, subId, callingPackage, callingFeatureId, message, false);
     }
@@ -315,8 +327,8 @@
             return true;
         }
 
-        PermissionManager permissionManager = (PermissionManager) context.getSystemService(
-                Context.PERMISSION_SERVICE);
+        LegacyPermissionManager permissionManager = (LegacyPermissionManager)
+                context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
         if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
                 pid, uid) == PackageManager.PERMISSION_GRANTED) {
             return true;
@@ -385,6 +397,26 @@
     }
 
     /**
+     * Check whether the caller (or self, if not processing an IPC) has {@link
+     * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission.
+     *
+     * <p>With the permission, the caller can access device/subscriber identifiers and use ICC
+     * authentication like EAP-AKA.
+     */
+    public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context,
+            String callingPackage, String callingFeatureId, String message) {
+        // Cannot perform appop check if the calling package is null
+        if (callingPackage == null) {
+            return false;
+        }
+        int callingUid = Binder.getCallingUid();
+        AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+                callingUid, callingPackage, callingFeatureId, message);
+        return opMode == AppOpsManager.MODE_ALLOWED;
+    }
+
+    /**
      * Check whether the app with the given pid/uid can read the call log.
      * @return {@code true} if the specified app has the read call log permission and AppOpp granted
      *      to it, {@code false} otherwise.
@@ -651,4 +683,23 @@
 
         throw new SecurityException(message + ": Only shell user can call it");
     }
+
+    /**
+     * Returns the target SDK version number for a given package name.
+     *
+     * This call MUST be invoked before clearing the calling UID.
+     *
+     * @return target SDK if the package is found or INT_MAX.
+     */
+    public static int getTargetSdk(Context c, String packageName) {
+        try {
+            final ApplicationInfo ai = c.getPackageManager().getApplicationInfoAsUser(
+                    packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
+            if (ai != null) return ai.targetSdkVersion;
+        } catch (PackageManager.NameNotFoundException unexpected) {
+            Log.e(LOG_TAG, "Failed to get package info for pkg="
+                    + packageName + ", uid=" + Binder.getCallingUid());
+        }
+        return Integer.MAX_VALUE;
+    }
 }
diff --git a/telephony/java/android/service/euicc/OWNERS b/telephony/java/android/service/euicc/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/service/euicc/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/service/sms/OWNERS b/telephony/java/android/service/sms/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/service/sms/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index f900c38..99f2e5e 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -624,6 +624,20 @@
     public @interface UiccAppType{}
 
     /**
+     * UICC SIM Application Types including UNKNOWN
+     */
+    @IntDef(prefix = { "APPTYPE_" }, value = {
+            TelephonyManager.APPTYPE_UNKNOWN,
+            TelephonyManager.APPTYPE_SIM,
+            TelephonyManager.APPTYPE_USIM,
+            TelephonyManager.APPTYPE_RUIM,
+            TelephonyManager.APPTYPE_CSIM,
+            TelephonyManager.APPTYPE_ISIM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface UiccAppTypeExt{}
+
+    /**
      * Override network type
      */
     @Retention(RetentionPolicy.SOURCE)
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0939bf0..56345c0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -2049,7 +2050,13 @@
      * via {@link android.telecom.PhoneAccount#CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE}
      * and can choose to hide or show the video calling icon based on whether a contact supports
      * video.
+     *
+     * @deprecated No longer used in framework code, however it may still be used by applications
+     * that have not updated their code. This config should still be set to {@code true} if
+     * {@link Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is set to {@code true} and
+     * {@link Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL} is set to {@code true}.
      */
+    @Deprecated
     public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
 
     /**
@@ -3865,13 +3872,51 @@
          * <p>
          * If this key's value is set to false, the procedure for RCS contact capability exchange
          * via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and
-         * {@link #KEY_USE_RCS_PRESENCE_BOOL} must also be set to false to ensure apps do not
-         * improperly think that capability exchange via SIP PUBLISH is enabled.
+         * {@link Ims#KEY_ENABLE_PRESENCE_PUBLISH_BOOL} must also be set to false to ensure
+         * apps do not improperly think that capability exchange via SIP PUBLISH is enabled.
          * <p> The default value for this key is {@code false}.
          */
         public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL =
                 KEY_PREFIX + "enable_presence_publish_bool";
 
+        /**
+         * Flag indicating whether or not this carrier supports the exchange of phone numbers with
+         * the carrier's RCS presence server in order to retrieve the RCS capabilities of requested
+         * contacts used in the RCS User Capability Exchange (UCE) procedure. See RCC.71, section 3
+         * for more information.
+         * <p>
+         * When presence is supported, the device uses the SIP SUBSCRIBE/NOTIFY procedure internally
+         * to retrieve the requested RCS capabilities. See
+         * {@link android.telephony.ims.RcsUceAdapter} for more information on how RCS capabilities
+         * can be retrieved from the carrier's network.
+         */
+        public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL =
+                KEY_PREFIX + "enable_presence_capability_exchange_bool";
+
+
+        /**
+         * Flag indicating whether or not the carrier expects the RCS UCE service to periodically
+         * refresh the RCS capabilities cache of the user's contacts as well as request the
+         * capabilities of call contacts when the SIM card is first inserted or when a new contact
+         * is added, removed, or modified. This corresponds to the RCC.07 A.19
+         * "DISABLE INITIAL ADDRESS BOOK SCAN" parameter.
+         * <p>
+         * If this flag is disabled, the capabilities cache will not be refreshed internally at all
+         * and will only be updated if the cached capabilities are stale when an application
+         * requests them.
+         */
+        public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL =
+                KEY_PREFIX + "rcs_bulk_capability_exchange_bool";
+
+        /**
+         * Flag indicating whether or not the carrier supports capability exchange with a list of
+         * contacts. When {@code true}, the device will batch together multiple requests and
+         * construct a RLMI document in the SIP SUBSCRIBE request (see RFC 4662). If {@code false},
+         * the request will be split up into one SIP SUBSCRIBE request per contact.
+         */
+        public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL =
+                KEY_PREFIX + "enable_presence_group_subscribe_bool";
+
         private Ims() {}
 
         private static PersistableBundle getDefaults() {
@@ -3879,6 +3924,510 @@
             defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
             defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
             defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
+            defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
+            defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
+            defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
+            return defaults;
+        }
+    }
+
+    /**
+     * Configs used for epdg tunnel bring up.
+     *
+     * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange Protocol
+     *     Version 2 (IKEv2)</a>
+     */
+    public static final class Iwlan {
+        /** Prefix of all Epdg.KEY_* constants. */
+        public static final String KEY_PREFIX = "iwlan.";
+
+        /**
+         * Time in seconds after which the child security association session is terminated if rekey
+         * procedure is not successful. If not set or set to <= 0, the default value is 3600
+         * seconds.
+         */
+        public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT =
+                KEY_PREFIX + "child_sa_rekey_hard_timer_sec_int";
+
+        /**
+         * Time in seconds after which the child session rekey procedure is started. If not set or
+         * set to <= 0, default value is 3000 seconds.
+         */
+        public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT =
+                KEY_PREFIX + "child_sa_rekey_soft_timer_sec_int";
+
+        /**
+         * Supported DH groups for IKE negotiation. Possible values are {@link #DH_GROUP_NONE},
+         * {@link #DH_GROUP_1024_BIT_MODP}, {@link #DH_GROUP_1536_BIT_MODP}, {@link
+         * #DH_GROUP_2048_BIT_MODP}
+         */
+        public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
+                KEY_PREFIX + "diffie_hellman_groups_int_array";
+
+        /**
+         * Time in seconds after which a dead peer detection (DPD) request is sent. If not set or
+         * set to <= 0, default value is 120 seconds.
+         */
+        public static final String KEY_DPD_TIMER_SEC_INT = KEY_PREFIX + "dpd_timer_sec_int";
+
+        /**
+         * Method used to authenticate epdg server. Possible values are {@link
+         * #AUTHENTICATION_METHOD_EAP_ONLY}, {@link #AUTHENTICATION_METHOD_CERT}
+         */
+        public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT =
+                KEY_PREFIX + "epdg_authentication_method_int";
+
+        /**
+         * A priority list of ePDG addresses to be used. Possible values are {@link
+         * #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN}, {@link #EPDG_ADDRESS_PCO}, {@link
+         * #EPDG_ADDRESS_CELLULAR_LOC}
+         */
+        public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
+                KEY_PREFIX + "epdg_address_priority_int_array";
+
+        /** Epdg static IP address or FQDN */
+        public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
+                KEY_PREFIX + "epdg_static_address_string";
+
+        /** Epdg static IP address or FQDN for roaming */
+        public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING =
+                KEY_PREFIX + "epdg_static_address_roaming_string";
+
+        /**
+         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of child
+         * session. Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128}, {@link
+         * #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "child_session_aes_cbc_key_size_int_array";
+
+        /**
+         * List of supported key sizes for AES Counter (CTR) encryption mode of child session.
+         * Possible values are {@link #KEY_LEN_UNUSED},
+         * {@link #KEY_LEN_AES_128}, {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "child_session_aes_ctr_key_size_int_array";
+
+        /**
+         * List of supported encryption algorithms for child session. Possible values are
+         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}
+         */
+        public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";
+
+        /**
+         * Time in seconds after which the IKE session is terminated if rekey procedure is not
+         * successful. If not set or set to <= 0, default value is 3600 seconds.
+         */
+        public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT =
+                KEY_PREFIX + "ike_rekey_hard_timer_in_sec";
+
+        /**
+         * Time in seconds after which the IKE session rekey procedure is started. If not set or set
+         * to <= 0, default value is 3000 seconds.
+         */
+        public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT =
+                KEY_PREFIX + "ike_rekey_soft_timer_sec_int";
+
+        /**
+         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of IKE
+         * session. Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128}, {@link
+         * #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
+
+
+        /**
+         * List of supported key sizes for AES Counter (CTR) encryption mode of IKE session.
+         * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+         * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+         public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+                 KEY_PREFIX + "ike_session_encryption_aes_ctr_key_size_int_array";
+
+        /**
+         * List of supported encryption algorithms for IKE session. Possible values are
+         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_CTR}
+         */
+        public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_ike_session_encryption_algorithms_int_array";
+
+        /**
+         * List of supported integrity algorithms for IKE session Possible values are {@link
+         * #INTEGRITY_ALGORITHM_NONE}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA1_96}, {@link
+         * #INTEGRITY_ALGORITHM_AES_XCBC_96}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_256_128}, {@link
+         * #INTEGRITY_ALGORITHM_HMAC_SHA2_384_192}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_512_256}
+         */
+        public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_integrity_algorithms_int_array";
+
+        /** Maximum number of retries for tunnel establishment. */
+        public static final String KEY_MAX_RETRIES_INT = KEY_PREFIX + "max_retries_int";
+
+        /**
+         * Time in seconds after which a NATT keep alive message is sent. If not set or set to <= 0,
+         * default value is 20 seconds.
+         */
+        public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT =
+                KEY_PREFIX + "natt_keep_alive_timer_sec_int";
+
+        /** List of '-' separated MCC/MNCs used to create ePDG FQDN as per 3GPP TS 23.003 */
+        public static final String KEY_MCC_MNCS_STRING_ARRAY = KEY_PREFIX + "mcc_mncs_string_array";
+
+        /**
+         * List of supported pseudo random function algorithms for IKE session. Possible values are
+         * {@link #PSEUDORANDOM_FUNCTION_HMAC_SHA1}, {@link #PSEUDORANDOM_FUNCTION_AES128_XCBC},
+         * {@link #PSEUDORANDOM_FUNCTION_SHA2_256}, {@link #PSEUDORANDOM_FUNCTION_SHA2_384},
+         * {@link #PSEUDORANDOM_FUNCTION_SHA2_512}
+         */
+        public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_prf_algorithms_int_array";
+
+        /**
+         * List of IKE message retransmission timeouts in milliseconds, where each timeout
+         * is the waiting time before next retry, except the last timeout which is the waiting time
+         * before terminating the IKE Session. Min list length = 1, Max
+         * list length = 10 Min timeout = 500 ms, Max timeout = 1800000 ms
+         */
+        public static final String KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY =
+                KEY_PREFIX + "retransmit_timer_sec_int_array";
+
+        /** Controls if wifi mac Id should be added to network access identifier(NAI) */
+        public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL =
+                KEY_PREFIX + "add_wifi_mac_addr_to_nai_bool";
+
+        /**
+         * Specifies the local identity type for IKE negotiations. Possible values are {@link
+         * #ID_TYPE_FQDN}, {@link #ID_TYPE_RFC822_ADDR}, {@link #ID_TYPE_KEY_ID}
+         */
+        public static final String KEY_IKE_LOCAL_ID_TYPE_INT = KEY_PREFIX + "ike_local_id_type_int";
+
+        /**
+         * Specifies the remote identity type for IKE negotiations. Possible values are {@link
+         * #ID_TYPE_FQDN}, {@link #ID_TYPE_RFC822_ADDR}, {@link #ID_TYPE_KEY_ID}
+         */
+        public static final String KEY_IKE_REMOTE_ID_TYPE_INT =
+                KEY_PREFIX + "ike_remote_id_type_int";
+
+        /** Controls if KE payload should be added during child session local rekey procedure. */
+        public static final String KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL =
+                KEY_PREFIX + "add_ke_to_child_session_rekey_bool";
+
+        /** Specifies the PCO id for IPv6 Epdg server address */
+        public static final String KEY_EPDG_PCO_ID_IPV6_INT = KEY_PREFIX + "epdg_pco_id_ipv6_int";
+
+        /** Specifies the PCO id for IPv4 Epdg server address */
+        public static final String KEY_EPDG_PCO_ID_IPV4_INT = KEY_PREFIX + "epdg_pco_id_ipv4_int";
+
+        /** @hide */
+        @IntDef({AUTHENTICATION_METHOD_EAP_ONLY, AUTHENTICATION_METHOD_CERT})
+        public @interface AuthenticationMethodType {}
+
+        /**
+         * Certificate sent from the server is ignored. Only Extensible Authentication Protocol
+         * (EAP) is used to authenticate the server. EAP_ONLY_AUTH payload is added to IKE_AUTH
+         * request if supported.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998</a>
+         */
+        public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0;
+        /** Server is authenticated using its certificate. */
+        public static final int AUTHENTICATION_METHOD_CERT = 1;
+
+        /** @hide */
+        @IntDef({
+            EPDG_ADDRESS_STATIC,
+            EPDG_ADDRESS_PLMN,
+            EPDG_ADDRESS_PCO,
+            EPDG_ADDRESS_CELLULAR_LOC
+        })
+        public @interface EpdgAddressType {}
+
+        /** Use static epdg address. */
+        public static final int EPDG_ADDRESS_STATIC = 0;
+        /** Construct the epdg address using plmn. */
+        public static final int EPDG_ADDRESS_PLMN = 1;
+        /**
+         * Use the epdg address received in protocol configuration options (PCO) from the network.
+         */
+        public static final int EPDG_ADDRESS_PCO = 2;
+        /** Use cellular location to chose epdg server */
+        public static final int EPDG_ADDRESS_CELLULAR_LOC = 3;
+
+        /** @hide */
+        @IntDef({KEY_LEN_UNUSED, KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256})
+        public @interface EncrpytionKeyLengthType {}
+
+        public static final int KEY_LEN_UNUSED = 0;
+        /** AES Encryption/Ciphering Algorithm key length 128 bits. */
+        public static final int KEY_LEN_AES_128 = 128;
+        /** AES Encryption/Ciphering Algorithm key length 192 bits. */
+        public static final int KEY_LEN_AES_192 = 192;
+        /** AES Encryption/Ciphering Algorithm key length 256 bits. */
+        public static final int KEY_LEN_AES_256 = 256;
+
+        /** @hide */
+        @IntDef({
+            DH_GROUP_NONE,
+            DH_GROUP_1024_BIT_MODP,
+            DH_GROUP_1536_BIT_MODP,
+            DH_GROUP_2048_BIT_MODP,
+            DH_GROUP_3072_BIT_MODP,
+            DH_GROUP_4096_BIT_MODP
+        })
+        public @interface DhGroup {}
+
+        /** None Diffie-Hellman Group. */
+        public static final int DH_GROUP_NONE = 0;
+        /**
+         * 1024-bit MODP Diffie-Hellman Group.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int DH_GROUP_1024_BIT_MODP = 2;
+        /**
+         * 1536-bit MODP Diffie-Hellman Group.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int DH_GROUP_1536_BIT_MODP = 5;
+        /**
+         * 2048-bit MODP Diffie-Hellman Group.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int DH_GROUP_2048_BIT_MODP = 14;
+        /**
+         * 3072-bit MODP Diffie-Hellman Group.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int DH_GROUP_3072_BIT_MODP = 15;
+        /**
+         * 4096-bit MODP Diffie-Hellman Group.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int DH_GROUP_4096_BIT_MODP = 16;
+
+        /** @hide */
+        @IntDef({ENCRYPTION_ALGORITHM_AES_CBC, ENCRYPTION_ALGORITHM_AES_CTR})
+        public @interface EncryptionAlgorithm {}
+
+        /**
+         * AES-CBC Encryption/Ciphering Algorithm.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12;
+
+        /**
+         * AES-CTR Encryption/Ciphering Algorithm.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int ENCRYPTION_ALGORITHM_AES_CTR = 13;
+
+        /** @hide */
+        @IntDef({
+            INTEGRITY_ALGORITHM_NONE,
+            INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+            INTEGRITY_ALGORITHM_AES_XCBC_96,
+            INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+            INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+            INTEGRITY_ALGORITHM_HMAC_SHA2_512_256
+        })
+        public @interface IntegrityAlgorithm {}
+
+        /** None Authentication/Integrity Algorithm. */
+        public static final int INTEGRITY_ALGORITHM_NONE = 0;
+        /**
+         * HMAC-SHA1 Authentication/Integrity Algorithm.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2;
+        /**
+         * AES-XCBC-96 Authentication/Integrity Algorithm.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5;
+        /**
+         * HMAC-SHA256 Authentication/Integrity Algorithm with 128-bit truncation.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12;
+        /**
+         * HMAC-SHA384 Authentication/Integrity Algorithm with 192-bit truncation.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13;
+        /**
+         * HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14;
+
+        /** @hide */
+        @IntDef({
+            PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+            PSEUDORANDOM_FUNCTION_AES128_XCBC,
+            PSEUDORANDOM_FUNCTION_SHA2_256,
+            PSEUDORANDOM_FUNCTION_SHA2_384,
+            PSEUDORANDOM_FUNCTION_SHA2_512
+        })
+        public @interface PseudorandomFunction {}
+
+        /**
+         * HMAC-SHA1 Pseudorandom Function.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2;
+        /**
+         * AES128-XCBC Pseudorandom Function.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4;
+        /**
+         * HMAC-SHA2-256 Pseudorandom Function.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int PSEUDORANDOM_FUNCTION_SHA2_256 = 5;
+        /**
+         * HMAC-SHA2-384 Pseudorandom Function.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int PSEUDORANDOM_FUNCTION_SHA2_384 = 6;
+        /**
+         * HMAC-SHA2-384 Pseudorandom Function.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int PSEUDORANDOM_FUNCTION_SHA2_512 = 7;
+
+        /** @hide */
+        @IntDef({ID_TYPE_FQDN, ID_TYPE_RFC822_ADDR, ID_TYPE_KEY_ID})
+        public @interface IkeIdType {}
+
+        /**
+         * Ike Identification Fully Qualified Domain Name
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int ID_TYPE_FQDN = 2;
+        /**
+         * Ike Identification Fully Qualified RFC 822 email address.
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int ID_TYPE_RFC822_ADDR = 3;
+        /**
+         * Ike Identification opaque octet stream for vendor specific information
+         *
+         * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+         *     Exchange Protocol Version 2 (IKEv2)</a>
+         */
+        public static final int ID_TYPE_KEY_ID = 11;
+
+        private Iwlan() {}
+
+        private static PersistableBundle getDefaults() {
+            PersistableBundle defaults = new PersistableBundle();
+            defaults.putInt(KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, 7200);
+            defaults.putInt(KEY_IKE_REKEY_HARD_TIMER_SEC_INT, 14400);
+            defaults.putInt(KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, 3600);
+            defaults.putInt(KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, 7200);
+            defaults.putIntArray(
+                    KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY, new int[] {500, 1000, 2000, 4000, 8000});
+            defaults.putInt(KEY_DPD_TIMER_SEC_INT, 120);
+            defaults.putInt(KEY_MAX_RETRIES_INT, 3);
+            defaults.putIntArray(
+                    KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY,
+                    new int[] {
+                        DH_GROUP_1024_BIT_MODP, DH_GROUP_1536_BIT_MODP, DH_GROUP_2048_BIT_MODP
+                    });
+            defaults.putIntArray(
+                    KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+                    new int[] {ENCRYPTION_ALGORITHM_AES_CBC});
+            defaults.putIntArray(
+                    KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+                    new int[] {ENCRYPTION_ALGORITHM_AES_CBC});
+            defaults.putIntArray(
+                    KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
+                    new int[] {
+                        INTEGRITY_ALGORITHM_AES_XCBC_96,
+                        INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+                        INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+                        INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+                        INTEGRITY_ALGORITHM_HMAC_SHA2_512_256,
+                    });
+            defaults.putIntArray(
+                    KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY,
+                    new int[] {
+                        PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+                        PSEUDORANDOM_FUNCTION_AES128_XCBC,
+                        PSEUDORANDOM_FUNCTION_SHA2_256,
+                        PSEUDORANDOM_FUNCTION_SHA2_384,
+                        PSEUDORANDOM_FUNCTION_SHA2_512
+                    });
+
+            defaults.putInt(KEY_EPDG_AUTHENTICATION_METHOD_INT, AUTHENTICATION_METHOD_EAP_ONLY);
+            defaults.putString(KEY_EPDG_STATIC_ADDRESS_STRING, "");
+            defaults.putString(KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, "");
+            // will be used after b/158036773 is fixed
+            defaults.putInt(KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, 20);
+            defaults.putIntArray(
+                    KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+                    new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+            defaults.putIntArray(
+                    KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+                    new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+            defaults.putIntArray(
+                    KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+                    new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+            defaults.putIntArray(
+                    KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+                    new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+            defaults.putIntArray(
+                    KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
+                    new int[] {EPDG_ADDRESS_PLMN, EPDG_ADDRESS_STATIC});
+            defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[] {});
+            defaults.putBoolean(KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL, false);
+            defaults.putInt(KEY_IKE_LOCAL_ID_TYPE_INT, ID_TYPE_RFC822_ADDR);
+            defaults.putInt(KEY_IKE_REMOTE_ID_TYPE_INT, ID_TYPE_FQDN);
+            defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
+            defaults.putInt(KEY_EPDG_PCO_ID_IPV6_INT, 0);
+            defaults.putInt(KEY_EPDG_PCO_ID_IPV4_INT, 0);
+
             return defaults;
         }
     }
@@ -4032,6 +4581,12 @@
     public static final String KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED =
             "use_lower_mtu_value_if_both_received";
 
+    /**
+     * Indicates if auto-configuration server is used for the RCS config
+     * Reference: GSMA RCC.14
+     */
+    public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -4551,6 +5106,7 @@
                 });
         sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
         sDefaults.putAll(Ims.getDefaults());
+        sDefaults.putAll(Iwlan.getDefaults());
         sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[0]);
          sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false);
         sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
@@ -4577,6 +5133,7 @@
         sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
         sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
         sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
+        sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index db7d10a..7addf33 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -443,10 +443,12 @@
     /**
      * Get table index for channel quality indicator
      *
+     * Reference: 3GPP TS 136.213 section 7.2.3.
+     *
      * @return the CQI table index if available or
      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
-    /** @hide */
+    @IntRange(from = 1, to = 6)
     public int getCqiTableIndex() {
         return mCqiTableIndex;
     }
@@ -454,9 +456,12 @@
     /**
      * Get channel quality indicator
      *
+     * Reference: 3GPP TS 136.213 section 7.2.3.
+     *
      * @return the CQI if available or
      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
+    @IntRange(from = 0, to = 15)
     public int getCqi() {
         return mCqi;
     }
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 1518190..bde62fb 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -294,9 +294,10 @@
      *
      * Reference: 3GPP TS 138.214 section 5.2.2.1.
      *
-     * Range [1, 3].
+     * @return the CQI table index if available or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
-    /** @hide */
+    @IntRange(from = 1, to = 3)
     public int getCsiCqiTableIndex() {
         return mCsiCqiTableIndex;
     }
@@ -310,10 +311,10 @@
      *
      * Reference: 3GPP TS 138.214 section 5.2.2.1.
      *
-     * Range [0, 15] for each CQI.
+     * @return the CQIs for all subbands if available or empty list if unavailable.
      */
-    /** @hide */
     @NonNull
+    @IntRange(from = 0, to = 15)
     public List<Integer> getCsiCqiReport() {
         return mCsiCqiReport;
     }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 8b7a243..d502da9 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -916,6 +916,84 @@
     /** System preference change back to SRAT during handoff */
     public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
 
+    //IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
+
+    /** The PDN connection corresponding to the requested APN has been rejected. */
+    public static final int IWLAN_PDN_CONNECTION_REJECTION = 0x2000;
+    /**
+     * The PDN connection has been rejected. No additional PDN connections can be established
+     * for the UE due to the network policies or capabilities.
+     */
+    public static final int IWLAN_MAX_CONNECTION_REACHED = 0x2001;
+    /**
+     * The PDN connection has been rejected due to a semantic error in TFT operation.
+     */
+    public static final int IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 0x2031;
+    /**
+     * The PDN connection has been rejected due to a syntactic error in TFT operation.
+     */
+    public static final int IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 0x2032;
+    /**
+     * The PDN connection has been rejected due to sematic errors in the packet filter.
+     */
+    public static final int IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS = 0x2034;
+    /**
+     * The PDN connection has been rejected due to syntactic errors in the packet filter.
+     */
+    public static final int IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS = 0x2035;
+    /**
+     * No non-3GPP subscription is associated with the IMSI.
+     * The UE is not allowed to use non-3GPP access to EPC.
+     */
+    public static final int IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED = 0x2328;
+    /** The user identified by the IMSI is unknown. */
+    public static final int IWLAN_USER_UNKNOWN = 0x2329;
+    /**
+     * The requested APN is not included in the user's profile,
+     * and therefore is not authorized for that user.
+     */
+    public static final int IWLAN_NO_APN_SUBSCRIPTION = 0x232A;
+    /** The user is barred from using the non-3GPP access or the subscribed APN. */
+    public static final int IWLAN_AUTHORIZATION_REJECTED = 0x232B;
+    /** The Mobile Equipment used is not acceptable to the network */
+    public static final int IWLAN_ILLEGAL_ME = 0x232E;
+    /**
+     * The network has determined that the requested procedure cannot be completed successfully
+     * due to network failure.
+     */
+    public static final int IWLAN_NETWORK_FAILURE = 0x2904;
+    /** The access type is restricted to the user. */
+    public static final int IWLAN_RAT_TYPE_NOT_ALLOWED = 0x2AF9;
+    /** The network does not accept emergency PDN bringup request using an IMEI */
+    public static final int IWLAN_IMEI_NOT_ACCEPTED = 0x2AFD;
+    /**
+     * The ePDG performs PLMN filtering (based on roaming agreements) and rejects
+     * the request from the UE.
+     * The UE requests service in a PLMN where the UE is not allowed to operate.
+     */
+    public static final int IWLAN_PLMN_NOT_ALLOWED = 0x2B03;
+    /** The ePDG does not support un-authenticated IMSI based emergency PDN bringup **/
+    public static final int IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED = 0x2B2F;
+
+    // Device is unable to establish an IPSec tunnel with the ePDG for any reason
+    // e.g authentication fail or certificate validation or DNS Resolution and timeout failure.
+
+    /** IKE configuration error resulting in failure  */
+    public static final int IWLAN_IKEV2_CONFIG_FAILURE = 0x4000;
+    /**
+     * Sent in the response to an IKE_AUTH message when, for some reason,
+     * the authentication failed.
+     */
+    public static final int IWLAN_IKEV2_AUTH_FAILURE = 0x4001;
+    /** IKE message timeout, tunnel setup failed due to no response from EPDG  */
+    public static final int IWLAN_IKEV2_MSG_TIMEOUT = 0x4002;
+    /** IKE Certification validation failure  */
+    public static final int IWLAN_IKEV2_CERT_INVALID = 0x4003;
+    /** Unable to resolve FQDN for the ePDG to an IP address */
+    public static final int IWLAN_DNS_RESOLUTION_NAME_FAILURE = 0x4004;
+    /** No response received from the DNS Server due to a timeout*/
+    public static final int IWLAN_DNS_RESOLUTION_TIMEOUT = 0x4005;
+
     // OEM sepecific error codes. To be used by OEMs when they don't
     // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
     public static final int OEM_DCFAILCAUSE_1 = 0x1001;
@@ -1341,6 +1419,34 @@
         sFailCauseMap.put(VSNCP_RECONNECT_NOT_ALLOWED, "VSNCP_RECONNECT_NOT_ALLOWED");
         sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE");
         sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED");
+        sFailCauseMap.put(IWLAN_PDN_CONNECTION_REJECTION, "IWLAN_PDN_CONNECTION_REJECTION");
+        sFailCauseMap.put(IWLAN_MAX_CONNECTION_REACHED, "IWLAN_MAX_CONNECTION_REACHED");
+        sFailCauseMap.put(IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION,
+                "IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION");
+        sFailCauseMap.put(IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION,
+                "IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION");
+        sFailCauseMap.put(IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS,
+                "IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS");
+        sFailCauseMap.put(IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS,
+                "IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS");
+        sFailCauseMap.put(IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED,
+                "IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED");
+        sFailCauseMap.put(IWLAN_USER_UNKNOWN, "IWLAN_USER_UNKNOWN");
+        sFailCauseMap.put(IWLAN_NO_APN_SUBSCRIPTION, "IWLAN_NO_APN_SUBSCRIPTION");
+        sFailCauseMap.put(IWLAN_AUTHORIZATION_REJECTED, "IWLAN_AUTHORIZATION_REJECTED");
+        sFailCauseMap.put(IWLAN_ILLEGAL_ME, "IWLAN_ILLEGAL_ME");
+        sFailCauseMap.put(IWLAN_NETWORK_FAILURE, "IWLAN_NETWORK_FAILURE");
+        sFailCauseMap.put(IWLAN_RAT_TYPE_NOT_ALLOWED, "IWLAN_RAT_TYPE_NOT_ALLOWED");
+        sFailCauseMap.put(IWLAN_IMEI_NOT_ACCEPTED, "IWLAN_IMEI_NOT_ACCEPTED");
+        sFailCauseMap.put(IWLAN_PLMN_NOT_ALLOWED, "IWLAN_PLMN_NOT_ALLOWED");
+        sFailCauseMap.put(IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED,
+                "IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED");
+        sFailCauseMap.put(IWLAN_IKEV2_CONFIG_FAILURE, "IWLAN_IKEV2_CONFIG_FAILURE");
+        sFailCauseMap.put(IWLAN_IKEV2_AUTH_FAILURE, "IWLAN_IKEV2_AUTH_FAILURE");
+        sFailCauseMap.put(IWLAN_IKEV2_MSG_TIMEOUT, "IWLAN_IKEV2_MSG_TIMEOUT");
+        sFailCauseMap.put(IWLAN_IKEV2_CERT_INVALID, "IWLAN_IKEV2_CERT_INVALID");
+        sFailCauseMap.put(IWLAN_DNS_RESOLUTION_NAME_FAILURE, "IWLAN_DNS_RESOLUTION_NAME_FAILURE");
+        sFailCauseMap.put(IWLAN_DNS_RESOLUTION_TIMEOUT, "IWLAN_DNS_RESOLUTION_TIMEOUT");
         sFailCauseMap.put(OEM_DCFAILCAUSE_1, "OEM_DCFAILCAUSE_1");
         sFailCauseMap.put(OEM_DCFAILCAUSE_2, "OEM_DCFAILCAUSE_2");
         sFailCauseMap.put(OEM_DCFAILCAUSE_3, "OEM_DCFAILCAUSE_3");
diff --git a/telephony/java/android/telephony/IBootstrapAuthenticationCallback.aidl b/telephony/java/android/telephony/IBootstrapAuthenticationCallback.aidl
new file mode 100644
index 0000000..d39ad0e
--- /dev/null
+++ b/telephony/java/android/telephony/IBootstrapAuthenticationCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.telephony;
+
+/**
+ * Callback to handle the response of bootstrapAuthenticationRequest
+ * @hide
+ */
+oneway interface IBootstrapAuthenticationCallback
+{
+    void onKeysAvailable(int token, in byte[] gbaKey, String btId);
+    void onAuthenticationFailure(int token, int reason);
+}
diff --git a/telephony/java/android/telephony/OWNERS b/telephony/java/android/telephony/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 572aed3..e145fcf 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -3134,26 +3134,20 @@
 
     /**
      * Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this.
-     *
-     * @return {@code true} if succeeded, otherwise {@code false}.
-     *
-     * // TODO: Unhide the API in S.
      * @hide
      */
-    public boolean resetAllCellBroadcastRanges() {
-        boolean success = false;
-
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+    public void resetAllCellBroadcastRanges() {
         try {
             ISms iSms = getISmsService();
             if (iSms != null) {
                 // If getSubscriptionId() returns INVALID or an inactive subscription, we will use
                 // the default phone internally.
-                success = iSms.resetAllCellBroadcastRanges(getSubscriptionId());
+                iSms.resetAllCellBroadcastRanges(getSubscriptionId());
             }
         } catch (RemoteException ex) {
-            // ignore it
+            ex.rethrowFromSystemServer();
         }
-
-        return success;
     }
 }
diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java
index 3d5c6aa..1fcb504 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -29,6 +29,10 @@
  * information is provided in accordance with carrier policy and branding preferences; it is not
  * necessarily a precise or accurate representation of the current state and should be treated
  * accordingly.
+ * To be notified of changes in TelephonyDisplayInfo, use
+ * {@link TelephonyManager#registerPhoneStateListener} with a {@link PhoneStateListener}
+ * that implements {@link PhoneStateListener.DisplayInfoChangedListener}.
+ * Override the onDisplayInfoChanged() method to handle the broadcast.
  */
 public final class TelephonyDisplayInfo implements Parcelable {
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 239329c..d1fd2d8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.Manifest;
+import android.annotation.BytesLong;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.LongDef;
@@ -80,12 +81,14 @@
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.ThermalMitigationResult;
 import android.telephony.Annotation.UiccAppType;
+import android.telephony.Annotation.UiccAppTypeExt;
 import android.telephony.CallForwardingInfo.CallForwardingReason;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.ApnSetting.MvnoType;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
 import android.telephony.ims.ImsMmTelManager;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsRegistration;
@@ -124,7 +127,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -549,6 +551,21 @@
         return getPhoneCount() > 1;
     }
 
+    private static final int MAXIMUM_CALL_COMPOSER_PICTURE_SIZE = 80000;
+
+    // TODO(hallliu): link to upload method in docs
+    /**
+     * Indicates the maximum size of the call composure picture.
+     *
+     * Pictures sent via uploadCallComposerPicture must not exceed this size, or an
+     * {@link IllegalArgumentException} will be thrown.
+     *
+     * @return Maximum file size in bytes.
+     */
+    public static @BytesLong long getMaximumCallComposerPictureSize() {
+        return MAXIMUM_CALL_COMPOSER_PICTURE_SIZE;
+    }
+
     //
     // Broadcast Intent actions
     //
@@ -1499,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.
@@ -2009,6 +2036,8 @@
      *     active subscription.
      *     <li>If the calling app is the default SMS role holder (see {@link
      *     RoleManager#isRoleHeld(String)}).
+     *     <li>If the calling app has been granted the
+     *      {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
      * </ul>
      *
      * <p>If the calling app does not meet one of these requirements then this method will behave
@@ -4019,6 +4048,8 @@
      *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *     <li>If the calling app is the default SMS role holder (see {@link
      *     RoleManager#isRoleHeld(String)}).
+     *     <li>If the calling app has been granted the
+     *     {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
      * </ul>
      *
      * <p>If the calling app does not meet one of these requirements then this method will behave
@@ -4043,33 +4074,8 @@
      * for a subscription.
      * Return null if it is unavailable.
      *
-     * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
-     * restrictions, and apps are recommended to use resettable identifiers (see <a
-     * href="/training/articles/user-data-ids">Best practices for unique identifiers</a>). This
-     * method can be invoked if one of the following requirements is met:
-     * <ul>
-     *     <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
-     *     is a privileged permission that can only be granted to apps preloaded on the device.
-     *     <li>If the calling app is the device or profile owner and has been granted the
-     *     {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
-     *     owns a managed profile on the device; for more details see <a
-     *     href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
-     *     Profile owner access is deprecated and will be removed in a future release.
-     *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
-     *     <li>If the calling app is the default SMS role holder (see {@link
-     *     RoleManager#isRoleHeld(String)}).
-     * </ul>
-     *
-     * <p>If the calling app does not meet one of these requirements then this method will behave
-     * as follows:
-     *
-     * <ul>
-     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
-     *     READ_PHONE_STATE permission then null is returned.</li>
-     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
-     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
-     *     higher, then a SecurityException is thrown.</li>
-     * </ul>
+     * See {@link #getSubscriberId()} for details on the required permissions and behavior
+     * when the caller does not hold sufficient permissions.
      *
      * @param subId whose subscriber id is returned
      * @hide
@@ -5594,57 +5600,6 @@
         }
     }
 
-    /**
-     * Registers a listener object to receive notification of changes
-     * in specified telephony states.
-     * <p>
-     * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony
-     * state of interest in the events argument.
-     *
-     * At registration, and when a specified telephony state changes, the telephony manager invokes
-     * the appropriate callback method on the listener object and passes the current (updated)
-     * values.
-     * <p>
-     * To un-register a listener, pass the listener object and set the events argument to
-     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
-     *
-     * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
-     * applies to the given subId. Otherwise, applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
-     * pass a separate listener object to each TelephonyManager object created with
-     * {@link #createForSubscriptionId}.
-     *
-     * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
-     * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
-     * {@link SecurityException} will be thrown otherwise.
-     *
-     * This API should be used sparingly -- large numbers of listeners will cause system
-     * instability. If a process has registered too many listeners without unregistering them, it
-     * may encounter an {@link IllegalStateException} when trying to register more listeners.
-     *
-     * @param events The telephony state(s) of interest to the listener,
-     *               as a bitwise-OR combination of {@link PhoneStateListener}
-     *               LISTEN_ flags.
-     * @param listener The {@link PhoneStateListener} object to register
-     *                 (or unregister)
-     * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}.
-     */
-    @Deprecated
-    public void listen(long events, @NonNull PhoneStateListener listener) {
-        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
-        if (mTelephonyRegistryMgr != null) {
-            if (events != PhoneStateListener.LISTEN_NONE) {
-                mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId,
-                        getOpPackageName(), getAttributionTag(), listener,
-                        Long.valueOf(events).intValue(), getITelephony() != null);
-            } else {
-                unregisterPhoneStateListener(listener);
-            }
-        } else {
-            throw new IllegalStateException("telephony service is null.");
-        }
-    }
-
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"ERI_"}, value = {
@@ -7204,6 +7159,8 @@
         }
     }
 
+    /** UICC application type is unknown or not specified */
+    public static final int APPTYPE_UNKNOWN = PhoneConstants.APPTYPE_UNKNOWN;
     /** UICC application type is SIM */
     public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
     /** UICC application type is USIM */
@@ -7226,8 +7183,13 @@
      * Returns the response of authentication for the default subscription.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling
-     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>Requires one of the following permissions:
+     * <ul>
+     *     <li>READ_PRIVILEGED_PHONE_STATE
+     *     <li>the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *     <li>the calling app has been granted the
+     *     {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
+     * </ul>
      *
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
      * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
@@ -7252,7 +7214,8 @@
      * Returns the response of USIM Authentication for specified subId.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>See {@link #getIccAuthentication(int, int, String)} for details on the required
+     * permissions.
      *
      * @param subId subscription ID used for authentication
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -7275,7 +7238,8 @@
             IPhoneSubInfo info = getSubscriberInfoService();
             if (info == null)
                 return null;
-            return info.getIccSimChallengeResponse(subId, appType, authType, data);
+            return info.getIccSimChallengeResponse(subId, appType, authType, data,
+                    getOpPackageName(), getAttributionTag());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -8707,6 +8671,77 @@
         return Collections.EMPTY_LIST;
     }
 
+    /**
+     * Call composer status OFF from user setting.
+     */
+    public static final int CALL_COMPOSER_STATUS_OFF = 0;
+
+    /**
+     * Call composer status ON from user setting.
+     */
+    public static final int CALL_COMPOSER_STATUS_ON = 1;
+
+    /** @hide */
+    @IntDef(prefix = {"CALL_COMPOSER_STATUS_"},
+            value = {
+                CALL_COMPOSER_STATUS_ON,
+                CALL_COMPOSER_STATUS_OFF,
+            })
+    public @interface CallComposerStatus {}
+
+    /**
+     * Set the user-set status for enriched calling with call composer.
+     *
+     * @param status user-set status for enriched calling with call composer;
+     *               it must be a value of either {@link #CALL_COMPOSER_STATUS_ON}
+     *               or {@link #CALL_COMPOSER_STATUS_OFF}.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
+     *
+     * @throws IllegalArgumentException if requested state is invalid.
+     * @throws SecurityException if the caller does not have the permission.
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setCallComposerStatus(@CallComposerStatus int status) {
+        if (status != CALL_COMPOSER_STATUS_ON && status != CALL_COMPOSER_STATUS_OFF) {
+            throw new IllegalArgumentException("requested status is invalid");
+        }
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setCallComposerStatus(getSubId(), status);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Error calling ITelephony#setCallComposerStatus", ex);
+            ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get the user-set status for enriched calling with call composer.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
+     *
+     * @throws SecurityException if the caller does not have the permission.
+     *
+     * @return the user-set status for enriched calling with call composer either
+     * {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @CallComposerStatus int getCallComposerStatus() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getCallComposerStatus(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Error calling ITelephony#getCallComposerStatus", ex);
+            ex.rethrowFromSystemServer();
+        }
+        return CALL_COMPOSER_STATUS_OFF;
+    }
 
     /** @hide */
     @SystemApi
@@ -9366,9 +9401,10 @@
      * @return true if mobile data is enabled.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
-            android.Manifest.permission.MODIFY_PHONE_STATE})
+            android.Manifest.permission.MODIFY_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE})
     public boolean isDataEnabled() {
-        return getDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
+        return isDataEnabledForReason(DATA_ENABLED_REASON_USER);
     }
 
     /**
@@ -9613,7 +9649,7 @@
     @SystemApi
     public boolean getDataEnabled(int subId) {
         try {
-            return isDataEnabledForReason(DATA_ENABLED_REASON_USER);
+            return isDataEnabledForReason(subId, DATA_ENABLED_REASON_USER);
         } catch (RuntimeException e) {
             Log.e(TAG, "Error calling isDataEnabledForReason e:" + e);
         }
@@ -10023,6 +10059,16 @@
      */
     public static final int CARD_POWER_UP_PASS_THROUGH = 2;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"CARD_POWER"},
+            value = {
+                    CARD_POWER_DOWN,
+                    CARD_POWER_UP,
+                    CARD_POWER_UP_PASS_THROUGH,
+            })
+    public @interface SimPowerState {}
+
     /**
      * Set SIM card power state.
      *
@@ -10033,12 +10079,17 @@
      * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
      * broadcasts to determine success or failure and timeout if needed.
      *
+     * @deprecated prefer {@link setSimPowerState(int, Executor, Consumer<Integer>)}.
+     * There is no guarantee that SIM power changes will trigger ACTION_SIM_STATE_CHANGED on new
+     * devices.
+     *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * {@hide}
      **/
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSimPowerState(int state) {
         setSimPowerStateForSlot(getSlotIndex(), state);
@@ -10055,12 +10106,16 @@
      * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
      * broadcasts to determine success or failure and timeout if needed.
      *
+     * @deprecated prefer {@link setSimPowerStateForSlot(int, int, Executor, Consumer<Integer>)}.
+     * changes will trigger ACTION_SIM_STATE_CHANGED on new devices.
+     *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      *
      * {@hide}
      **/
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setSimPowerStateForSlot(int slotIndex, int state) {
         try {
@@ -10076,6 +10131,85 @@
     }
 
     /**
+     * Set SIM card power state.
+     *
+     * @param state  State of SIM (power down, power up, pass through)
+     * @see #CARD_POWER_DOWN
+     * @see #CARD_POWER_UP
+     * @see #CARD_POWER_UP_PASS_THROUGH
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
+     * @see #SET_SIM_POWER_STATE_SUCCESS
+     * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE
+     * @see #SET_SIM_POWER_STATE_MODEM_ERROR
+     * @see #SET_SIM_POWER_STATE_SIM_ERROR
+     * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED
+     * @throws IllegalArgumentException if requested SIM state is invalid
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * {@hide}
+     **/
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSimPowerState(@SimPowerState int state, @NonNull Executor executor,
+            @NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
+        setSimPowerStateForSlot(getSlotIndex(), state, executor, callback);
+    }
+
+    /**
+     * Set SIM card power state.
+     *
+     * @param slotIndex SIM slot id
+     * @param state  State of SIM (power down, power up, pass through)
+     * @see #CARD_POWER_DOWN
+     * @see #CARD_POWER_UP
+     * @see #CARD_POWER_UP_PASS_THROUGH
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
+     * @see #SET_SIM_POWER_STATE_SUCCESS
+     * @see #SET_SIM_POWER_STATE_ALREADY_IN_STATE
+     * @see #SET_SIM_POWER_STATE_MODEM_ERROR
+     * @see #SET_SIM_POWER_STATE_SIM_ERROR
+     * @see #SET_SIM_POWER_STATE_NOT_SUPPORTED
+     * @throws IllegalArgumentException if requested SIM state is invalid
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * {@hide}
+     **/
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSimPowerStateForSlot(int slotIndex, @SimPowerState int state,
+            @NonNull Executor executor,
+            @NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
+        if (state != CARD_POWER_DOWN && state != CARD_POWER_UP
+                && state != CARD_POWER_UP_PASS_THROUGH) {
+            throw new IllegalArgumentException("requested SIM state is invalid");
+        }
+        try {
+            ITelephony telephony = getITelephony();
+            IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+                @Override
+                public void accept(int result) {
+                    executor.execute(() ->
+                            Binder.withCleanCallingIdentity(() -> callback.accept(result)));
+                }
+            };
+            if (telephony != null) {
+                telephony.setSimPowerStateForSlotWithCallback(slotIndex, state, internalCallback);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot",
+                    e);
+        }
+    }
+
+    /**
      * Set baseband version for the default phone.
      *
      * @param version baseband version
@@ -11194,6 +11328,55 @@
     public @interface SetCarrierRestrictionResult {}
 
     /**
+     * The SIM power state was successfully set.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_SUCCESS = 0;
+
+    /**
+     * The SIM is already in the requested power state.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_ALREADY_IN_STATE = 1;
+
+    /**
+     * Failed to connect to the modem to make the power state request. This may happen if the
+     * modem has an error. The user may want to make the request again later.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_MODEM_ERROR = 2;
+
+    /**
+     * Failed to connect to the SIM to make the power state request. This may happen if the
+     * SIM has been removed. The user may want to make the request again later.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_SIM_ERROR = 3;
+
+    /**
+     * The modem version does not support synchronous power.
+     * @hide
+     */
+    @SystemApi
+    public static final int SET_SIM_POWER_STATE_NOT_SUPPORTED = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SET_SIM_POWER_STATE_"},
+            value = {
+                    SET_SIM_POWER_STATE_SUCCESS,
+                    SET_SIM_POWER_STATE_ALREADY_IN_STATE,
+                    SET_SIM_POWER_STATE_MODEM_ERROR,
+                    SET_SIM_POWER_STATE_SIM_ERROR,
+                    SET_SIM_POWER_STATE_NOT_SUPPORTED
+            })
+    public @interface SetSimPowerStateResult {}
+
+    /**
      * Set the allowed carrier list and the excluded carrier list indicating the priority between
      * the two lists.
      * Requires system privileges.
@@ -14415,4 +14598,173 @@
             throw new IllegalStateException("telephony service is null.");
         }
     }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"GBA_FAILURE_REASON_"}, value = {
+            GBA_FAILURE_REASON_UNKNOWN,
+            GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED,
+            GBA_FAILURE_REASON_FEATURE_NOT_READY,
+            GBA_FAILURE_REASON_NETWORK_FAILURE,
+            GBA_FAILURE_REASON_INCORRECT_NAF_ID,
+            GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED})
+    public @interface AuthenticationFailureReason {}
+
+    /**
+     * GBA Authentication has failed for an unknown reason.
+     *
+     * <p>The caller should retry a message that failed with this response.
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_UNKNOWN = 0;
+
+    /**
+     * GBA Authentication is not supported by the carrier, SIM or android.
+     *
+     * <p>Application should use other authentication mechanisms if possible.
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED = 1;
+
+    /**
+     * GBA Authentication service is not ready for use.
+     *
+     * <p>Application could try again at a later time.
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_FEATURE_NOT_READY = 2;
+
+    /**
+     * GBA Authentication has been failed by the network.
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_NETWORK_FAILURE = 3;
+
+    /**
+     * GBA Authentication has failed due to incorrect NAF URL.
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_INCORRECT_NAF_ID = 4;
+
+    /**
+     * GBA Authentication has failed due to unsupported security protocol
+     * @hide
+     */
+    @SystemApi
+    public static final int GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED = 5;
+
+    /**
+     * The callback associated with a {@link #bootstrapAuthenticationRequest()}.
+     * @hide
+     */
+    @SystemApi
+    public static class BootstrapAuthenticationCallback {
+
+        /**
+         * Invoked when the previously requested GBA keys are available (@see
+         * bootstrapAuthenticationRequest()).
+         * @param gbaKey Ks_NAF/Ks_ext_NAF Response
+         * @param transactionId Bootstrapping Transaction Identifier
+         */
+        public void onKeysAvailable(@NonNull byte[] gbaKey, @NonNull String transactionId) {}
+
+        /**
+         * @param reason The reason for the authentication failure.
+         */
+        public void onAuthenticationFailure(@AuthenticationFailureReason int reason) {}
+    }
+
+    /**
+     * Used to get the Generic Bootstrapping Architecture authentication keys
+     * KsNAF/Ks_ext_NAF for a particular NAF as defined in 3GPP spec TS 33.220 for
+     * the specified sub id.
+     *
+     * <p>Application must be prepared to wait for receiving the Gba keys through the
+     * registered callback and not invoke the API on the main application thread.
+     * Application also must call the api to get the fresh key every time instead
+     * of caching the key.
+     *
+     * Following steps may be invoked on the API call depending on the state of the
+     * underlying GBA implementation:
+     * <ol>
+     *     <li>Resolve and bind to a Gba implementation.</li>
+     *     <li>Run bootstrapping if no valid keys are available or bootstrapping is forced.</li>
+     *     <li>Generate the ks_NAF/ ks_Ext_NAF to be returned via the callback.</li>
+     * </ol>
+     *
+     * <p> Requires Permission: MODIFY_PHONE_STATE or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}).
+     * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link
+     * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN}
+     * @param nafId Network Application Function(NAF) fully qualified domain name and
+     * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first
+     * part is the constant string "3GPP-bootstrapping" (GBA_ME),
+     * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest),
+     * and the latter part shall be the FQDN of the NAF (e.g.
+     * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com",
+     * or "3GPP-bootstrapping-digest@naf1.operator.com").
+     * @param securityProtocol Security protocol identifier between UE and NAF.  See
+     * 3GPP TS 33.220 Annex H. Application can use
+     * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId},
+     * {@link UaSecurityProtocolIdentifier#create3GppUaSpId},
+     * to create the ua security protocol identifier as needed
+     * @param forceBootStrapping true=force bootstrapping, false=do not force
+     * bootstrapping. Bootstrapping shouldn't be forced unless the application sees
+     * authentication errors from the server.
+     * @param e The {@link Executor} that will be used to call the Gba callback.
+     * @param callback A callback called on the supplied {@link Executor} that will
+     * contain the GBA Ks_NAF/Ks_ext_NAF when available. If the NAF keys are
+     * available and valid at the time of call and bootstrapping is not requested,
+     * then the callback shall be invoked with the available keys.
+     * @hide
+     */
+    @SystemApi
+    @WorkerThread
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void bootstrapAuthenticationRequest(
+            @UiccAppTypeExt int appType, @NonNull Uri nafId,
+            @NonNull UaSecurityProtocolIdentifier securityProtocol,
+            boolean forceBootStrapping, @NonNull Executor e,
+            @NonNull BootstrapAuthenticationCallback callback) {
+        try {
+            ITelephony service = getITelephony();
+            if (service == null) {
+                e.execute(() -> callback.onAuthenticationFailure(
+                        GBA_FAILURE_REASON_FEATURE_NOT_READY));
+                return;
+            }
+            service.bootstrapAuthenticationRequest(
+                    getSubId(), appType, nafId, securityProtocol, forceBootStrapping,
+                    new IBootstrapAuthenticationCallback.Stub() {
+                        @Override
+                        public void onKeysAvailable(int token, byte[] gbaKey,
+                                String transactionId) {
+                            final long identity = Binder.clearCallingIdentity();
+                            try {
+                                e.execute(() -> callback.onKeysAvailable(gbaKey, transactionId));
+                            } finally {
+                                Binder.restoreCallingIdentity(identity);
+                            }
+                        }
+
+                        @Override
+                        public void onAuthenticationFailure(int token, int reason) {
+                            final long identity = Binder.clearCallingIdentity();
+                            try {
+                                e.execute(() -> callback.onAuthenticationFailure(reason));
+                            } finally {
+                                Binder.restoreCallingIdentity(identity);
+                            }
+                        }
+                    });
+        } catch (RemoteException exception) {
+            Log.e(TAG, "Error calling ITelephony#bootstrapAuthenticationRequest", exception);
+            e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY));
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/cdma/OWNERS b/telephony/java/android/telephony/cdma/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.java b/telephony/java/android/telephony/data/ApnThrottleStatus.java
index 51461d1..eec1408 100644
--- a/telephony/java/android/telephony/data/ApnThrottleStatus.java
+++ b/telephony/java/android/telephony/data/ApnThrottleStatus.java
@@ -261,6 +261,10 @@
         private long mThrottleExpiryTimeMillis;
         private @RetryType int mRetryType;
         private @ThrottleType int mThrottleType;
+
+        /**
+         * @hide
+         */
         public static final long NO_THROTTLE_EXPIRY_TIME =
                 DataCallResponse.RETRY_DURATION_UNDEFINED;
 
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 090c970..556f2d5 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -253,7 +253,9 @@
     public int getCause() { return mCause; }
 
     /**
-     * @return The suggested data retry time in milliseconds.
+     * @return The suggested data retry time in milliseconds. 0 when network does not
+     * suggest a retry time (Note this is different from the replacement
+     * {@link #getRetryDurationMillis()}).
      *
      * @deprecated Use {@link #getRetryDurationMillis()} instead.
      */
diff --git a/telephony/java/android/telephony/data/OWNERS b/telephony/java/android/telephony/data/OWNERS
new file mode 100644
index 0000000..932b35c
--- /dev/null
+++ b/telephony/java/android/telephony/data/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+jackyu@google.com
diff --git a/telephony/java/android/telephony/emergency/OWNERS b/telephony/java/android/telephony/emergency/OWNERS
new file mode 100644
index 0000000..fa07dce
--- /dev/null
+++ b/telephony/java/android/telephony/emergency/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+shuoq@google.com
diff --git a/telephony/java/android/telephony/euicc/OWNERS b/telephony/java/android/telephony/euicc/OWNERS
new file mode 100644
index 0000000..9e51a4b
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+refuhoo@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/telephony/gba/GbaAuthRequest.aidl b/telephony/java/android/telephony/gba/GbaAuthRequest.aidl
new file mode 100644
index 0000000..ba243a2
--- /dev/null
+++ b/telephony/java/android/telephony/gba/GbaAuthRequest.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.gba;
+
+parcelable GbaAuthRequest;
diff --git a/telephony/java/android/telephony/gba/GbaAuthRequest.java b/telephony/java/android/telephony/gba/GbaAuthRequest.java
new file mode 100644
index 0000000..5366e9a
--- /dev/null
+++ b/telephony/java/android/telephony/gba/GbaAuthRequest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.gba;
+
+import android.annotation.NonNull;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.IBootstrapAuthenticationCallback;
+
+import com.android.internal.telephony.uicc.IccUtils;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * GBA authentication request
+ * {@hide}
+ */
+public final class GbaAuthRequest implements Parcelable {
+    private int mToken;
+    private int mSubId;
+    private int mAppType;
+    private Uri mNafUrl;
+    private byte[] mSecurityProtocol;
+    private boolean mForceBootStrapping;
+    private IBootstrapAuthenticationCallback mCallback;
+
+    private static AtomicInteger sUniqueToken = new AtomicInteger(0);
+
+    public GbaAuthRequest(int subId, int appType, Uri nafUrl, byte[] securityProtocol,
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) {
+        this(nextUniqueToken(), subId, appType, nafUrl,
+                securityProtocol, forceBootStrapping, callback);
+    }
+
+    public GbaAuthRequest(GbaAuthRequest request) {
+        this(request.mToken, request.mSubId, request.mAppType, request.mNafUrl,
+                request.mSecurityProtocol, request.mForceBootStrapping, request.mCallback);
+    }
+
+    public GbaAuthRequest(int token, int subId, int appType, Uri nafUrl, byte[] securityProtocol,
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) {
+        mToken = token;
+        mSubId = subId;
+        mAppType = appType;
+        mNafUrl = nafUrl;
+        mSecurityProtocol = securityProtocol;
+        mCallback = callback;
+        mForceBootStrapping = forceBootStrapping;
+    }
+
+    public int getToken() {
+        return mToken;
+    }
+
+    public int getSubId() {
+        return mSubId;
+    }
+
+    public int getAppType() {
+        return mAppType;
+    }
+
+    public Uri getNafUrl() {
+        return mNafUrl;
+    }
+
+    public byte[] getSecurityProtocol() {
+        return mSecurityProtocol;
+    }
+
+    public boolean isForceBootStrapping() {
+        return mForceBootStrapping;
+    }
+
+    public void setCallback(IBootstrapAuthenticationCallback cb) {
+        mCallback = cb;
+    }
+
+    public IBootstrapAuthenticationCallback getCallback() {
+        return mCallback;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mToken);
+        out.writeInt(mSubId);
+        out.writeInt(mAppType);
+        out.writeParcelable(mNafUrl, 0);
+        out.writeInt(mSecurityProtocol.length);
+        out.writeByteArray(mSecurityProtocol);
+        out.writeBoolean(mForceBootStrapping);
+        out.writeStrongInterface(mCallback);
+    }
+
+    /**
+     * {@link Parcelable.Creator}
+     *
+     */
+    public static final @android.annotation.NonNull Parcelable.Creator<
+            GbaAuthRequest> CREATOR = new Creator<GbaAuthRequest>() {
+                @Override
+                public GbaAuthRequest createFromParcel(Parcel in) {
+                    int token = in.readInt();
+                    int subId = in.readInt();
+                    int appType = in.readInt();
+                    Uri nafUrl = in.readParcelable(GbaAuthRequest.class.getClassLoader());
+                    int len = in.readInt();
+                    byte[] protocol = new byte[len];
+                    in.readByteArray(protocol);
+                    boolean forceBootStrapping = in.readBoolean();
+                    IBootstrapAuthenticationCallback callback =
+                            IBootstrapAuthenticationCallback.Stub
+                            .asInterface(in.readStrongBinder());
+                    return new GbaAuthRequest(token, subId, appType, nafUrl, protocol,
+                            forceBootStrapping, callback);
+                }
+
+                @Override
+                public GbaAuthRequest[] newArray(int size) {
+                    return new GbaAuthRequest[size];
+                }
+            };
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    private static int nextUniqueToken() {
+        return sUniqueToken.getAndIncrement() << 16 | (0xFFFF & (int) System.currentTimeMillis());
+    }
+
+    @Override
+    public String toString() {
+        String str = "Token: " +  mToken + "SubId:" + mSubId + ", AppType:"
+                + mAppType + ", NafUrl:" + mNafUrl + ", SecurityProtocol:"
+                + IccUtils.bytesToHexString(mSecurityProtocol)
+                + ", ForceBootStrapping:" + mForceBootStrapping
+                + ", CallBack:" + mCallback;
+        return str;
+    }
+}
diff --git a/telephony/java/android/telephony/gba/GbaService.java b/telephony/java/android/telephony/gba/GbaService.java
new file mode 100644
index 0000000..3962aff
--- /dev/null
+++ b/telephony/java/android/telephony/gba/GbaService.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.gba;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.Annotation.UiccAppTypeExt;
+import android.telephony.IBootstrapAuthenticationCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.AuthenticationFailureReason;
+import android.util.Log;
+import android.util.SparseArray;
+
+/**
+  * Base class for GBA Service. Any implementation which wants to provide
+  * GBA service must extend this class.
+  *
+  * <p>Note that the application to implement the service must declare to use
+  * the permission {@link android.Manifest.permission#BIND_GBA_SERVICE},
+  * and filter the intent of {@link #SERVICE_INTERFACE}.
+  * The manifest of the service must follow the format below:
+  *
+  * <p>...
+  * <service
+  *     android:name=".EgGbaService"
+  *     android:directBootAware="true"
+  *     android:permission="android.permission.BIND_GBA_SERVICE" >
+  *     ...
+  *     <intent-filter>
+  *         <action android:name="android.telephony.gba.GbaService"/>
+  *     </intent-filter>
+  * </service>
+  * ...
+  *
+  * <p>The service should also be file-based encryption (FBE) aware.
+  * {@hide}
+  */
+@SystemApi
+public class GbaService extends Service  {
+    private static final boolean DBG = Build.IS_DEBUGGABLE;
+    private static final String TAG = "GbaService";
+
+    /**
+    * The intent must be defined as an intent-filter in the
+    * AndroidManifest of the GbaService.
+    */
+    public static final String SERVICE_INTERFACE = "android.telephony.gba.GbaService";
+
+    private static final int EVENT_GBA_AUTH_REQUEST = 1;
+
+    private final HandlerThread mHandlerThread;
+    private final GbaServiceHandler mHandler;
+
+    private final SparseArray<IBootstrapAuthenticationCallback> mCallbacks = new SparseArray<>();
+    private final IGbaServiceWrapper mBinder = new IGbaServiceWrapper();
+
+    /**
+     * Default constructor.
+     */
+    public GbaService() {
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+
+        mHandler = new GbaServiceHandler(mHandlerThread.getLooper());
+        Log.d(TAG, "GBA service created");
+    }
+
+    private class GbaServiceHandler extends Handler {
+
+        GbaServiceHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_GBA_AUTH_REQUEST:
+                    GbaAuthRequest req = (GbaAuthRequest) msg.obj;
+                    synchronized (mCallbacks) {
+                        mCallbacks.put(req.getToken(), req.getCallback());
+                    }
+                    onAuthenticationRequest(req.getSubId(), req.getToken(), req.getAppType(),
+                            req.getNafUrl(), req.getSecurityProtocol(), req.isForceBootStrapping());
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Called by the platform when a GBA authentication request is received from
+     * {@link TelephonyManager#bootstrapAuthenticationRequest} to get the KsNAF for
+     * a particular NAF.
+     *
+     * @param subscriptionId the ICC card to be used for the bootstrapping authentication.
+     * @param token the identification of the authentication request.
+     * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link
+     * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN}
+     * @param nafUrl Network Application Function(NAF) fully qualified domain name and
+     * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first
+     * part is the constant string "3GPP-bootstrapping" (GBA_ME),
+     * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest),
+     * and the latter part shall be the FQDN of the NAF (e.g.
+     * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com",
+     * or "3GPP-bootstrapping-digest@naf1.operator.com").
+     * @param securityProtocol Security protocol identifier between UE and NAF.  See
+     * 3GPP TS 33.220 Annex H. Application can use
+     * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId},
+     * {@link UaSecurityProtocolIdentifier#create3GppUaSpId},
+     * to create the ua security protocol identifier as needed
+     * @param forceBootStrapping true=force bootstrapping, false=do not force
+     * bootstrapping. Bootstrapping shouldn't be forced unless the application sees
+     * authentication errors from the server.
+     * Response is returned via {@link TelephonyManager#BootstrapAuthenticationCallback}
+     * along with the token to identify the request.
+     *
+     * <p>Note that this is not called in the main thread.
+     */
+    public void onAuthenticationRequest(int subscriptionId, int token, @UiccAppTypeExt int appType,
+            @NonNull Uri nafUrl, @NonNull byte[] securityProtocol, boolean forceBootStrapping) {
+        //Default implementation should be overridden by vendor Gba Service. Vendor Gba Service
+        //should handle the gba bootstrap authentication request, and call reportKeysAvailable or
+        //reportAuthenticationFailure to notify the caller accordingly.
+        reportAuthenticationFailure(
+                token, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED);
+    }
+
+    /**
+     * Called by {@link GbaService} when the previously requested GBA keys are available
+     * (@see onAuthenticationRequest())
+     *
+     * @param token unique identifier of the request.
+     * @param gbaKey KsNaf Response.
+     * @param transactionId Bootstrapping Transaction ID.
+     * @throws RuntimeException when there is remote failure of callback.
+     */
+    public final void reportKeysAvailable(int token, @NonNull byte[] gbaKey,
+            @NonNull String transactionId) throws RuntimeException {
+        IBootstrapAuthenticationCallback cb = null;
+        synchronized (mCallbacks) {
+            cb = mCallbacks.get(token);
+            mCallbacks.remove(token);
+        }
+        if (cb != null) {
+            try {
+                cb.onKeysAvailable(token, gbaKey, transactionId);
+            } catch (RemoteException exception) {
+                throw exception.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
+     * Invoked when the previously requested GBA key authentication failed
+     * (@see onAuthenticationRequest())
+     *
+     * @param token unique identifier of the request.
+     * @param reason The reason for the authentication failure.
+     * @throws RuntimeException when there is remote failure of callback.
+     */
+    public final void reportAuthenticationFailure(int token,
+            @AuthenticationFailureReason int reason) throws RuntimeException {
+        IBootstrapAuthenticationCallback cb = null;
+        synchronized (mCallbacks) {
+            cb = mCallbacks.get(token);
+            mCallbacks.remove(token);
+        }
+        if (cb != null) {
+            try {
+                cb.onAuthenticationFailure(token, reason);
+            } catch (RemoteException exception) {
+                throw exception.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /** @hide */
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            Log.d(TAG, "GbaService Bound.");
+            return mBinder;
+        }
+        return null;
+    }
+
+    /** @hide */
+    @Override
+    public void onDestroy() {
+        mHandlerThread.quit();
+        super.onDestroy();
+    }
+
+    private class IGbaServiceWrapper extends IGbaService.Stub {
+        @Override
+        public void authenticationRequest(GbaAuthRequest request) {
+            if (DBG) Log.d(TAG, "receive request: " + request);
+            mHandler.obtainMessage(EVENT_GBA_AUTH_REQUEST, request).sendToTarget();
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/gba/IGbaService.aidl b/telephony/java/android/telephony/gba/IGbaService.aidl
new file mode 100644
index 0000000..b7ba5a4
--- /dev/null
+++ b/telephony/java/android/telephony/gba/IGbaService.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.telephony.gba;
+
+import android.net.Uri;
+import android.telephony.gba.GbaAuthRequest;
+
+/**
+ * @hide
+ */
+interface IGbaService
+{
+    oneway void authenticationRequest(in GbaAuthRequest request);
+}
diff --git a/telephony/java/android/telephony/gba/TlsParams.java b/telephony/java/android/telephony/gba/TlsParams.java
new file mode 100644
index 0000000..922f4bb
--- /dev/null
+++ b/telephony/java/android/telephony/gba/TlsParams.java
@@ -0,0 +1,281 @@
+/*
+ * 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.telephony.gba;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * Defines the TLS parameters for GBA as per IANA and TS 33.210, which are used
+ * by some UA security protocol identifiers defined in 3GPP TS 33.220 Annex H,
+ * and 3GPP TS 33.222.
+ *
+ * @hide
+ */
+@SystemApi
+public class TlsParams {
+
+    private TlsParams() {}
+
+    /**
+     * TLS protocol version supported by GBA
+     */
+    public static final int PROTOCOL_VERSION_TLS_1_2 = 0x0303;
+    public static final int PROTOCOL_VERSION_TLS_1_3 = 0x0304;
+
+    /**
+     * TLS cipher suites are used to create {@link UaSecurityProtocolIdentifier}
+     * by {@link UaSecurityProtocolIdentifier#create3GppUaSpId}
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+        prefix = {"TLS_"},
+        value = {
+            TLS_NULL_WITH_NULL_NULL,
+            TLS_RSA_WITH_NULL_MD5,
+            TLS_RSA_WITH_NULL_SHA,
+            TLS_RSA_WITH_RC4_128_MD5,
+            TLS_RSA_WITH_RC4_128_SHA,
+            TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+            TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+            TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+            TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+            TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+            TLS_DH_ANON_WITH_RC4_128_MD5,
+            TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA,
+            TLS_RSA_WITH_AES_128_CBC_SHA,
+            TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+            TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+            TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+            TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+            TLS_DH_ANON_WITH_AES_128_CBC_SHA,
+            TLS_RSA_WITH_AES_256_CBC_SHA,
+            TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+            TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+            TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+            TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+            TLS_DH_ANON_WITH_AES_256_CBC_SHA,
+            TLS_RSA_WITH_NULL_SHA256,
+            TLS_RSA_WITH_AES_128_CBC_SHA256,
+            TLS_RSA_WITH_AES_256_CBC_SHA256,
+            TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+            TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+            TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+            TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+            TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+            TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+            TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+            TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+            TLS_DH_ANON_WITH_AES_128_CBC_SHA256,
+            TLS_DH_ANON_WITH_AES_256_CBC_SHA256,
+            TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+            TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+            TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+            TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+            TLS_AES_128_GCM_SHA256,
+            TLS_AES_256_GCM_SHA384,
+            TLS_CHACHA20_POLY1305_SHA256,
+            TLS_AES_128_CCM_SHA256,
+            TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+            TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+            TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+            TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+            TLS_DHE_RSA_WITH_AES_128_CCM,
+            TLS_DHE_RSA_WITH_AES_256_CCM,
+            TLS_DHE_PSK_WITH_AES_128_CCM,
+            TLS_DHE_PSK_WITH_AES_256_CCM,
+            TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+            TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+            TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+            TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+            TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+            TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+            TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
+            TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256
+        })
+    public @interface TlsCipherSuite {}
+
+    // Cipher suites for TLS v1.2 per RFC5246
+    public static final int TLS_NULL_WITH_NULL_NULL = 0x0000;
+    public static final int TLS_RSA_WITH_NULL_MD5 = 0x0001;
+    public static final int TLS_RSA_WITH_NULL_SHA = 0x0002;
+    public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
+    public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
+    public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
+    public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
+    public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
+    public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
+    public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
+    public static final int TLS_DH_ANON_WITH_RC4_128_MD5 = 0x0018;
+    public static final int TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA = 0x001B;
+    public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
+    public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
+    public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
+    public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
+    public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
+    public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034;
+    public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
+    public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
+    public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
+    public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
+    public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
+    public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A;
+    public static final int TLS_RSA_WITH_NULL_SHA256 = 0x003B;
+    public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C;
+    public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D;
+    public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E;
+    public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F;
+    public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040;
+    public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067;
+    public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068;
+    public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069;
+    public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A;
+    public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
+    public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 0x006C;
+    public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x006D;
+
+    // Cipher suites for TLS v1.3 per RFC8446 and recommended by IANA
+    public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E;
+    public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F;
+    public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA;
+    public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB;
+    public static final int TLS_AES_128_GCM_SHA256 = 0x1301;
+    public static final int TLS_AES_256_GCM_SHA384 = 0x1302;
+    public static final int TLS_CHACHA20_POLY1305_SHA256 = 0x1303;
+    public static final int TLS_AES_128_CCM_SHA256 = 0x1304;
+    public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
+    public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
+    public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
+    public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
+    public static final int TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E;
+    public static final int TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F;
+    public static final int TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6;
+    public static final int TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7;
+    public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8;
+    public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9;
+    public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA;
+    public static final int TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC;
+    public static final int TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD;
+    public static final int TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 0xD001;
+    public static final int TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = 0xD002;
+    public static final int TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = 0xD005;
+
+    private static final int[] CS_EXPECTED = {
+        TLS_NULL_WITH_NULL_NULL,
+        TLS_RSA_WITH_NULL_MD5,
+        TLS_RSA_WITH_NULL_SHA,
+        TLS_RSA_WITH_RC4_128_MD5,
+        TLS_RSA_WITH_RC4_128_SHA,
+        TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+        TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+        TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+        TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+        TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+        TLS_DH_ANON_WITH_RC4_128_MD5,
+        TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA,
+        TLS_RSA_WITH_AES_128_CBC_SHA,
+        TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+        TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+        TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+        TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+        TLS_DH_ANON_WITH_AES_128_CBC_SHA,
+        TLS_RSA_WITH_AES_256_CBC_SHA,
+        TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+        TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+        TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+        TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+        TLS_DH_ANON_WITH_AES_256_CBC_SHA,
+        TLS_RSA_WITH_NULL_SHA256,
+        TLS_RSA_WITH_AES_128_CBC_SHA256,
+        TLS_RSA_WITH_AES_256_CBC_SHA256,
+        TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+        TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+        TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+        TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+        TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+        TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+        TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+        TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+        TLS_DH_ANON_WITH_AES_128_CBC_SHA256,
+        TLS_DH_ANON_WITH_AES_256_CBC_SHA256,
+        TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+        TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+        TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+        TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+        TLS_AES_128_GCM_SHA256,
+        TLS_AES_256_GCM_SHA384,
+        TLS_CHACHA20_POLY1305_SHA256,
+        TLS_AES_128_CCM_SHA256,
+        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+        TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+        TLS_DHE_RSA_WITH_AES_128_CCM,
+        TLS_DHE_RSA_WITH_AES_256_CCM,
+        TLS_DHE_PSK_WITH_AES_128_CCM,
+        TLS_DHE_PSK_WITH_AES_256_CCM,
+        TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+        TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+        TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+        TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+        TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+        TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
+        TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256
+    };
+
+    /**
+     * TLS supported groups required by TS 33.210
+     */
+    public static final int GROUP_SECP256R1 = 23;
+    public static final int GROUP_SECP384R1 = 24;
+    public static final int GROUP_X25519 = 29;
+    public static final int GROUP_X448 = 30;
+
+    /**
+     * Signature algorithms shall be supported as per TS 33.210
+     */
+    public static final int SIG_RSA_PKCS1_SHA1 = 0X0201;
+    public static final int SIG_ECDSA_SHA1 = 0X0203;
+    public static final int SIG_RSA_PKCS1_SHA256 = 0X0401;
+    public static final int SIG_ECDSA_SECP256R1_SHA256 = 0X0403;
+    public static final int SIG_RSA_PKCS1_SHA256_LEGACY = 0X0420;
+    public static final int SIG_RSA_PKCS1_SHA384 = 0X0501;
+    public static final int SIG_ECDSA_SECP384R1_SHA384 = 0X0503;
+    public static final int SIG_RSA_PKCS1_SHA384_LEGACY = 0X0520;
+    public static final int SIG_RSA_PKCS1_SHA512 = 0X0601;
+    public static final int SIG_ECDSA_SECP521R1_SHA512 = 0X0603;
+    public static final int SIG_RSA_PKCS1_SHA512_LEGACY = 0X0620;
+    public static final int SIG_RSA_PSS_RSAE_SHA256 = 0X0804;
+    public static final int SIG_RSA_PSS_RSAE_SHA384 = 0X0805;
+    public static final int SIG_RSA_PSS_RSAE_SHA512 = 0X0806;
+    public static final int SIG_ECDSA_BRAINPOOLP256R1TLS13_SHA256 = 0X081A;
+    public static final int SIG_ECDSA_BRAINPOOLP384R1TLS13_SHA384 = 0X081B;
+    public static final int SIG_ECDSA_BRAINPOOLP512R1TLS13_SHA512 = 0X081C;
+
+    /**
+     * Returns whether the TLS cipher suite id is supported
+     */
+    public static boolean isTlsCipherSuiteSupported(int csId) {
+        return Arrays.binarySearch(CS_EXPECTED, csId) >= 0;
+    }
+}
diff --git a/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl
new file mode 100644
index 0000000..a71e860
--- /dev/null
+++ b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.gba;
+
+parcelable UaSecurityProtocolIdentifier;
diff --git a/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java
new file mode 100644
index 0000000..c141875
--- /dev/null
+++ b/telephony/java/android/telephony/gba/UaSecurityProtocolIdentifier.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.gba;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.gba.TlsParams.TlsCipherSuite;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+/**
+ * Description of ua security protocol identifier defined in 3GPP TS 33.220 H.2
+ * @hide
+ */
+@SystemApi
+public final class UaSecurityProtocolIdentifier implements Parcelable {
+
+    /**
+     * Organization code defined in 3GPP TS 33.220 H.3
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ORG_"}, value = {
+        ORG_NONE,
+        ORG_3GPP,
+        ORG_3GPP2,
+        ORG_OMA,
+        ORG_GSMA,
+        ORG_LOCAL})
+    public @interface OrganizationCode {}
+
+    /**
+     * Organization octet value for default ua security protocol
+     */
+    public static final int ORG_NONE  = 0;
+    /**
+     * Organization octet value for 3GPP ua security protocol
+     */
+    public static final int ORG_3GPP  = 0x01;
+    /**
+     * Organization octet value for 3GPP2 ua security protocol
+     */
+    public static final int ORG_3GPP2 = 0x02;
+    /**
+     * Organization octet value for OMA ua security protocol
+     */
+    public static final int ORG_OMA   = 0x03;
+    /**
+     * Organization octet value for GSMA ua security protocol
+     */
+    public static final int ORG_GSMA  = 0x04;
+    /**
+     * Internal organization octet value for local/experimental protocols
+     */
+    public static final int ORG_LOCAL = 0xFF;
+
+    /**
+     * 3GPP UA Security Protocol ID defined in 3GPP TS 33.220 H.3
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"UA_SECURITY_PROTOCOL_3GPP_"}, value = {
+        UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
+        UA_SECURITY_PROTOCOL_3GPP_MBMS,
+        UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
+        UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
+        UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
+        UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
+        UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
+        UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI,
+        UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
+        UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER})
+    public @interface UaSecurityProtocol3gpp {}
+
+    /**
+     * Security protocol param according to TS 33.221 as described in TS
+     * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x00".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE = 0;
+
+    /**
+     * Security protocol param according to TS 33.246 for Multimedia
+     * broadcast/Multimedia services (MBMS) as described in TS
+     * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x01".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_MBMS = 1;
+
+    /**
+     * Security protocol param based on HTTP digest authentication
+     * according to TS 24.109 as described in TS 33.220 Annex H. Mapped to
+     * byte stream "0x01,0x00,0x00,0x00,0x02".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION = 2;
+
+    /**
+     * Security protocol param used with HTTP-based security procedures for
+     * Multimedia broadcast/Multimedia services (MBMS) user services
+     * according to TS 26.237 as described in TS 33.220 Annex H.
+     * Mapped to byte stream "0x01,0x00,0x00,0x00,0x03".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS = 3;
+
+    /**
+     * Security protocol param used with SIP-based security procedures for
+     * Multimedia broadcast/Multimedia services (MBMS) user services
+     * according to TS 26.237 as described in TS 33.220 Annex H.
+     * Mapped to byte stream "0x01,0x00,0x00,0x00,0x04".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS = 4;
+
+    /**
+     * Security protocol param used with Generic Push Layer according to TS
+     * 33.224  as described in TS 33.220 Annex H. Mapped to byte stream
+     * "0x01,0x00,0x00,0x00,0x05".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER = 5;
+
+    /**
+     * Security protocol param used for IMS UE to KMS http based message
+     * exchanges according to "IMS media plane security", TS 33.328   as
+     * described in TS 33.220 Annex H. Mapped to byte stream
+     * "0x01,0x00,0x00,0x00,0x06".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE = 6;
+
+    /**
+     * Security protocol param used for Generation of Temporary IP
+     * Multimedia Private Identity (TMPI) according to TS 33.220 Annex B.4
+     * Mapped to byte stream "0x01,0x00,0x00,0x01,0x00".
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI = 0x0100;
+
+    /**
+     * Security protocol param used for Shared key-based UE authentication with
+     * certificate-based NAF authentication, according to TS 33.222 section 5.3,
+     * or Shared key-based mutual authentication between UE and NAF, according to
+     * TS 33.222 section 5.4. Mapped to byte stream "0x01,0x00,0x01,yy,zz".
+     * "yy, zz" is the TLS CipherSuite code.
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT = 0x010000;
+
+    /**
+     * Security protocol param used for Shared key-based UE authentication with
+     * certificate-based NAF authentication, according to TS 33.222 Annex D.
+     * Mapped to byte stream "0x01,0x00,0x02,yy,zz".
+     * "yy, zz" is the TLS CipherSuite code.
+     */
+    public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER = 0x020000;
+
+    private static final int PROTOCOL_SIZE = 5;
+    private static final int[] sUaSp3gppIds = new int[] {
+            UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
+            UA_SECURITY_PROTOCOL_3GPP_MBMS,
+            UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
+            UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
+            UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
+            UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
+            UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
+            UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI,
+            UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
+            UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER};
+
+    private int mOrg;
+    private int mProtocol;
+    private int mTlsCipherSuite;
+
+    private UaSecurityProtocolIdentifier() {}
+
+    private UaSecurityProtocolIdentifier(UaSecurityProtocolIdentifier sp) {
+        mOrg = sp.mOrg;
+        mProtocol = sp.mProtocol;
+        mTlsCipherSuite = sp.mTlsCipherSuite;
+    }
+
+    /**
+     * Returns the byte array representing the ua security protocol
+     */
+    @NonNull
+    public byte[] toByteArray() {
+        byte[] data = new byte[PROTOCOL_SIZE];
+        ByteBuffer buf = ByteBuffer.wrap(data);
+        buf.put((byte) mOrg);
+        buf.putInt(mProtocol | mTlsCipherSuite);
+        return data;
+    }
+
+    /**
+     * Returns the organization code
+     */
+    public @OrganizationCode int getOrg() {
+        return mOrg;
+    }
+
+    /**
+     * Returns the security procotol id
+     *
+     * <p>Note that only 3GPP UA Security Protocols are supported for now
+     */
+    public @UaSecurityProtocol3gpp int getProtocol() {
+        return mProtocol;
+    }
+
+    /**
+     * Returns the TLS cipher suite
+     */
+    public @TlsCipherSuite int getTlsCipherSuite() {
+        return mTlsCipherSuite;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mOrg);
+        out.writeInt(mProtocol);
+        out.writeInt(mTlsCipherSuite);
+    }
+
+    /**
+     * {@link Parcelable.Creator}
+     *
+     */
+    public static final @NonNull Parcelable.Creator<
+            UaSecurityProtocolIdentifier> CREATOR = new Creator<UaSecurityProtocolIdentifier>() {
+                @Nullable
+                @Override
+                public UaSecurityProtocolIdentifier createFromParcel(Parcel in) {
+                    int org = in.readInt();
+                    int protocol = in.readInt();
+                    int cs = in.readInt();
+                    if (org < 0 || protocol < 0 || cs < 0) {
+                        return null;
+                    }
+                    Builder builder = new Builder();
+                    try {
+                        if (org > 0) {
+                            builder.setOrg(org);
+                        }
+                        if (protocol > 0) {
+                            builder.setProtocol(protocol);
+                        }
+                        if (cs > 0) {
+                            builder.setTlsCipherSuite(cs);
+                        }
+                    } catch (IllegalArgumentException e) {
+                        return null;
+                    }
+                    return builder.build();
+                }
+
+                @NonNull
+                @Override
+                public UaSecurityProtocolIdentifier[] newArray(int size) {
+                    return new UaSecurityProtocolIdentifier[size];
+                }
+            };
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "UaSecurityProtocolIdentifier[" + mOrg + " , " + (mProtocol | mTlsCipherSuite) + "]";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof UaSecurityProtocolIdentifier)) {
+            return false;
+        }
+
+        UaSecurityProtocolIdentifier other = (UaSecurityProtocolIdentifier) obj;
+
+        return mOrg == other.mOrg && mProtocol == other.mProtocol
+                && mTlsCipherSuite == other.mTlsCipherSuite;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mOrg, mProtocol, mTlsCipherSuite);
+    }
+
+    private boolean isTlsSupported() {
+        //TODO May update to support non 3gpp protocol in the future
+        if (mOrg == ORG_3GPP && (mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT
+                    || mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Builder class for UaSecurityProtocolIdentifier
+     */
+    public static final class Builder {
+        private final UaSecurityProtocolIdentifier mSp;
+
+        /**
+         * Creates a Builder with default UaSecurityProtocolIdentifier, a.k.a 0x00 00 00 00 00
+         */
+        public Builder() {
+            mSp = new UaSecurityProtocolIdentifier();
+        }
+
+        /**
+         * Creates a Builder from a UaSecurityProtocolIdentifier
+         */
+        public Builder(@NonNull final UaSecurityProtocolIdentifier sp) {
+            Objects.requireNonNull(sp);
+            mSp = new UaSecurityProtocolIdentifier(sp);
+        }
+
+        /**
+         * Sets the organization code
+         *
+         * @param orgCode the organization code with the following value
+         * <ol>
+         * <li>{@link #ORG_NONE} </li>
+         * <li>{@link #ORG_3GPP} </li>
+         * <li>{@link #ORG_3GPP2} </li>
+         * <li>{@link #ORG_OMA} </li>
+         * <li>{@link #ORG_GSMA} </li>
+         * <li>{@link #ORG_LOCAL} </li>
+         * </ol>
+         * @throws IllegalArgumentException if it is not one of the value above.
+         *
+         * <p>Note that this method will reset the security protocol and TLS cipher suite
+         * if they have been set.
+         */
+        @NonNull
+        public Builder setOrg(@OrganizationCode int orgCode) {
+            if (orgCode < ORG_NONE || orgCode > ORG_LOCAL) {
+                throw new IllegalArgumentException("illegal organization code");
+            }
+            mSp.mOrg = orgCode;
+            mSp.mProtocol = 0;
+            mSp.mTlsCipherSuite = 0;
+            return this;
+        }
+
+        /**
+         * Sets the UA security protocol for 3GPP
+         *
+         * @param protocol only 3GPP ua security protocol ID is supported for now, which
+         * is one of the following value
+         * <ol>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_MBMS} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT} </li>
+         * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER} </li>
+         * </ol>
+         * @throws IllegalArgumentException if the protocol is not one of the value above.
+         *
+         * <p>Note that this method will reset TLS cipher suite if it has been set.
+         */
+        @NonNull
+        public Builder setProtocol(@UaSecurityProtocol3gpp int protocol) {
+            //TODO May update to support non 3gpp protocol in the future
+            if (protocol < UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE
+                    || (protocol > UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE
+                    && protocol != UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI
+                    && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT
+                    && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER)
+                    || mSp.mOrg != ORG_3GPP) {
+                throw new IllegalArgumentException("illegal protocol code");
+            }
+            mSp.mProtocol = protocol;
+            mSp.mTlsCipherSuite = 0;
+            return this;
+        }
+
+        /**
+         * Sets the UA security protocol for 3GPP
+         *
+         * @param cs TLS cipher suite value defined by {@link TlsParams#TlsCipherSuite}
+         * @throws IllegalArgumentException if it is not a 3GPP ua security protocol,
+         * the protocol does not support TLS, or does not support the cipher suite.
+         */
+        @NonNull
+        public Builder setTlsCipherSuite(@TlsCipherSuite int cs) {
+            if (!mSp.isTlsSupported()) {
+                throw new IllegalArgumentException("The protocol does not support TLS");
+            }
+            if (!TlsParams.isTlsCipherSuiteSupported(cs)) {
+                throw new IllegalArgumentException("TLS cipher suite is not supported");
+            }
+            mSp.mTlsCipherSuite = cs;
+            return this;
+        }
+
+        /**
+         * Builds the instance of UaSecurityProtocolIdentifier
+         *
+         * @return the built instance of UaSecurityProtocolIdentifier
+         */
+        @NonNull
+        public UaSecurityProtocolIdentifier build() {
+            return new UaSecurityProtocolIdentifier(mSp);
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/gsm/OWNERS b/telephony/java/android/telephony/gsm/OWNERS
new file mode 100644
index 0000000..6aa399d
--- /dev/null
+++ b/telephony/java/android/telephony/gsm/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+amitmahajan@google.com
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index 3558a9b..66281ed 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -62,7 +62,8 @@
     /**
      * This feature tag is being deregistered because the PDN that the IMS registration is on is
      *changing.
-     * All open SIP dialogs need to be closed before the PDN change can proceed.
+     * All open SIP dialogs need to be closed before the PDN change can proceed using
+     * {@link SipDelegateConnection#closeDialog(String)}.
      */
     public static final int DEREGISTERING_REASON_PDN_CHANGE = 3;
 
@@ -73,7 +74,8 @@
      * a user triggered hange, such as data being enabled/disabled.
      * <p>
      * All open SIP dialogs associated with the new deprovisioned feature tag need to be closed
-     * before the IMS registration modification can proceed.
+     * using {@link SipDelegateConnection#closeDialog(String)} before the IMS registration
+     * modification can proceed.
      */
     public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4;
 
@@ -81,8 +83,8 @@
      * This feature tag is deregistering because the SipDelegate associated with this feature tag
      * needs to change its supported feature set.
      * <p>
-     * All open SIP Dialogs associated with this feature tag must be closed before this operation
-     * can proceed.
+     * All open SIP Dialogs associated with this feature tag must be  closed
+     * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
      */
     public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5;
 
@@ -90,8 +92,8 @@
      * This feature tag is deregistering because the SipDelegate is in the process of being
      * destroyed.
      * <p>
-     * All open SIP Dialogs associated with this feature tag must be closed before this operation
-     * can proceed.
+     * All open SIP Dialogs associated with this feature tag must be closed
+     * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
      */
     public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6;
 
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 885ff9b..ad461c0 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -30,7 +30,6 @@
 import android.provider.Settings;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.BinderCacheManager;
-import android.telephony.CarrierConfigManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsRcsController;
@@ -62,9 +61,10 @@
      * been enabled by the user can be queried using {@link RcsUceAdapter#isUceSettingEnabled()}.
      * <p>
      * This intent will always be handled by the system, however the application should only send
-     * this Intent if the carrier supports RCS contact discovery, which can be queried using the key
-     * {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL}. Otherwise, the RCS contact discovery
-     * opt-in dialog will not be shown.
+     * this Intent if the carrier supports bulk RCS contact exchange, which will be true if either
+     * key {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL}
+     * or {@link android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set to true.
+     * Otherwise, the RCS contact discovery opt-in dialog will not be shown.
      * <p>
      * Input: A mandatory {@link Settings#EXTRA_SUB_ID} extra containing the subscription that the
      * setting will be be shown for.
@@ -396,6 +396,7 @@
      * rather the subscription is capable of this service over IMS.
      * @see #isAvailable(int)
      * @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL
+     * @see android.telephony.CarrierConfigManager.Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL
      * @throws ImsException if the IMS service is not available when calling this method.
      * See {@link ImsException#getCode()} for more information on the error codes.
      * @hide
diff --git a/telephony/java/android/telephony/ims/OWNERS b/telephony/java/android/telephony/ims/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 24ae979..f444c62 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.annotation.WorkerThread;
@@ -31,6 +32,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.feature.RcsFeature;
 import android.telephony.ims.stub.ImsConfigImplBase;
@@ -936,6 +938,115 @@
     private int mSubId;
 
     /**
+     * The callback for RCS provisioning changes.
+     */
+    public static class RcsProvisioningCallback {
+        private static class CallbackBinder extends IRcsConfigCallback.Stub {
+
+            private final RcsProvisioningCallback mLocalCallback;
+            private Executor mExecutor;
+
+            private CallbackBinder(RcsProvisioningCallback localCallback) {
+                mLocalCallback = localCallback;
+            }
+
+            @Override
+            public void onConfigurationChanged(byte[] configXml) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mLocalCallback.onConfigurationChanged(configXml));
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            @Override
+            public void onAutoConfigurationErrorReceived(int errorCode, String errorString) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mLocalCallback.onAutoConfigurationErrorReceived(
+                            errorCode, errorString));
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            @Override
+            public void onConfigurationReset() {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mLocalCallback.onConfigurationReset());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            @Override
+            public void onRemoved() {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mLocalCallback.onRemoved());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            private void setExecutor(Executor executor) {
+                mExecutor = executor;
+            }
+        }
+
+        private final CallbackBinder mBinder = new CallbackBinder(this);
+
+        /**
+         * RCS configuration received via OTA provisioning. Configuration may change
+         * due to various triggers defined in GSMA RCC.14 for ACS(auto configuration
+         * server) or other operator defined triggers. If RCS provisioning is already
+         * completed at the time of callback registration, then this method shall be
+         * invoked with the current configuration
+         * @param configXml The RCS configurationXML received OTA.
+         */
+        public void onConfigurationChanged(@NonNull byte[] configXml) {}
+
+        /**
+         * Errors during autoconfiguration connection setup are notified by the
+         * ACS(auto configuration server) client using this interface.
+         * @param errorCode HTTP error received during connection setup defined in
+         * GSMA RCC.14 2.4.3, like {@link java.net.HttpURLConnection#HTTP_UNAUTHORIZED},
+         * {@link java.net.HttpURLConnection#HTTP_FORBIDDEN}, etc.
+         * @param errorString reason phrase received with the error
+         */
+        public void onAutoConfigurationErrorReceived(int errorCode,
+                @NonNull String errorString) {}
+
+        /**
+         * When the previously valid RCS configuration is cleaned up by telephony for
+         * any case like SIM removed, default messaging application changed, etc.,
+         * this method will be invoked to notify the application regarding this change.
+         */
+        public void onConfigurationReset() {}
+
+        /**
+         * When the RCS application is no longer the Default messaging application,
+         * or when the subscription associated with this callback is removed (SIM
+         * removed, ESIM swap,etc...), callback will automatically be removed and
+         * the below method is invoked. There is a possibility that the method is
+         * invoked after the subscription has become inactive
+         */
+        public void onRemoved() {}
+
+        /**@hide*/
+        public final IRcsConfigCallback getBinder() {
+            return mBinder;
+        }
+
+        /**@hide*/
+        public void setExecutor(Executor executor) {
+            mBinder.setExecutor(executor);
+        }
+    }
+
+    /**
      * Create a new {@link ProvisioningManager} for the subscription specified.
      *
      * @param subId The ID of the subscription that this ProvisioningManager will use.
@@ -1207,6 +1318,174 @@
 
     }
 
+    /**
+     * Provides the single registration capability of the device and the carrier.
+     *
+     * <p>This intent only provides the capability and not the current provisioning status of
+     * the RCS VoLTE single registration feature. Only default messaging application may receive
+     * the intent.
+     *
+     * <p>Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to specify the subscription index for which
+     * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
+     * status.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
+            "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
+
+    /**
+     * Integer extra to specify subscription index.
+     */
+    public static final String EXTRA_SUBSCRIPTION_ID =
+            "android.telephony.ims.extra.SUBSCRIPTION_ID";
+
+    /**
+     * Integer extra to specify RCS single registration status
+     *
+     * <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE},
+     * {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of
+     * {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}.
+     */
+    public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
+
+    /**
+     * RCS VoLTE single registration is supported by the device and carrier.
+     */
+    public static final int STATUS_CAPABLE                       = 0;
+
+    /**
+     * RCS VoLTE single registration is not supported by the device.
+     */
+    public static final int STATUS_DEVICE_NOT_CAPABLE            = 0x01;
+
+    /**
+     * RCS VoLTE single registration is not supported by the carrier
+     */
+    public static final int STATUS_CARRIER_NOT_CAPABLE           = 0x01 << 1;
+
+    /**
+     * Provide the client configuration parameters of the RCS application.
+     *
+     * <p>When this application is also the default messaging application, and RCS
+     * provisioning is done using autoconfiguration, then these parameters shall be
+     * sent in the HTTP get request to fetch the RCS provisioning. RCS client
+     * configuration must be provided by the application before registering for the
+     * provisioning status events {@link #registerRcsProvisioningChangedCallback()}
+     * @param rcc RCS client configuration {@link RcsClientConfiguration}
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void setRcsClientConfiguration(
+            @NonNull RcsClientConfiguration rcc) throws ImsException {
+        try {
+            getITelephony().setRcsClientConfiguration(mSubId, rcc);
+        } catch (ServiceSpecificException e) {
+            throw new ImsException(e.getMessage(), e.errorCode);
+        } catch (RemoteException | IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Returns a flag to indicate if the device software and the carrier
+     * have the capability to support RCS Volte single IMS registration.
+     * @return true if this single registration is capable, false otherwise
+     * @throws ImsException If the remote ImsService is not available for
+     * any reason or the subscription associated with this instance is no
+     * longer active. See {@link ImsException#getCode()} for more
+     * information.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
+        try {
+            return getITelephony().isRcsVolteSingleRegistrationCapable(mSubId);
+        } catch (RemoteException | IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+   /**
+     * Registers a new {@link RcsProvisioningCallback} to listen to changes to
+     * RCS provisioning xml.
+     *
+     * <p>RCS application must be the default messaging application and must
+     * have already registered its {@link RcsClientConfiguration} by using
+     * {@link #setRcsClientConfiguration} before it registers the provisioning
+     * callback. If ProvisioningManager has a valid RCS configuration at the
+     * time of callback registration and a reconfiguration is not required
+     * due to RCS client parameters change, then the callback shall be invoked
+     * immediately with the xml.
+     * When the subscription associated with this callback is removed (SIM removed,
+     * ESIM swap,etc...), this callback will automatically be removed.
+     *
+     * @param executor The {@link Executor} to call the callback methods on
+     * @param callback The rcs provisioning callback to be registered.
+     * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback)
+     * @see SubscriptionManager.OnSubscriptionsChangedListener
+     * @throws IllegalArgumentException if the subscription associated with this
+     * callback is not active (SIM is not inserted, ESIM inactive) or the
+     * subscription is invalid.
+     * @throws ImsException if the subscription associated with this callback is
+     * valid, but the {@link ImsService} associated with the subscription is not
+     * available. This can happen if the service crashed, for example.
+     * It shall also throw this exception when the RCS client parameters for the
+     * application are not valid. In that case application must set the client
+     * params (See {@link #setRcsClientConfiguration()}) and re register the
+     * callback.
+     * See {@link ImsException#getCode()} for a more detailed reason.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void registerRcsProvisioningChangedCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull RcsProvisioningCallback callback) throws ImsException {
+        callback.setExecutor(executor);
+        try {
+            getITelephony().registerRcsProvisioningChangedCallback(mSubId, callback.getBinder());
+        } catch (ServiceSpecificException e) {
+            throw new ImsException(e.getMessage(), e.errorCode);
+        } catch (RemoteException | IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Unregister an existing {@link RcsProvisioningCallback}. Application can
+     * unregister when its no longer interested in the provisioning updates
+     * like when a user disables RCS from the UI/settings.
+     * When the subscription associated with this callback is removed (SIM
+     * removed, ESIM swap, etc...), this callback will automatically be
+     * removed. If this method is called for an inactive subscription, it
+     * will result in a no-op.
+     * @param callback The existing {@link RcsProvisioningCallback} to be
+     * removed.
+     * @see #registerRcsProvisioningChangedCallback(RcsClientConfiguration,
+     * Executor, RcsProvisioningCallback) @throws IllegalArgumentException
+     * if the subscription associated with this callback is invalid.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void unregisterRcsProvisioningChangedCallback(
+            @NonNull RcsProvisioningCallback callback) {
+        try {
+            getITelephony().unregisterRcsProvisioningChangedCallback(
+                    mSubId, callback.getBinder());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Reconfiguration triggered by the RCS application. Most likely cause
+     * is the 403 forbidden to a HTTP request.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void triggerRcsReconfiguration() {
+        try {
+            getITelephony().triggerRcsReconfiguration(mSubId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.aidl b/telephony/java/android/telephony/ims/RcsClientConfiguration.aidl
new file mode 100644
index 0000000..a702f0f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+parcelable RcsClientConfiguration;
diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
new file mode 100644
index 0000000..793c377
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.annotation.NonNull;
+import android.annotation.StringDef;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of RCS application related configs.
+ *
+ * @hide
+ */
+@SystemApi
+public final class RcsClientConfiguration implements Parcelable {
+
+    /**@hide*/
+    @StringDef(prefix = "RCS_PROFILE_",
+            value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3})
+    public @interface StringRcsProfile {}
+
+    /**
+     * RCS profile UP 1.0
+     */
+    public static final String RCS_PROFILE_1_0 = "UP_1.0";
+    /**
+     * RCS profile UP 2.3
+     */
+    public static final String RCS_PROFILE_2_3 = "UP_2.3";
+
+    private String mRcsVersion;
+    private String mRcsProfile;
+    private String mClientVendor;
+    private String mClientVersion;
+
+    /**
+     * Create a RcsClientConfiguration object.
+     * Default messaging application must pass a valid configuration object
+     * @param rcsVersion The parameter identifies the RCS version supported
+     * by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
+     * @param rcsProfile Identifies a fixed set of RCS services that are
+     * supported by the client. See {@link #RCS_PROFILE_1_0 } or
+     * {@link #RCS_PROFILE_2_3 }
+     * @param clientVendor Identifies the vendor providing the RCS client.
+     * @param clientVersion Identifies the RCS client version. Refer to GSMA
+     * RCC.07 "client_version" parameter.
+     * Example:client_version=RCSAndrd-1.0
+     */
+    public RcsClientConfiguration(@NonNull String rcsVersion,
+            @NonNull @StringRcsProfile String rcsProfile,
+            @NonNull String clientVendor, @NonNull String clientVersion) {
+        mRcsVersion = rcsVersion;
+        mRcsProfile = rcsProfile;
+        mClientVendor = clientVendor;
+        mClientVersion = clientVersion;
+    }
+
+    /**
+     * Returns RCS version supported.
+     */
+    public @NonNull String getRcsVersion() {
+        return mRcsVersion;
+    }
+
+    /**
+     * Returns RCS profile supported.
+     */
+    public @NonNull @StringRcsProfile String getRcsProfile() {
+        return mRcsProfile;
+    }
+
+    /**
+     * Returns the name of the vendor providing the RCS client.
+     */
+    public @NonNull String getClientVendor() {
+        return mClientVendor;
+    }
+
+    /**
+     * Returns the RCS client version.
+     */
+    public @NonNull String getClientVersion() {
+        return mClientVersion;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeString(mRcsVersion);
+        out.writeString(mRcsProfile);
+        out.writeString(mClientVendor);
+        out.writeString(mClientVersion);
+    }
+
+    /**
+     * {@link Parcelable.Creator}
+     *
+     */
+    public static final @android.annotation.NonNull Parcelable.Creator<
+            RcsClientConfiguration> CREATOR = new Creator<RcsClientConfiguration>() {
+                @Override
+                public RcsClientConfiguration createFromParcel(Parcel in) {
+                    String rcsVersion = in.readString();
+                    String rcsProfile = in.readString();
+                    String clientVendor = in.readString();
+                    String clientVersion = in.readString();
+                    return new RcsClientConfiguration(rcsVersion, rcsProfile,
+                            clientVendor, clientVersion);
+                }
+
+                @Override
+                public RcsClientConfiguration[] newArray(int size) {
+                    return new RcsClientConfiguration[size];
+                }
+            };
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof RcsClientConfiguration)) {
+            return false;
+        }
+
+        RcsClientConfiguration other = (RcsClientConfiguration) obj;
+
+        return mRcsVersion.equals(other.mRcsVersion) && mRcsProfile.equals(other.mRcsProfile)
+                && mClientVendor.equals(other.mClientVendor)
+                && mClientVersion.equals(other.mClientVersion);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mRcsVersion, mRcsProfile, mClientVendor, mClientVersion);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/RcsConfig.aidl b/telephony/java/android/telephony/ims/RcsConfig.aidl
new file mode 100644
index 0000000..cfd93fb
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+parcelable RcsConfig;
diff --git a/telephony/java/android/telephony/ims/RcsConfig.java b/telephony/java/android/telephony/ims/RcsConfig.java
new file mode 100644
index 0000000..07e95cc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsConfig.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.SimInfo;
+import android.text.TextUtils;
+
+import com.android.telephony.Rlog;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * RCS config data and methods to process the config
+ * @hide
+ */
+public final class RcsConfig implements Parcelable {
+    private static final String LOG_TAG = "RcsConfig";
+    private static final boolean DBG = Build.IS_ENG;
+
+    private final HashMap<String, String> mValues = new HashMap<>();
+
+    private RcsConfig(HashMap<String, String> values) {
+        mValues.putAll(values);
+    }
+
+    public RcsConfig(byte[] data) throws IllegalArgumentException {
+        if (data == null || data.length == 0) {
+            throw new IllegalArgumentException("Empty data");
+        }
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+        try {
+            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+            factory.setNamespaceAware(true);
+            XmlPullParser xpp = factory.newPullParser();
+            xpp.setInput(inputStream, null);
+            int eventType = xpp.getEventType();
+            String tag = null;
+            while (eventType != XmlPullParser.END_DOCUMENT) {
+                if (eventType == XmlPullParser.START_TAG) {
+                    tag = xpp.getName().trim();
+                } else if (eventType == XmlPullParser.END_TAG) {
+                    tag = null;
+                } else if (eventType == XmlPullParser.TEXT) {
+                    String value = xpp.getText().trim();
+                    if (!TextUtils.isEmpty(tag) && !TextUtils.isEmpty(value)) {
+                        mValues.put(tag, value);
+                    }
+                }
+                eventType = xpp.next();
+            }
+        } catch (IOException | XmlPullParserException e) {
+            throw new IllegalArgumentException(e);
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                loge("error to close input stream, skip.");
+            }
+        }
+    }
+
+    /**
+     * Retrieve a String value of the config item with the tag
+     *
+     * @param tag The name of the config to retrieve.
+     * @param defaultVal Value to return if the config does not exist.
+     *
+     * @return Returns the config value if it exists, or defaultVal.
+     */
+    public @Nullable String getString(@NonNull String tag, @Nullable String defaultVal) {
+        return mValues.containsKey(tag) ? mValues.get(tag) : defaultVal;
+    }
+
+    /**
+     * Retrieve a int value of the config item with the tag
+     *
+     * @param tag The name of the config to retrieve.
+     * @param defaultVal Value to return if the config does not exist or not valid.
+     *
+     * @return Returns the config value if it exists and is a valid int, or defaultVal.
+     */
+    public int getInteger(@NonNull String tag, int defaultVal) {
+        try {
+            return Integer.parseInt(mValues.get(tag));
+        } catch (NumberFormatException e) {
+            logd("error to getInteger for " + tag + " due to " + e);
+        }
+        return defaultVal;
+    }
+
+    /**
+     * Retrieve a boolean value of the config item with the tag
+     *
+     * @param tag The name of the config to retrieve.
+     * @param defaultVal Value to return if the config does not exist.
+     *
+     * @return Returns the config value if it exists, or defaultVal.
+     */
+    public boolean getBoolean(@NonNull String tag, boolean defaultVal) {
+        if (!mValues.containsKey(tag)) {
+            return defaultVal;
+        }
+        return Boolean.parseBoolean(mValues.get(tag));
+    }
+
+    /**
+     * Check whether the config item exists
+     *
+     * @param tag The name of the config to retrieve.
+     *
+     * @return Returns true if it exists, or false.
+     */
+    public boolean hasConfig(@NonNull String tag) {
+        return mValues.containsKey(tag);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("[RCS Config]");
+        if (DBG) {
+            mValues.forEach((t, v) -> {
+                sb.append("\n");
+                sb.append(t);
+                sb.append(" : ");
+                sb.append(v);
+            });
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof RcsConfig)) {
+            return false;
+        }
+
+        RcsConfig other = (RcsConfig) obj;
+
+        return mValues.equals(other.mValues);
+    }
+
+    @Override
+    public int hashCode() {
+        return mValues.hashCode();
+    }
+
+    /**
+     * compress the gzip format data
+     */
+    public static @Nullable byte[] compressGzip(@NonNull byte[] data) {
+        if (data == null || data.length == 0) {
+            return data;
+        }
+        byte[] out = null;
+        try {
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
+            GZIPOutputStream gzipCompressingStream =
+                    new GZIPOutputStream(outputStream);
+            gzipCompressingStream.write(data);
+            gzipCompressingStream.close();
+            out = outputStream.toByteArray();
+            outputStream.close();
+        } catch (IOException e) {
+            loge("Error to compressGzip due to " + e);
+        }
+        return out;
+    }
+
+    /**
+     * decompress the gzip format data
+     */
+    public static @Nullable byte[] decompressGzip(@NonNull byte[] data) {
+        if (data == null || data.length == 0) {
+            return data;
+        }
+        byte[] out = null;
+        try {
+            ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            GZIPInputStream gzipDecompressingStream =
+                    new GZIPInputStream(inputStream);
+            byte[] buf = new byte[1024];
+            int size = gzipDecompressingStream.read(buf);
+            while (size >= 0) {
+                outputStream.write(buf, 0, size);
+                size = gzipDecompressingStream.read(buf);
+            }
+            gzipDecompressingStream.close();
+            inputStream.close();
+            out = outputStream.toByteArray();
+            outputStream.close();
+        } catch (IOException e) {
+            loge("Error to decompressGzip due to " + e);
+        }
+        return out;
+    }
+
+    /**
+     * save the config to siminfo db. It is only used internally.
+     */
+    public static void updateConfigForSub(@NonNull Context cxt, int subId,
+            @NonNull byte[] config, boolean isCompressed) {
+        //always store gzip compressed data
+        byte[] data = isCompressed ? config : compressGzip(config);
+        ContentValues values = new ContentValues();
+        values.put(SimInfo.COLUMN_RCS_CONFIG, data);
+        cxt.getContentResolver().update(SimInfo.CONTENT_URI, values,
+                SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null);
+    }
+
+    /**
+     * load the config from siminfo db. It is only used internally.
+     */
+    public static @Nullable byte[] loadRcsConfigForSub(@NonNull Context cxt,
+            int subId, boolean isCompressed) {
+
+        byte[] data = null;
+
+        Cursor cursor = cxt.getContentResolver().query(SimInfo.CONTENT_URI, null,
+                SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null, null);
+        try {
+            if (cursor != null && cursor.moveToFirst()) {
+                data = cursor.getBlob(cursor.getColumnIndexOrThrow(SimInfo.COLUMN_RCS_CONFIG));
+            }
+        } catch (Exception e) {
+            loge("error to load rcs config for sub:" + subId + " due to " + e);
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return isCompressed ? data : decompressGzip(data);
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeMap(mValues);
+    }
+
+    /**
+     * {@link Parcelable.Creator}
+     *
+     */
+    public static final @NonNull Parcelable.Creator<RcsConfig>
+            CREATOR = new Creator<RcsConfig>() {
+                @Override
+                public RcsConfig createFromParcel(Parcel in) {
+                    HashMap<String, String> values = in.readHashMap(null);
+                    return values == null ? null : new RcsConfig(values);
+                }
+
+                @Override
+                public RcsConfig[] newArray(int size) {
+                    return new RcsConfig[size];
+                }
+            };
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    private static void logd(String msg) {
+        Rlog.d(LOG_TAG, msg);
+    }
+
+    private static void loge(String msg) {
+        Rlog.e(LOG_TAG, msg);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java
index c3cc1ed..04a772c 100644
--- a/telephony/java/android/telephony/ims/SipDelegateConnection.java
+++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java
@@ -62,6 +62,22 @@
     void notifyMessageReceived(@NonNull String viaTransactionId);
 
     /**
+     * The SIP Dialog associated with the provided Call-ID is being closed and routing resources
+     * associated with the SIP dialog are free to be released.
+     * <p>
+     * Calling this method is also mandatory for situations where the framework IMS stack is waiting
+     * for pending SIP dialogs to be closed before it can perform a handover or apply a provisioning
+     * change. See {@link DelegateRegistrationState} for more information about
+     * the scenarios where this can occur.
+     * <p>
+     * This method will need to be called for each SIP dialog managed by this application when it is
+     * closed.
+     * @param callId The call-ID header value associated with the ongoing SIP Dialog that is
+     *         closing.
+     */
+    void closeDialog(@NonNull String callId);
+
+    /**
      * Notify the SIP delegate that the SIP message has been received from
      * {@link DelegateMessageCallback#onMessageReceived(SipMessage)}, however there was an error
      * processing it.
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 2ec88ff..2e9eb94 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -18,7 +18,9 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
@@ -372,4 +374,37 @@
                     + " into this method");
         }
     }
+
+    /**
+     * Trigger a full network registration as required by receiving a SIP message containing a
+     * permanent error from the network or never receiving a response to a SIP transaction request.
+     *
+     * @param connection The {@link SipDelegateConnection} that was being used when this error was
+     *         received.
+     * @param sipCode The SIP code response associated with the SIP message request that
+     *         triggered this condition.
+     * @param sipReason The SIP reason code associated with the SIP message request that triggered
+     *         this condition. May be {@code null} if there was no reason String provided from the
+     *         network.
+     */
+    public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection,
+            @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) {
+        if (connection == null) {
+            throw new IllegalArgumentException("invalid connection.");
+        }
+        if (connection instanceof SipDelegateConnectionAidlWrapper) {
+            SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) connection;
+            try {
+                IImsRcsController controller = mBinderCache.getBinder();
+                controller.triggerNetworkRegistration(mSubId, w.getSipDelegateBinder(), sipCode,
+                        sipReason);
+            } catch (RemoteException e) {
+                // Connection to telephony died, but this will signal destruction of SipDelegate
+                // eventually anyway, so return.
+            }
+        } else {
+            throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
+                    + " into this method");
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
index 57206c9..5eee389 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
@@ -18,8 +18,9 @@
 package android.telephony.ims.aidl;
 
 import android.os.PersistableBundle;
-
 import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
+import android.telephony.ims.RcsClientConfiguration;
 
 import com.android.ims.ImsConfigListener;
 
@@ -41,4 +42,9 @@
     int setConfigString(int item, String value);
     void updateImsCarrierConfigs(in PersistableBundle bundle);
     void notifyRcsAutoConfigurationReceived(in byte[] config, boolean isCompressed);
+    void notifyRcsAutoConfigurationRemoved();
+    void addRcsConfigCallback(IRcsConfigCallback c);
+    void removeRcsConfigCallback(IRcsConfigCallback c);
+    void triggerRcsReconfiguration();
+    void setRcsClientConfiguration(in RcsClientConfiguration rcc);
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index c6d9a86..3634989 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -67,6 +67,8 @@
             ISipDelegateConnectionStateCallback delegateState,
             ISipDelegateMessageCallback delegateMessage);
     void destroySipDelegate(int subId, ISipDelegate connection, int reason);
+    void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
+            String sipReason);
 
     // Internal commands that should not be made public
     void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
index 4ae0a75..4fd9040 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
@@ -28,4 +28,7 @@
    int getRegistrationTechnology();
    oneway void addRegistrationCallback(IImsRegistrationCallback c);
    oneway void removeRegistrationCallback(IImsRegistrationCallback c);
-}
\ No newline at end of file
+   oneway void triggerFullNetworkRegistration(int sipCode, String sipReason);
+   oneway void triggerUpdateSipDelegateRegistration();
+   oneway void triggerSipDelegateDeregistration();
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
new file mode 100644
index 0000000..5a8973e
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims.aidl;
+
+/**
+ * The callback for RCS provisioning changes.
+ * {@hide}
+ */
+oneway interface IRcsConfigCallback {
+    void onConfigurationChanged(in byte[] config);
+    void onAutoConfigurationErrorReceived(int errorCode, String errorString);
+    void onConfigurationReset();
+    void onRemoved();
+}
+
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
index 5d6766a6..ad75be4 100644
--- a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
@@ -26,7 +26,5 @@
     void sendMessage(in SipMessage sipMessage, long configVersion);
     void notifyMessageReceived(in String viaTransactionId);
     void notifyMessageReceiveError(in String viaTransactionId, int reason);
-
-    // only used by SipDelegate.
     void closeDialog(in String callId);
 }
diff --git a/telephony/java/android/telephony/ims/aidl/OWNERS b/telephony/java/android/telephony/ims/aidl/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index 29ba8e2..a35039b 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -199,6 +199,19 @@
         }
     }
 
+    @Override
+    public void closeDialog(String callId) {
+        try {
+            ISipDelegate conn = getSipDelegateBinder();
+            if (conn == null) {
+                return;
+            }
+            conn.closeDialog(callId);
+        } catch (RemoteException e) {
+            // Nothing to do here, app will eventually get remote death callback.
+        }
+    }
+
     // Also called upon IImsRcsController death (telephony process dies).
     @Override
     public void binderDied() {
diff --git a/telephony/java/android/telephony/ims/compat/OWNERS b/telephony/java/android/telephony/ims/compat/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/compat/feature/OWNERS b/telephony/java/android/telephony/ims/compat/feature/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/feature/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/compat/stub/OWNERS b/telephony/java/android/telephony/ims/compat/stub/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/feature/OWNERS b/telephony/java/android/telephony/ims/feature/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index e757d9f..cc050be 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -23,8 +23,11 @@
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.RcsClientConfiguration;
+import android.telephony.ims.RcsConfig;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.util.Log;
 
 import com.android.ims.ImsConfig;
@@ -202,7 +205,13 @@
         @Override
         public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
                 throws RemoteException {
-            getImsConfigImpl().notifyRcsAutoConfigurationReceived(config, isCompressed);
+            getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+        }
+
+        @Override
+        public void notifyRcsAutoConfigurationRemoved()
+                throws RemoteException {
+            getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
         }
 
         private void notifyImsConfigChanged(int item, int value) throws RemoteException {
@@ -228,6 +237,26 @@
                 notifyImsConfigChanged(item, value);
             }
         }
+
+        @Override
+        public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
+            getImsConfigImpl().addRcsConfigCallback(c);
+        }
+
+        @Override
+        public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
+            getImsConfigImpl().removeRcsConfigCallback(c);
+        }
+
+        @Override
+        public void triggerRcsReconfiguration() throws RemoteException {
+            getImsConfigImpl().triggerAutoConfiguration();
+        }
+
+        @Override
+        public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
+            getImsConfigImpl().setRcsClientConfiguration(rcc);
+        }
     }
 
     /**
@@ -257,6 +286,9 @@
 
     private final RemoteCallbackListExt<IImsConfigCallback> mCallbacks =
             new RemoteCallbackListExt<>();
+    private final RemoteCallbackListExt<IRcsConfigCallback> mRcsCallbacks =
+            new RemoteCallbackListExt<>();
+    private byte[] mRcsConfigData;
     ImsConfigStub mImsConfigStub;
 
     /**
@@ -320,6 +352,50 @@
         });
     }
 
+    private void addRcsConfigCallback(IRcsConfigCallback c) {
+        mRcsCallbacks.register(c);
+        if (mRcsConfigData != null) {
+            try {
+                c.onConfigurationChanged(mRcsConfigData);
+            } catch (RemoteException e) {
+                Log.w(TAG, "dead binder to call onConfigurationChanged, skipping.");
+            }
+        }
+    }
+
+    private void removeRcsConfigCallback(IRcsConfigCallback c) {
+        mRcsCallbacks.unregister(c);
+    }
+
+    private void onNotifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
+        mRcsConfigData = isCompressed ? RcsConfig.decompressGzip(config) : config;
+        // can be null in testing
+        if (mRcsCallbacks != null) {
+            mRcsCallbacks.broadcastAction(c -> {
+                try {
+                    c.onConfigurationChanged(mRcsConfigData);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping.");
+                }
+            });
+        }
+        notifyRcsAutoConfigurationReceived(config, isCompressed);
+    }
+
+    private void onNotifyRcsAutoConfigurationRemoved() {
+        mRcsConfigData = null;
+        if (mRcsCallbacks != null) {
+            mRcsCallbacks.broadcastAction(c -> {
+                try {
+                    c.onConfigurationReset();
+                } catch (RemoteException e) {
+                    Log.w(TAG, "dead binder in notifyRcsAutoConfigurationRemoved, skipping.");
+                }
+            });
+        }
+        notifyRcsAutoConfigurationRemoved();
+    }
+
     /**
      * @hide
      */
@@ -369,6 +445,12 @@
     }
 
     /**
+     * The RCS autoconfiguration XML file is removed or invalid.
+     */
+    public void notifyRcsAutoConfigurationRemoved() {
+    }
+
+    /**
      * Sets the configuration value for this ImsService.
      *
      * @param item an integer key.
@@ -421,4 +503,43 @@
     public void updateImsCarrierConfigs(PersistableBundle bundle) {
         // Base Implementation - Should be overridden
     }
+
+    /**
+     * Default messaging application parameters are sent to the ACS client
+     * using this interface.
+     * @param rcc RCS client configuration {@link RcsClientConfiguration}
+     */
+    public void setRcsClientConfiguration(@NonNull RcsClientConfiguration rcc) {
+        // Base Implementation - Should be overridden
+    }
+
+    /**
+     * Reconfiguration triggered by the RCS application. Most likely cause
+     * is the 403 forbidden to a SIP/HTTP request
+     */
+    public void triggerAutoConfiguration() {
+        // Base Implementation - Should be overridden
+    }
+
+    /**
+     * Errors during autoconfiguration connection setup are notified by the
+     * ACS client using this interface.
+     * @param errorCode HTTP error received during connection setup.
+     * @param errorString reason phrase received with the error
+     */
+    public final void notifyAutoConfigurationErrorReceived(int errorCode,
+            @NonNull String errorString) {
+        // can be null in testing
+        if (mRcsCallbacks == null) {
+            return;
+        }
+        mRcsCallbacks.broadcastAction(c -> {
+            try {
+                //TODO compressed by default?
+                c.onAutoConfigurationErrorReceived(errorCode, errorString);
+            } catch (RemoteException e) {
+                Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
+            }
+        });
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 153d687..088a7e2 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -38,6 +38,9 @@
 /**
  * Controls IMS registration for this ImsService and notifies the framework when the IMS
  * registration for this ImsService has changed status.
+ * <p>
+ * Note: There is no guarantee on the thread that the calls from the framework will be called on. It
+ * is the implementors responsibility to handle moving the calls to a working thread if required.
  * @hide
  */
 @SystemApi
@@ -92,6 +95,21 @@
         public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
             ImsRegistrationImplBase.this.removeRegistrationCallback(c);
         }
+
+        @Override
+        public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
+            ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
+        }
+
+        @Override
+        public void triggerUpdateSipDelegateRegistration() {
+            ImsRegistrationImplBase.this.updateSipDelegateRegistration();
+        }
+
+        @Override
+        public void triggerSipDelegateDeregistration() {
+            ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
+        }
     };
 
     private final RemoteCallbackListExt<IImsRegistrationCallback> mCallbacks =
@@ -133,7 +151,6 @@
      * If the SIP delegate feature tag configuration has changed, then this method will be
      * called in order to let the ImsService know that it can pick up these changes in the IMS
      * registration.
-     * @hide
      */
     public void updateSipDelegateRegistration() {
         // Stub implementation, ImsService should implement this
@@ -150,7 +167,6 @@
      * <p>
      * This should not affect the registration of features managed by the ImsService itself, such as
      * feature tags related to MMTEL registration.
-     * @hide
      */
     public void triggerSipDelegateDeregistration() {
         // Stub implementation, ImsService should implement this
@@ -169,9 +185,8 @@
      *    be carrier specific.
      * @param sipReason The reason associated with the SIP error code. {@code null} if there was no
      *    reason associated with the error.
-     * @hide
      */
-    public void triggerNetworkReregistration(@IntRange(from = 100, to = 699) int sipCode,
+    public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode,
             @Nullable String sipReason) {
         // Stub implementation, ImsService should implement this
     }
diff --git a/telephony/java/android/telephony/ims/stub/OWNERS b/telephony/java/android/telephony/ims/stub/OWNERS
new file mode 100644
index 0000000..0854c5d
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+breadley@google.com
diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java
index d7e7b62..b036b5e 100644
--- a/telephony/java/android/telephony/ims/stub/SipDelegate.java
+++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java
@@ -19,7 +19,9 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.DelegateRegistrationState;
 import android.telephony.ims.ImsService;
+import android.telephony.ims.SipDelegateConnection;
 import android.telephony.ims.SipDelegateImsConfiguration;
 import android.telephony.ims.SipDelegateManager;
 import android.telephony.ims.SipMessage;
@@ -65,10 +67,13 @@
      * The framework is requesting that routing resources associated with the SIP dialog using the
      * provided Call-ID to be cleaned up.
      * <p>
-     * Typically a SIP Dialog close event will be signalled by that dialog receiving a BYE or 200 OK
-     * message, however, in some cases, the framework will request that the ImsService close the
+     * Typically, a SIP Dialog close event will be signalled by that dialog receiving a BYE or
+     * 200 OK message, however, the IMS application will still call
+     * {@link SipDelegateConnection#closeDialog(String)} to signal to the framework that resources
+     * can be released. In some cases, the framework will request that the ImsService close the
      * dialog due to the open dialog holding up an event such as applying a provisioning change or
-     * handing over to another transport type.
+     * handing over to another transport type. See {@link DelegateRegistrationState}.
+     *
      * @param callId The call-ID header value associated with the ongoing SIP Dialog that the
      *         framework is requesting be closed.
      */
diff --git a/telephony/java/android/telephony/mbms/OWNERS b/telephony/java/android/telephony/mbms/OWNERS
new file mode 100644
index 0000000..718e0a2
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+hallliu@google.com
diff --git a/telephony/java/android/telephony/mbms/vendor/OWNERS b/telephony/java/android/telephony/mbms/vendor/OWNERS
new file mode 100644
index 0000000..718e0a2
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 20868
+
+rgreenwalt@google.com
+tgunn@google.com
+hallliu@google.com
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 09f9b42..ce2017b 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -216,5 +216,6 @@
      * @param data authentication challenge data
      * @return challenge response
      */
-    String getIccSimChallengeResponse(int subId, int appType, int authType, String data);
+    String getIccSimChallengeResponse(int subId, int appType, int authType, String data,
+            String callingPackage, String callingFeatureId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5d4fdd0..de4da38 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -37,6 +37,8 @@
 import android.telephony.CellInfo;
 import android.telephony.ClientRequestStats;
 import android.telephony.ThermalMitigationRequest;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+import android.telephony.IBootstrapAuthenticationCallback;
 import android.telephony.IccOpenLogicalChannelResponse;
 import android.telephony.ICellInfoCallback;
 import android.telephony.ModemActivityInfo;
@@ -50,6 +52,7 @@
 import android.telephony.TelephonyHistogram;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.RcsClientConfiguration;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
@@ -57,6 +60,7 @@
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.IBooleanConsumer;
@@ -124,6 +128,15 @@
      */
     boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
 
+    /**
+     * Set the user-set status for enriched calling with call composer.
+     */
+    void setCallComposerStatus(int subId, int status);
+
+    /**
+     * Get the user-set status for enriched calling with call composer.
+     */
+    int getCallComposerStatus(int subId);
 
     /**
      * Supply a pin to unlock the SIM for particular subId.
@@ -1674,10 +1687,19 @@
      * @param slotIndex SIM slot id
      * @param state  State of SIM (power down, power up, pass through)
      * @hide
-     * */
+     */
     void setSimPowerStateForSlot(int slotIndex, int state);
 
     /**
+     * Set SIM card power state.
+     * @param slotIndex SIM slot id
+     * @param state  State of SIM (power down, power up, pass through)
+     * @param callback callback to receive result info
+     * @hide
+     */
+    void setSimPowerStateForSlotWithCallback(int slotIndex, int state, IIntegerConsumer callback);
+
+    /**
      * Returns a list of Forbidden PLMNs from the specified SIM App
      * Returns null if the query fails.
      *
@@ -2273,4 +2295,78 @@
      */
     int sendThermalMitigationRequest(int subId,
             in ThermalMitigationRequest thermalMitigationRequest);
+
+    /**
+     * get the Generic Bootstrapping Architecture authentication keys
+     */
+    void bootstrapAuthenticationRequest(int subId, int appType, in Uri nafUrl,
+            in UaSecurityProtocolIdentifier securityProtocol,
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback);
+
+    /**
+     * Set the GbaService Package Name that Telephony will bind to.
+     */
+    boolean setBoundGbaServiceOverride(int subId, String packageName);
+
+    /**
+     * Return the package name of the currently bound GbaService.
+     */
+    String getBoundGbaService(int subId);
+
+    /**
+     * Set the release time for telephony to unbind GbaService.
+     */
+    boolean setGbaReleaseTimeOverride(int subId, int interval);
+
+    /**
+     * Return the release time for telephony to unbind GbaService.
+     */
+    int getGbaReleaseTime(int subId);
+
+    /**
+     * Provide the client configuration parameters of the RCS application.
+     */
+    void setRcsClientConfiguration(int subId, in RcsClientConfiguration rcc);
+
+    /**
+     * return value to indicate whether the device and the carrier can support RCS VoLTE
+     * single registration.
+     */
+    boolean isRcsVolteSingleRegistrationCapable(int subId);
+
+    /**
+     * Register RCS provisioning callback.
+     */
+    void registerRcsProvisioningChangedCallback(int subId,
+            IRcsConfigCallback callback);
+
+    /**
+     * Unregister RCS provisioning callback.
+     */
+    void unregisterRcsProvisioningChangedCallback(int subId, IRcsConfigCallback callback);
+
+    /**
+     * trigger RCS reconfiguration.
+     */
+    void triggerRcsReconfiguration(int subId);
+
+    /**
+     * Overrides the config of RCS VoLTE single registration enabled for the device.
+     */
+    void setDeviceSingleRegistrationEnabledOverride(String enabled);
+
+    /**
+     * Gets the config of RCS VoLTE single registration enabled for the device.
+     */
+    boolean getDeviceSingleRegistrationEnabled();
+
+    /**
+     * Overrides the config of RCS VoLTE single registration enabled for the carrier/subscription.
+     */
+    boolean setCarrierSingleRegistrationEnabledOverride(int subId, String enabled);
+
+    /**
+     * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
+     */
+    boolean getCarrierSingleRegistrationEnabled(int subId);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 42dee0e..76243a5 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -522,6 +522,8 @@
     int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
     int RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES = 220;
     int RIL_REQUEST_SET_DATA_THROTTLING = 221;
+    int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP = 222;
+    int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP = 223;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/test-mock/src/android/test/mock/OWNERS b/test-mock/src/android/test/mock/OWNERS
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/test-mock/src/android/test/mock/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/tests/ActivityManagerPerfTests/OWNERS b/tests/ActivityManagerPerfTests/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/tests/AmSlam/OWNERS b/tests/AmSlam/OWNERS
new file mode 100644
index 0000000..72c0a9e
--- /dev/null
+++ b/tests/AmSlam/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/tests/BatteryStatsPerfTest/OWNERS b/tests/BatteryStatsPerfTest/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/tests/BatteryStatsPerfTest/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/tests/BatteryWaster/OWNERS b/tests/BatteryWaster/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/tests/BatteryWaster/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/tests/BlobStoreTestUtils/OWNERS b/tests/BlobStoreTestUtils/OWNERS
new file mode 100644
index 0000000..65bb6b8
--- /dev/null
+++ b/tests/BlobStoreTestUtils/OWNERS
@@ -0,0 +1 @@
+include /apex/blobstore/OWNERS
diff --git a/tests/Camera2Tests/OWNERS b/tests/Camera2Tests/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/tests/Camera2Tests/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/tests/CanvasCompare/OWNERS b/tests/CanvasCompare/OWNERS
new file mode 100644
index 0000000..c88a9f8
--- /dev/null
+++ b/tests/CanvasCompare/OWNERS
@@ -0,0 +1 @@
+include /libs/hwui/OWNERS
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/Compatibility/OWNERS b/tests/Compatibility/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/tests/Compatibility/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/tests/DozeTest/OWNERS b/tests/DozeTest/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/tests/DozeTest/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/tests/FixVibrateSetting/OWNERS b/tests/FixVibrateSetting/OWNERS
new file mode 100644
index 0000000..cc63ceb
--- /dev/null
+++ b/tests/FixVibrateSetting/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/vibrator/OWNERS
diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS
new file mode 100644
index 0000000..f35a318
--- /dev/null
+++ b/tests/FlickerTests/OWNERS
@@ -0,0 +1,2 @@
+include /services/core/java/com/android/server/wm/OWNERS
+natanieljr@google.com
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index bb03237..e4db55e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -48,11 +48,12 @@
 }
 
 fun WmAssertion.visibleWindowsShownMoreThanOneConsecutiveEntry(
+    ignoreWindows: List<String> = emptyList(),
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("visibleWindowShownMoreThanOneConsecutiveEntry", bugId, enabled) {
-        this.visibleWindowsShownMoreThanOneConsecutiveEntry()
+    all("visibleWindowsShownMoreThanOneConsecutiveEntry", bugId, enabled) {
+        this.visibleWindowsShownMoreThanOneConsecutiveEntry(ignoreWindows)
     }
 }
 
@@ -79,16 +80,39 @@
     }
 }
 
-fun WmAssertion.windowAlwaysVisible(
+fun WmAssertion.wallpaperWindowBecomesInvisible(
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("wallpaperWindowBecomesInvisible", bugId, enabled) {
+        this.showsBelowAppWindow("Wallpaper")
+                .then()
+                .hidesBelowAppWindow("Wallpaper")
+    }
+}
+
+fun WmAssertion.appWindowAlwaysVisibleOnTop(
     packageName: String,
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("windowAlwaysVisible", bugId, enabled) {
+    all("appWindowAlwaysVisibleOnTop", bugId, enabled) {
         this.showsAppWindowOnTop(packageName)
     }
 }
 
+fun WmAssertion.appWindowBecomesVisible(
+    appName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("appWindowBecomesVisible", bugId, enabled) {
+        this.hidesAppWindow(appName)
+                .then()
+                .showsAppWindow(appName)
+    }
+}
+
 @JvmOverloads
 fun LayersAssertion.noUncoveredRegions(
     beginRotation: Int,
@@ -204,11 +228,24 @@
 }
 
 fun LayersAssertion.visibleLayersShownMoreThanOneConsecutiveEntry(
+    ignoreLayers: List<String> = emptyList(),
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
     all("visibleLayersShownMoreThanOneConsecutiveEntry", bugId, enabled) {
-        this.visibleLayersShownMoreThanOneConsecutiveEntry()
+        this.visibleLayersShownMoreThanOneConsecutiveEntry(ignoreLayers)
+    }
+}
+
+fun LayersAssertion.appLayerReplacesWallpaperLayer(
+    appName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("appLayerReplacesWallpaperLayer", bugId, enabled) {
+        this.showsLayer("Wallpaper")
+                .then()
+                .replaceVisibleLayer("Wallpaper", appName)
     }
 }
 
@@ -234,6 +271,30 @@
     }
 }
 
+fun LayersAssertion.layerBecomesVisible(
+    packageName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("layerBecomesVisible", bugId, enabled) {
+        this.hidesLayer(packageName)
+                .then()
+                .showsLayer(packageName)
+    }
+}
+
+fun LayersAssertion.layerBecomesInvisible(
+    packageName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("layerBecomesInvisible", bugId, enabled) {
+        this.showsLayer(packageName)
+                .then()
+                .hidesLayer(packageName)
+    }
+}
+
 fun EventLogAssertion.focusChanges(
     vararg windows: String,
     bugId: Int = 0,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index f4de36e..3565ca4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -22,6 +22,7 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.UiDevice
 import androidx.test.uiautomator.Until
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import org.junit.Assert
 
 open class ImeAppHelper(
@@ -38,7 +39,7 @@
         Assert.assertNotNull("Text field not found, this usually happens when the device " +
                 "was left in an unknown state (e.g. in split screen)", editText)
         editText.click()
-        if (!device.waitForIME()) {
+        if (!WindowManagerStateHelper().waitImeWindowShown()) {
             Assert.fail("IME did not appear")
         }
     }
@@ -46,6 +47,8 @@
     open fun closeIME(device: UiDevice) {
         device.pressBack()
         // Using only the AccessibilityInfo it is not possible to identify if the IME is active
-        device.waitForIdle(1000)
+        if (!WindowManagerStateHelper().waitImeWindowGone()) {
+            Assert.fail("IME did not close")
+        }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index a73264d..b341e62 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -27,6 +27,8 @@
 import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -66,8 +68,10 @@
                     withTag { buildTestTag("imeToAppAutoOpen", testApp, configuration) }
                     repeat { configuration.repetitions }
                     setup {
-                        eachRun {
+                        test {
                             device.wakeUpAndGoToHomeScreen()
+                        }
+                        eachRun {
                             this.setRotation(configuration.startRotation)
                             testApp.open()
                             testApp.openIME(device)
@@ -80,14 +84,15 @@
                         }
                     }
                     transitions {
-                        device.pressBack()
-                        device.waitForIdle()
+                        testApp.closeIME(device)
                     }
                     assertions {
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
-                            imeAppWindowIsAlwaysVisible(testApp, bugId = 141458352)
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(listOf("InputMethod"))
+
+                            imeAppWindowIsAlwaysVisible(testApp)
                         }
 
                         layersTrace {
@@ -96,8 +101,10 @@
                             noUncoveredRegions(configuration.startRotation)
                             navBarLayerRotatesAndScales(configuration.startRotation)
                             statusBarLayerRotatesScales(configuration.startRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry()
+
                             imeLayerBecomesInvisible(bugId = 141458352)
-                            imeAppLayerIsAlwaysVisible(testApp, bugId = 141458352)
+                            imeAppLayerIsAlwaysVisible(testApp)
                         }
                     }
                 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index 6cc2e22..51a4ca8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -27,6 +27,8 @@
 import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -68,8 +70,10 @@
                     }
                     repeat { configuration.repetitions }
                     setup {
-                        eachRun {
+                        test {
                             device.wakeUpAndGoToHomeScreen()
+                        }
+                        eachRun {
                             this.setRotation(configuration.startRotation)
                             testApp.open()
                             testApp.openIME(device)
@@ -89,6 +93,8 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
                             imeWindowBecomesInvisible(bugId = 141458352)
                             imeAppWindowBecomesInvisible(testApp, bugId = 157449248)
                         }
@@ -100,10 +106,14 @@
                                 Surface.ROTATION_0, bugId = 140855415)
                             statusBarLayerRotatesScales(configuration.startRotation,
                                 Surface.ROTATION_0)
-                            navBarLayerIsAlwaysVisible(enabled = false)
-                            statusBarLayerIsAlwaysVisible(enabled = false)
+                            navBarLayerIsAlwaysVisible(
+                                    enabled = Surface.ROTATION_0 == configuration.startRotation)
+                            statusBarLayerIsAlwaysVisible(
+                                    enabled = Surface.ROTATION_0 == configuration.startRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
                             imeLayerBecomesInvisible(bugId = 141458352)
-                            imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
+                            imeAppLayerBecomesInvisible(testApp)
                         }
                     }
                 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index 136cf86..663d456 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -31,6 +31,8 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -65,8 +67,10 @@
                     withTestName { buildTestTag("imeToApp", testApp, configuration) }
                     repeat { configuration.repetitions }
                     setup {
-                        eachRun {
+                        test {
                             device.wakeUpAndGoToHomeScreen()
+                        }
+                        eachRun {
                             this.setRotation(configuration.startRotation)
                             testApp.open()
                             testApp.openIME(device)
@@ -79,13 +83,14 @@
                         }
                     }
                     transitions {
-                        device.pressBack()
-                        device.waitForIdle()
+                        testApp.closeIME(device)
                     }
                     assertions {
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(listOf("InputMethod"))
+
                             imeAppWindowIsAlwaysVisible(testApp)
                         }
 
@@ -95,6 +100,8 @@
                             noUncoveredRegions(configuration.startRotation)
                             navBarLayerRotatesAndScales(configuration.startRotation)
                             statusBarLayerRotatesScales(configuration.startRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry()
+
                             imeLayerBecomesInvisible(enabled = false)
                             imeAppLayerIsAlwaysVisible(testApp)
                         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index 8d9881e..bfe5264 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -33,6 +33,8 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -95,6 +97,8 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
                             imeWindowBecomesInvisible()
                             imeAppWindowBecomesInvisible(testApp)
                         }
@@ -106,10 +110,14 @@
                                 Surface.ROTATION_0, bugId = 140855415)
                             statusBarLayerRotatesScales(configuration.startRotation,
                                 Surface.ROTATION_0)
-                            navBarLayerIsAlwaysVisible(enabled = false)
-                            statusBarLayerIsAlwaysVisible(enabled = false)
+                            navBarLayerIsAlwaysVisible(
+                                    enabled = Surface.ROTATION_0 == configuration.startRotation)
+                            statusBarLayerIsAlwaysVisible(
+                                    enabled = Surface.ROTATION_0 == configuration.startRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
+
                             imeLayerBecomesInvisible(bugId = 153739621)
-                            imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
+                            imeAppLayerBecomesInvisible(testApp)
                         }
                     }
                 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 5798624..aa34b5d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -65,6 +65,17 @@
     }
 }
 
+fun WmAssertion.imeWindowBecomesVisible(
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("imeWindowBecomesVisible", bugId, enabled) {
+        this.hidesNonAppWindow(IME_WINDOW_TITLE)
+                .then()
+                .showsNonAppWindow(IME_WINDOW_TITLE)
+    }
+}
+
 fun WmAssertion.imeWindowBecomesInvisible(
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
@@ -76,6 +87,18 @@
     }
 }
 
+fun WmAssertion.imeAppWindowBecomesVisible(
+    windowName: String,
+    bugId: Int = 0,
+    enabled: Boolean = bugId == 0
+) {
+    all("imeAppWindowBecomesVisible", bugId, enabled) {
+        this.hidesAppWindow(windowName)
+                .then()
+                .showsAppWindow(windowName)
+    }
+}
+
 fun WmAssertion.imeAppWindowBecomesInvisible(
     testApp: IAppHelper,
     bugId: Int = 0,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index 5767a94..28a8bd3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -30,7 +30,11 @@
 import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
+import com.android.server.wm.flicker.layerAlwaysVisible
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -54,8 +58,6 @@
     flickerSpec: Flicker
 ) : FlickerTestRunner(testName, flickerSpec) {
     companion object {
-        private const val IME_WINDOW_TITLE = "InputMethod"
-
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): List<Array<Any>> {
@@ -89,13 +91,10 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+                            visibleWindowsShownMoreThanOneConsecutiveEntry()
 
-                            all("imeWindowBecomesVisible") {
-                                this.skipUntilFirstAssertion()
-                                    .hidesNonAppWindow(IME_WINDOW_TITLE)
-                                    .then()
-                                    .showsNonAppWindow(IME_WINDOW_TITLE)
-                            }
+                            imeWindowBecomesVisible()
+                            appWindowAlwaysVisibleOnTop(testApp.`package`)
                         }
 
                         layersTrace {
@@ -104,8 +103,10 @@
                             noUncoveredRegions(configuration.startRotation)
                             navBarLayerRotatesAndScales(configuration.startRotation)
                             statusBarLayerRotatesScales(configuration.startRotation)
+                            visibleLayersShownMoreThanOneConsecutiveEntry()
 
                             imeLayerBecomesVisible()
+                            layerAlwaysVisible(testApp.`package`)
                         }
                     }
                 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 7bd96f5..c7114da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -23,14 +23,27 @@
 import com.android.server.wm.flicker.Flicker
 import com.android.server.wm.flicker.FlickerTestRunner
 import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.hasWindow
+import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
+import com.android.server.wm.flicker.noUncoveredRegions
 import com.android.server.wm.flicker.repetitions
 import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.testapp.ActivityOptions
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -54,8 +67,9 @@
         fun getParams(): List<Array<Any>> {
             val instrumentation = InstrumentationRegistry.getInstrumentation()
             val testApp = ImeAppAutoFocusHelper(instrumentation)
+            val testAppComponentName = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
 
-            return FlickerTestRunnerFactory(instrumentation, repetitions = 10)
+            return FlickerTestRunnerFactory(instrumentation, repetitions = 5)
                     .buildTest { configuration ->
                         withTestName { buildTestTag("reOpenImeAutoFocus", testApp, configuration) }
                         repeat { configuration.repetitions }
@@ -73,7 +87,7 @@
                         }
                         transitions {
                             device.reopenAppFromOverview()
-                            device.hasWindow(testApp.getPackage())
+                            WindowManagerStateHelper().waitForFullScreenApp(testAppComponentName)
                         }
                         teardown {
                             eachRun {
@@ -84,6 +98,35 @@
                                 this.setRotation(Surface.ROTATION_0)
                             }
                         }
+                        assertions {
+                            windowManagerTrace {
+                                navBarWindowIsAlwaysVisible()
+                                statusBarWindowIsAlwaysVisible()
+                                visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+                                imeWindowBecomesVisible()
+                                imeAppWindowBecomesVisible(testAppComponentName.className)
+                                wallpaperWindowBecomesInvisible()
+                            }
+
+                            layersTrace {
+                                noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation,
+                                        bugId = 141361128)
+                                navBarLayerRotatesAndScales(Surface.ROTATION_0,
+                                        configuration.endRotation)
+                                statusBarLayerRotatesScales(Surface.ROTATION_0,
+                                        configuration.endRotation)
+                                statusBarLayerIsAlwaysVisible(
+                                        enabled = Surface.ROTATION_0 == configuration.endRotation)
+                                navBarLayerIsAlwaysVisible(
+                                        enabled = Surface.ROTATION_0 == configuration.endRotation)
+                                visibleLayersShownMoreThanOneConsecutiveEntry(
+                                        enabled = Surface.ROTATION_0 == configuration.endRotation)
+
+                                imeLayerBecomesVisible()
+                                appLayerReplacesWallpaperLayer(testAppComponentName.className)
+                            }
+                        }
                     }
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
index 72efdb1..71920f6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
@@ -17,20 +17,8 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.helpers.IAppHelper
-import com.android.server.wm.flicker.dsl.LayersAssertion
 import com.android.server.wm.flicker.dsl.WmAssertion
 
-fun WmAssertion.wallpaperWindowBecomesInvisible(
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("wallpaperWindowBecomesInvisible", bugId, enabled) {
-        this.showsBelowAppWindow("Wallpaper")
-                .then()
-                .hidesBelowAppWindow("Wallpaper")
-    }
-}
-
 fun WmAssertion.appWindowReplacesLauncherAsTopWindow(
     testApp: IAppHelper,
     bugId: Int = 0,
@@ -41,16 +29,4 @@
                 .then()
                 .showsAppWindowOnTop("Snapshot", testApp.getPackage())
     }
-}
-
-fun LayersAssertion.appLayerReplacesWallpaperLayer(
-    testApp: IAppHelper,
-    bugId: Int = 0,
-    enabled: Boolean = bugId == 0
-) {
-    all("appLayerReplacesWallpaperLayer", bugId, enabled) {
-        this.showsLayer("Wallpaper")
-                .then()
-                .replaceVisibleLayer("Wallpaper", testApp.getPackage())
-    }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 686ddcb..d81c24d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -40,6 +40,8 @@
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -107,7 +109,7 @@
                             statusBarLayerIsAlwaysVisible(enabled = false)
                             visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174541970)
 
-                            appLayerReplacesWallpaperLayer(testApp)
+                            appLayerReplacesWallpaperLayer(testApp.`package`)
                         }
 
                         eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 5aef314..1b682c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -29,7 +29,6 @@
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.hasWindow
 import com.android.server.wm.flicker.helpers.buildTestTag
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
@@ -42,6 +41,10 @@
 import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -83,7 +86,9 @@
                         }
                         transitions {
                             device.reopenAppFromOverview()
-                            device.hasWindow(testApp.getPackage())
+                            WindowManagerStateHelper().waitForFullScreenApp(
+                                    ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
+                            )
                         }
                         teardown {
                             test {
@@ -115,7 +120,7 @@
                                 visibleLayersShownMoreThanOneConsecutiveEntry(
                                         enabled = Surface.ROTATION_0 == configuration.endRotation)
 
-                                appLayerReplacesWallpaperLayer(testApp)
+                                appLayerReplacesWallpaperLayer(testApp.`package`)
                             }
 
                             eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 9b4223a..3703d9c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -40,6 +40,8 @@
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
 import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -112,7 +114,7 @@
                             visibleLayersShownMoreThanOneConsecutiveEntry(
                                     enabled = Surface.ROTATION_0 == configuration.endRotation)
 
-                            appLayerReplacesWallpaperLayer(testApp)
+                            appLayerReplacesWallpaperLayer(testApp.`package`)
                         }
 
                         eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index a1a7102..120354b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -30,7 +30,7 @@
 import com.android.server.wm.flicker.FlickerTestRunnerFactory
 import com.android.server.wm.flicker.endRotation
 import com.android.server.wm.flicker.focusDoesNotChange
-import com.android.server.wm.flicker.windowAlwaysVisible
+import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
 import com.android.server.wm.flicker.layerAlwaysVisible
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.buildTestTag
@@ -146,7 +146,7 @@
                         navBarWindowIsAlwaysVisible(bugId = 140855415)
                         statusBarWindowIsAlwaysVisible(bugId = 140855415)
                         visibleWindowsShownMoreThanOneConsecutiveEntry()
-                        windowAlwaysVisible(configuration.intentPackageName)
+                        appWindowAlwaysVisibleOnTop(configuration.intentPackageName)
                     }
 
                     layersTrace {
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
index 1899411..f167e95 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -23,4 +23,10 @@
     public static final ComponentName SEAMLESS_ACTIVITY_COMPONENT_NAME =
             new ComponentName("com.android.server.wm.flicker.testapp",
                     "com.android.server.wm.flicker.testapp.SeamlessRotationActivity");
+    public static final ComponentName IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
+            new ComponentName("com.android.server.wm.flicker.testapp",
+                    "com.android.server.wm.flicker.testapp.ImeActivityAutoFocus");
+    public static final ComponentName SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
+            new ComponentName("com.android.server.wm.flicker.testapp",
+                    "com.android.server.wm.flicker.testapp.SimpleActivity");
 }
diff --git a/tests/HugeBackup/OWNERS b/tests/HugeBackup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/tests/HugeBackup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/tests/HwAccelerationTest/OWNERS b/tests/HwAccelerationTest/OWNERS
new file mode 100644
index 0000000..c88a9f8
--- /dev/null
+++ b/tests/HwAccelerationTest/OWNERS
@@ -0,0 +1 @@
+include /libs/hwui/OWNERS
diff --git a/tests/Input/OWNERS b/tests/Input/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/tests/Input/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/tests/JobSchedulerPerfTests/OWNERS b/tests/JobSchedulerPerfTests/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/tests/JobSchedulerPerfTests/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/tests/JobSchedulerTestApp/OWNERS b/tests/JobSchedulerTestApp/OWNERS
new file mode 100644
index 0000000..6f207fb1
--- /dev/null
+++ b/tests/JobSchedulerTestApp/OWNERS
@@ -0,0 +1 @@
+include /apex/jobscheduler/OWNERS
diff --git a/tests/LocationTracker/OWNERS b/tests/LocationTracker/OWNERS
new file mode 100644
index 0000000..5ac6028
--- /dev/null
+++ b/tests/LocationTracker/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/location/OWNERS
diff --git a/tests/LowStorageTest/OWNERS b/tests/LowStorageTest/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/tests/LowStorageTest/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/PackageWatchdog/OWNERS b/tests/PackageWatchdog/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/PackageWatchdog/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/PackageWatchdog/src/com/android/server/OWNERS b/tests/PackageWatchdog/src/com/android/server/OWNERS
new file mode 100644
index 0000000..5cf4dcf
--- /dev/null
+++ b/tests/PackageWatchdog/src/com/android/server/OWNERS
@@ -0,0 +1 @@
+per-file PackageWatchdogTest.java = file:/services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/PlatformCompatGating/OWNERS b/tests/PlatformCompatGating/OWNERS
new file mode 100644
index 0000000..f8c3520
--- /dev/null
+++ b/tests/PlatformCompatGating/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/compat/OWNERS
diff --git a/tests/RollbackTest/OWNERS b/tests/RollbackTest/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/RollbackTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS
new file mode 100644
index 0000000..816bc6b
--- /dev/null
+++ b/tests/SoundTriggerTests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/media/soundtrigger/OWNERS
diff --git a/tests/StagedInstallTest/OWNERS b/tests/StagedInstallTest/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/tests/StagedInstallTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/tests/StatusBar/OWNERS b/tests/StatusBar/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/tests/StatusBar/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/tests/TaskOrganizerTest/OWNERS b/tests/TaskOrganizerTest/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/TaskOrganizerTest/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/TelephonyCommonTests/OWNERS b/tests/TelephonyCommonTests/OWNERS
new file mode 100644
index 0000000..640baf2
--- /dev/null
+++ b/tests/TelephonyCommonTests/OWNERS
@@ -0,0 +1 @@
+include /telephony/OWNERS
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
index 8013bd8..7ee19fb 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -46,6 +46,7 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Telephony;
 import android.telephony.TelephonyManager;
 
@@ -103,6 +104,7 @@
     @Mock private TelephonyManager mTelephonyManager;
     @Mock private RoleManager mRoleManager;
     @Mock private PackageManager mPackageManager;
+    @Mock private UserManager mUserManager;
     @Mock private AppOpsManager mAppOpsManager;
 
     @Before
@@ -112,6 +114,7 @@
         when(mContext.getSystemService(Context.ROLE_SERVICE)).thenReturn(mRoleManager);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
         when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
         when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);
 
@@ -132,6 +135,8 @@
         when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true);
         when(mRoleManager.getSmsRoleHolder(anyInt()))
                 .thenReturn(TEST_COMPONENT_NAME.getPackageName());
+        when(mUserManager.getUserHandles(true))
+                .thenReturn(Collections.singletonList(UserHandle.SYSTEM));
 
         for (String opStr : APP_OPS_TO_CHECK) {
             when(mAppOpsManager.unsafeCheckOp(
diff --git a/tests/UsageReportingTest/OWNERS b/tests/UsageReportingTest/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageReportingTest/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsageStatsPerfTests/OWNERS b/tests/UsageStatsPerfTests/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageStatsPerfTests/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsageStatsTest/OWNERS b/tests/UsageStatsTest/OWNERS
new file mode 100644
index 0000000..d3227de
--- /dev/null
+++ b/tests/UsageStatsTest/OWNERS
@@ -0,0 +1 @@
+include /services/usage/OWNERS
diff --git a/tests/UsbHostExternalManagmentTest/OWNERS b/tests/UsbHostExternalManagmentTest/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbHostExternalManagmentTest/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/UsbManagerTests/OWNERS b/tests/UsbManagerTests/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbManagerTests/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/UsbTests/OWNERS b/tests/UsbTests/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/tests/UsbTests/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/tests/VoiceInteraction/OWNERS b/tests/VoiceInteraction/OWNERS
new file mode 100644
index 0000000..ef1061b
--- /dev/null
+++ b/tests/VoiceInteraction/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/voice/OWNERS
diff --git a/tests/WindowAnimationJank/OWNERS b/tests/WindowAnimationJank/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/WindowAnimationJank/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/WindowInsetsTests/OWNERS b/tests/WindowInsetsTests/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/WindowInsetsTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/backup/OWNERS b/tests/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/tests/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS
new file mode 100644
index 0000000..aa87958
--- /dev/null
+++ b/tests/benchmarks/src/com/android/server/net/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index 60308e3..1eaf30c 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -68,8 +68,8 @@
 
     private static final String V4 = "192.0.2.1";
     private static final String V6 = "2001:db8::1";
-    private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
-    private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
+    private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4);
+    private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6);
 
     @Test
     public void testConstants() {
@@ -131,10 +131,10 @@
             ipv6Loopback = new LinkAddress(addrs.get(0));
         }
 
-        assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
+        assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress());
         assertEquals(8, ipv4Loopback.getPrefixLength());
 
-        assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
+        assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress());
         assertEquals(128, ipv6Loopback.getPrefixLength());
 
         // Null addresses are rejected.
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/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 2a24d1a..3d4dc4d 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -29,7 +29,7 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -38,7 +38,6 @@
 import android.net.NetworkAgent;
 import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
 import android.net.NetworkProvider;
 import android.net.NetworkSpecifier;
 import android.net.SocketKeepalive;
@@ -53,9 +52,9 @@
 import com.android.testutils.TestableNetworkCallback;
 
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
-    private final NetworkInfo mNetworkInfo;
     private final NetworkCapabilities mNetworkCapabilities;
     private final HandlerThread mHandlerThread;
     private final Context mContext;
@@ -63,6 +62,7 @@
 
     private final ConditionVariable mDisconnected = new ConditionVariable();
     private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
+    private final AtomicBoolean mConnected = new AtomicBoolean(false);
     private int mScore;
     private NetworkAgent mNetworkAgent;
     private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
@@ -76,7 +76,6 @@
             NetworkCapabilities ncTemplate, Context context) throws Exception {
         final int type = transportToLegacyType(transport);
         final String typeName = ConnectivityManager.getNetworkTypeName(type);
-        mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
         mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities();
         mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
         mNetworkCapabilities.addTransportType(transport);
@@ -108,22 +107,29 @@
         mHandlerThread = new HandlerThread(mLogTag);
         mHandlerThread.start();
 
-        mNetworkAgent = makeNetworkAgent(linkProperties);
+        mNetworkAgent = makeNetworkAgent(linkProperties, type, typeName);
     }
 
-    protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
+    protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
+            final int type, final String typeName)
             throws Exception {
-        return new InstrumentedNetworkAgent(this, linkProperties);
+        return new InstrumentedNetworkAgent(this, linkProperties, type, typeName);
     }
 
     public static class InstrumentedNetworkAgent extends NetworkAgent {
         private final NetworkAgentWrapper mWrapper;
+        private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider";
 
-        public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) {
-            super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag,
-                    wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore,
-                    new NetworkAgentConfig(), NetworkProvider.ID_NONE);
+        public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
+                final int type, final String typeName) {
+            super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag,
+                    wrapper.mNetworkCapabilities, lp, wrapper.mScore,
+                    new NetworkAgentConfig.Builder()
+                            .setLegacyType(type).setLegacyTypeName(typeName).build(),
+                    new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(),
+                            PROVIDER_NAME));
             mWrapper = wrapper;
+            register();
         }
 
         @Override
@@ -212,10 +218,12 @@
     }
 
     public void connect() {
-        assertNotEquals("MockNetworkAgents can only be connected once",
-                mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
-        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
-        mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+        if (!mConnected.compareAndSet(false /* expect */, true /* update */)) {
+            // compareAndSet returns false when the value couldn't be updated because it did not
+            // match the expected value.
+            fail("Test NetworkAgents can only be connected once");
+        }
+        mNetworkAgent.markConnected();
     }
 
     public void suspend() {
@@ -227,8 +235,7 @@
     }
 
     public void disconnect() {
-        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
-        mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+        mNetworkAgent.unregister();
     }
 
     @Override
diff --git a/tests/net/java/android/net/KeepalivePacketDataUtilTest.java b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
new file mode 100644
index 0000000..fc739fb
--- /dev/null
+++ b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
+
+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;
+import org.junit.runners.JUnit4;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+
+@RunWith(JUnit4.class)
+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};
+
+    @Before
+    public void setUp() {}
+
+    @Test
+    public void testFromTcpKeepaliveStableParcelable() throws Exception {
+        final int srcPort = 1234;
+        final int dstPort = 4321;
+        final int seq = 0x11111111;
+        final int ack = 0x22222222;
+        final int wnd = 8000;
+        final int wndScale = 2;
+        final int tos = 4;
+        final int ttl = 64;
+        TcpKeepalivePacketData resultData = null;
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = seq;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
+        testInfo.tos = tos;
+        testInfo.ttl = ttl;
+        try {
+            resultData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
+        } catch (InvalidPacketException e) {
+            fail("InvalidPacketException: " + e);
+        }
+
+        assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress());
+        assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress());
+        assertEquals(testInfo.srcPort, resultData.getSrcPort());
+        assertEquals(testInfo.dstPort, resultData.getDstPort());
+        assertEquals(testInfo.seq, resultData.tcpSeq);
+        assertEquals(testInfo.ack, resultData.tcpAck);
+        assertEquals(testInfo.rcvWnd, resultData.tcpWindow);
+        assertEquals(testInfo.rcvWndScale, resultData.tcpWindowScale);
+        assertEquals(testInfo.tos, resultData.ipTos);
+        assertEquals(testInfo.ttl, resultData.ipTtl);
+
+        assertParcelingIsLossless(resultData);
+
+        final byte[] packet = resultData.getPacket();
+        // IP version and IHL
+        assertEquals(packet[0], 0x45);
+        // TOS
+        assertEquals(packet[1], tos);
+        // TTL
+        assertEquals(packet[8], ttl);
+        // Source IP address.
+        byte[] ip = new byte[4];
+        ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4);
+        buf.get(ip);
+        assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
+        // Destination IP address.
+        buf = ByteBuffer.wrap(packet, 16, 4);
+        buf.get(ip);
+        assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR);
+
+        buf = ByteBuffer.wrap(packet, 20, 12);
+        // Source port.
+        assertEquals(buf.getShort(), srcPort);
+        // Destination port.
+        assertEquals(buf.getShort(), dstPort);
+        // Sequence number.
+        assertEquals(buf.getInt(), seq);
+        // Ack.
+        assertEquals(buf.getInt(), ack);
+        // Window size.
+        buf = ByteBuffer.wrap(packet, 34, 2);
+        assertEquals(buf.getShort(), wnd >> wndScale);
+    }
+
+    //TODO: add ipv6 test when ipv6 supported
+
+    @Test
+    public void testToTcpKeepaliveStableParcelable() throws Exception {
+        final int srcPort = 1234;
+        final int dstPort = 4321;
+        final int sequence = 0x11111111;
+        final int ack = 0x22222222;
+        final int wnd = 48_000;
+        final int wndScale = 2;
+        final int tos = 4;
+        final int ttl = 64;
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = sequence;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
+        testInfo.tos = tos;
+        testInfo.ttl = ttl;
+        TcpKeepalivePacketData testData = null;
+        TcpKeepalivePacketDataParcelable resultData = null;
+        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);
+        assertEquals(resultData.dstPort, dstPort);
+        assertEquals(resultData.seq, sequence);
+        assertEquals(resultData.ack, ack);
+        assertEquals(resultData.rcvWnd, wnd);
+        assertEquals(resultData.rcvWndScale, wndScale);
+        assertEquals(resultData.tos, tos);
+        assertEquals(resultData.ttl, ttl);
+
+        final String expected = ""
+                + "android.net.TcpKeepalivePacketDataParcelable{srcAddress: [10, 0, 0, 1],"
+                + " srcPort: 1234, dstAddress: [10, 0, 0, 5], dstPort: 4321, seq: 286331153,"
+                + " 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/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
deleted file mode 100644
index c5b25bd..0000000
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-
-@RunWith(JUnit4.class)
-public final class TcpKeepalivePacketDataTest {
-    private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
-    private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
-
-    @Before
-    public void setUp() {}
-
-    @Test
-    public void testV4TcpKeepalivePacket() throws Exception {
-        final int srcPort = 1234;
-        final int dstPort = 4321;
-        final int seq = 0x11111111;
-        final int ack = 0x22222222;
-        final int wnd = 8000;
-        final int wndScale = 2;
-        final int tos = 4;
-        final int ttl = 64;
-        TcpKeepalivePacketData resultData = null;
-        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
-        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
-        testInfo.srcPort = srcPort;
-        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
-        testInfo.dstPort = dstPort;
-        testInfo.seq = seq;
-        testInfo.ack = ack;
-        testInfo.rcvWnd = wnd;
-        testInfo.rcvWndScale = wndScale;
-        testInfo.tos = tos;
-        testInfo.ttl = ttl;
-        try {
-            resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
-        } catch (InvalidPacketException e) {
-            fail("InvalidPacketException: " + e);
-        }
-
-        assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress());
-        assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress());
-        assertEquals(testInfo.srcPort, resultData.getSrcPort());
-        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.tos, resultData.ipTos);
-        assertEquals(testInfo.ttl, resultData.ipTtl);
-
-        assertParcelingIsLossless(resultData);
-
-        final byte[] packet = resultData.getPacket();
-        // IP version and IHL
-        assertEquals(packet[0], 0x45);
-        // TOS
-        assertEquals(packet[1], tos);
-        // TTL
-        assertEquals(packet[8], ttl);
-        // Source IP address.
-        byte[] ip = new byte[4];
-        ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4);
-        buf.get(ip);
-        assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
-        // Destination IP address.
-        buf = ByteBuffer.wrap(packet, 16, 4);
-        buf.get(ip);
-        assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR);
-
-        buf = ByteBuffer.wrap(packet, 20, 12);
-        // Source port.
-        assertEquals(buf.getShort(), srcPort);
-        // Destination port.
-        assertEquals(buf.getShort(), dstPort);
-        // Sequence number.
-        assertEquals(buf.getInt(), seq);
-        // Ack.
-        assertEquals(buf.getInt(), ack);
-        // Window size.
-        buf = ByteBuffer.wrap(packet, 34, 2);
-        assertEquals(buf.getShort(), wnd >> wndScale);
-    }
-
-    //TODO: add ipv6 test when ipv6 supported
-
-    @Test
-    public void testParcel() throws Exception {
-        final int srcPort = 1234;
-        final int dstPort = 4321;
-        final int sequence = 0x11111111;
-        final int ack = 0x22222222;
-        final int wnd = 48_000;
-        final int wndScale = 2;
-        final int tos = 4;
-        final int ttl = 64;
-        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
-        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
-        testInfo.srcPort = srcPort;
-        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
-        testInfo.dstPort = dstPort;
-        testInfo.seq = sequence;
-        testInfo.ack = ack;
-        testInfo.rcvWnd = wnd;
-        testInfo.rcvWndScale = wndScale;
-        testInfo.tos = tos;
-        testInfo.ttl = ttl;
-        TcpKeepalivePacketData testData = null;
-        TcpKeepalivePacketDataParcelable resultData = null;
-        testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
-        resultData = testData.toStableParcelable();
-        assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
-        assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
-        assertEquals(resultData.srcPort, srcPort);
-        assertEquals(resultData.dstPort, dstPort);
-        assertEquals(resultData.seq, sequence);
-        assertEquals(resultData.ack, ack);
-        assertEquals(resultData.rcvWnd, wnd);
-        assertEquals(resultData.rcvWndScale, wndScale);
-        assertEquals(resultData.tos, tos);
-        assertEquals(resultData.ttl, ttl);
-
-        final String expected = ""
-                + "android.net.TcpKeepalivePacketDataParcelable{srcAddress: [10, 0, 0, 1],"
-                + " srcPort: 1234, dstAddress: [10, 0, 0, 5], dstPort: 4321, seq: 286331153,"
-                + " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}";
-        assertEquals(expected, resultData.toString());
-    }
-}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b9fa7ea..799b64e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
@@ -38,6 +39,7 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
@@ -100,6 +102,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -131,6 +135,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -139,6 +144,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.location.LocationManager;
@@ -175,19 +182,20 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkFactory;
 import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
 import android.net.NetworkStackClient;
 import android.net.NetworkState;
 import android.net.NetworkTestResultParcelable;
-import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.ResolverParamsParcel;
 import android.net.RouteInfo;
 import android.net.RouteInfoParcel;
 import android.net.SocketKeepalive;
 import android.net.UidRange;
+import android.net.UidRangeParcel;
 import android.net.Uri;
 import android.net.VpnManager;
 import android.net.metrics.IpConnectivityLog;
@@ -331,12 +339,13 @@
     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
     private static final String VPN_IFNAME = "tun10042";
     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+    private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
 
     private static final String INTERFACE_NAME = "interface";
 
     private MockContext mServiceContext;
     private HandlerThread mCsHandlerThread;
+    private ConnectivityService.Dependencies mDeps;
     private ConnectivityService mService;
     private WrappedConnectivityManager mCm;
     private TestNetworkAgentWrapper mWiFiNetworkAgent;
@@ -352,6 +361,7 @@
     @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
     @Mock IpConnectivityMetrics.Logger mMetricsService;
     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+    @Mock DeviceIdleInternal mDeviceIdleInternal;
     @Mock INetworkManagementService mNetworkManagementService;
     @Mock INetworkStatsService mStatsService;
     @Mock IBatteryStats mBatteryStatsService;
@@ -449,6 +459,15 @@
         }
 
         @Override
+        public ComponentName startService(Intent service) {
+            final String action = service.getAction();
+            if (!VpnConfig.SERVICE_INTERFACE.equals(action)) {
+                fail("Attempt to start unknown service, action=" + action);
+            }
+            return new ComponentName(service.getPackage(), "com.android.test.Service");
+        }
+
+        @Override
         public Object getSystemService(String name) {
             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
@@ -646,8 +665,8 @@
         }
 
         @Override
-        protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
-                throws Exception {
+        protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
+                final int type, final String typeName) throws Exception {
             mNetworkMonitor = mock(INetworkMonitor.class);
 
             final Answer validateAnswer = inv -> {
@@ -666,7 +685,8 @@
                     any() /* name */,
                     nmCbCaptor.capture());
 
-            final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
+            final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties,
+                    type, typeName) {
                 @Override
                 public void networkStatus(int status, String redirectUrl) {
                     mRedirectUrl = redirectUrl;
@@ -1053,9 +1073,19 @@
         private VpnInfo mVpnInfo;
 
         public MockVpn(int userId) {
-            super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
-                    userId, mock(KeyStore.class));
-            mConfig = new VpnConfig();
+            super(startHandlerThreadAndReturnLooper(), mServiceContext,
+                    new Dependencies() {
+                        @Override
+                        public boolean isCallerSystem() {
+                            return true;
+                        }
+
+                        @Override
+                        public DeviceIdleInternal getDeviceIdleInternal() {
+                            return mDeviceIdleInternal;
+                        }
+                    },
+                    mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class));
         }
 
         public void setUids(Set<UidRange> uids) {
@@ -1084,26 +1114,35 @@
             return mVpnType;
         }
 
+        private LinkProperties makeLinkProperties() {
+            final LinkProperties lp = new LinkProperties();
+            lp.setInterfaceName(VPN_IFNAME);
+            return lp;
+        }
+
         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
                 throws Exception {
             if (mAgentRegistered) throw new IllegalStateException("already registered");
+            mConfig = new VpnConfig();
             setUids(uids);
             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
             mInterface = VPN_IFNAME;
             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
                     mNetworkCapabilities);
             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
-            verify(mNetworkManagementService, times(1))
-                    .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0])));
-            verify(mNetworkManagementService, never())
-                    .removeVpnUidRanges(eq(mMockVpn.getNetId()), any());
+
+            verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()),
+                    eq(toUidRangeStableParcels(uids)));
+            verify(mMockNetd, never())
+                    .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
             mAgentRegistered = true;
+            updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
             mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
         }
 
         private void registerAgent(Set<UidRange> uids) throws Exception {
-            registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties());
+            registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
         }
 
         private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
@@ -1139,12 +1178,12 @@
         public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
                 throws Exception {
             final int uid = Process.myUid();
-            establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
+            establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
                     isStrictMode);
         }
 
         public void establishForMyUid() throws Exception {
-            establishForMyUid(new LinkProperties());
+            establishForMyUid(makeLinkProperties());
         }
 
         public void sendLinkProperties(LinkProperties lp) {
@@ -1152,7 +1191,10 @@
         }
 
         public void disconnect() {
-            if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
+            if (mMockNetworkAgent != null) {
+                mMockNetworkAgent.disconnect();
+                updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
+            }
             mAgentRegistered = false;
         }
 
@@ -1168,6 +1210,11 @@
         }
     }
 
+    private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
+        return ranges.stream().map(
+                r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
+    }
+
     private void mockVpn(int uid) {
         synchronized (mService.mVpns) {
             int userId = UserHandle.getUserId(uid);
@@ -1221,6 +1268,17 @@
         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
     }
 
+    private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
+            int uid) {
+        when(mDeps.getCallingUid()).thenReturn(uid);
+        try {
+            mCm.registerNetworkCallback(request, callback);
+            waitForIdle();
+        } finally {
+            returnRealCallingUid();
+        }
+    }
+
     private static final int VPN_USER = 0;
     private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
     private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
@@ -1263,7 +1321,8 @@
         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
 
         mCsHandlerThread = new HandlerThread("TestConnectivityService");
-        final ConnectivityService.Dependencies deps = makeDependencies();
+        mDeps = makeDependencies();
+        returnRealCallingUid();
         mService = new ConnectivityService(mServiceContext,
                 mNetworkManagementService,
                 mStatsService,
@@ -1271,9 +1330,9 @@
                 mMockDnsResolver,
                 mock(IpConnectivityLog.class),
                 mMockNetd,
-                deps);
+                mDeps);
         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
-        verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
+        verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any());
 
         final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
                 ArgumentCaptor.forClass(INetworkPolicyListener.class);
@@ -1293,6 +1352,10 @@
         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
     }
 
+    private void returnRealCallingUid() {
+        doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
+    }
+
     private ConnectivityService.Dependencies makeDependencies() {
         doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties)
                 .getInt("net.tcp.default_init_rwnd", 0);
@@ -1368,13 +1431,13 @@
     }
 
     private void mockDefaultPackages() throws Exception {
-        final String testPackageName = mContext.getPackageName();
-        final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
-                testPackageName, PackageManager.GET_PERMISSIONS);
+        final String myPackageName = mContext.getPackageName();
+        final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
+                myPackageName, PackageManager.GET_PERMISSIONS);
         when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
-                new String[] {testPackageName});
-        when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
-                eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+                new String[] {myPackageName});
+        when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(),
+                eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo);
 
         when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
                 Arrays.asList(new PackageInfo[] {
@@ -1382,6 +1445,25 @@
                         buildPackageInfo(/* SYSTEM */ false, APP2_UID),
                         buildPackageInfo(/* SYSTEM */ false, VPN_UID)
                 }));
+
+        // Create a fake always-on VPN package.
+        final int userId = UserHandle.getCallingUserId();
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
+        when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(),
+                eq(userId))).thenReturn(applicationInfo);
+
+        // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
+        ResolveInfo rInfo = new ResolveInfo();
+        rInfo.serviceInfo = new ServiceInfo();
+        rInfo.serviceInfo.metaData = new Bundle();
+        final List<ResolveInfo> services = Arrays.asList(new ResolveInfo[]{rInfo});
+        when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
+                eq(userId))).thenReturn(services);
+        when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId))
+                .thenReturn(Process.myUid());
+        when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId))
+                .thenReturn(VPN_UID);
     }
 
     private void verifyActiveNetwork(int transport) {
@@ -1958,6 +2040,37 @@
     }
 
     @Test
+    public void testOwnerUidCannotChange() throws Exception {
+        // Owner UIDs are not visible without location permission.
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
+
+        final NetworkCapabilities ncTemplate = new NetworkCapabilities();
+        final int originalOwnerUid = Process.myUid();
+        ncTemplate.setOwnerUid(originalOwnerUid);
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
+                ncTemplate);
+        mWiFiNetworkAgent.connect(false);
+        waitForIdle();
+
+        // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
+        // the owner UID and an unrelated capability.
+        NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
+        assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
+        agentCapabilities.setOwnerUid(42);
+        assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+        mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+        waitForIdle();
+
+        // Check that the capability change has been applied but the owner UID is not modified.
+        NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+        assertEquals(originalOwnerUid, nc.getOwnerUid());
+        assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+    }
+
+    @Test
     public void testMultipleLingering() throws Exception {
         // This test would be flaky with the default 120ms timer: that is short enough that
         // lingered networks are torn down before assertions can be run. We don't want to mock the
@@ -2213,10 +2326,10 @@
     }
 
     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
-        final String testPackageName = mContext.getPackageName();
-        when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
+        final String myPackageName = mContext.getPackageName();
+        when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS)))
                 .thenReturn(buildPackageInfo(true, uid));
-        mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
+        mService.mPermissionMonitor.onPackageAdded(myPackageName, uid);
     }
 
     @Test
@@ -2517,10 +2630,8 @@
 
     @Test
     public void testNoMutableNetworkRequests() throws Exception {
-        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"),
-                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
         NetworkRequest request1 = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_VALIDATED)
                 .build();
@@ -3180,21 +3291,17 @@
         assertThrows(SecurityException.class, () ->
                 mCm.registerNetworkCallback(r, new NetworkCallback()));
 
-        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         assertThrows(SecurityException.class, () ->
                 mCm.registerNetworkCallback(r, PendingIntent.getService(
-                        mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED)));
+                        mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
 
         // Requesting a Network with signal strength should get IllegalArgumentException.
         assertThrows(IllegalArgumentException.class, () ->
                 mCm.requestNetwork(r, new NetworkCallback()));
 
-        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
         assertThrows(IllegalArgumentException.class, () ->
                 mCm.requestNetwork(r, PendingIntent.getService(
-                        mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED)));
+                        mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
     }
 
     @Test
@@ -4658,16 +4765,14 @@
         }
         j = 0;
         while (j++ < INTENTS / 2) {
-            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+            final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+                    new Intent("a" + j), FLAG_IMMUTABLE);
             mCm.requestNetwork(networkRequest, pi);
             registered.add(pi);
         }
         while (j++ < INTENTS) {
-            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-            PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+            final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+                    new Intent("b" + j), FLAG_IMMUTABLE);
             mCm.registerNetworkCallback(networkRequest, pi);
             registered.add(pi);
         }
@@ -4681,15 +4786,13 @@
         );
         assertThrows(TooManyRequestsException.class, () ->
                 mCm.requestNetwork(networkRequest,
-                        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-                        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-                        PendingIntent.getBroadcast(mContext, 0, new Intent("c"), PendingIntent.FLAG_MUTABLE_UNAUDITED))
+                        PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+                                new Intent("c"), FLAG_IMMUTABLE))
         );
         assertThrows(TooManyRequestsException.class, () ->
                 mCm.registerNetworkCallback(networkRequest,
-                        // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-                        // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-                        PendingIntent.getBroadcast(mContext, 0, new Intent("d"), PendingIntent.FLAG_MUTABLE_UNAUDITED))
+                        PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+                                new Intent("d"), FLAG_IMMUTABLE))
         );
 
         for (Object o : registered) {
@@ -4718,20 +4821,16 @@
         waitForIdle();
 
         for (int i = 0; i < MAX_REQUESTS; i++) {
-            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-            PendingIntent pendingIntent =
-                    PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
             mCm.requestNetwork(networkRequest, pendingIntent);
             mCm.unregisterNetworkCallback(pendingIntent);
         }
         waitForIdle();
 
         for (int i = 0; i < MAX_REQUESTS; i++) {
-            // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below
-            // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE.
-            PendingIntent pendingIntent =
-                    PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
             mCm.registerNetworkCallback(networkRequest, pendingIntent);
             mCm.unregisterNetworkCallback(pendingIntent);
         }
@@ -4809,7 +4908,7 @@
         lp.setInterfaceName(WIFI_IFNAME);
         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
-                NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+                InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
         lp.addLinkAddress(myIpv4Address);
         lp.addRoute(myIpv4DefaultRoute);
 
@@ -4929,8 +5028,8 @@
         expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
         reset(mStatsService);
 
-        // Captive portal change shouldn't update ifaces
-        mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+        // Temp metered change shouldn't update ifaces
+        mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED);
         waitForIdle();
         verify(mStatsService, never())
                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
@@ -5446,6 +5545,7 @@
         final Network wifi = mWiFiNetworkAgent.getNetwork();
 
         final NetworkCapabilities initialCaps = new NetworkCapabilities();
+        initialCaps.addTransportType(TRANSPORT_VPN);
         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
 
@@ -5477,44 +5577,45 @@
         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
 
+        final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
+        initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
+
         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
-        final boolean notDeclaredMetered = false;
-        mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
         assertEquals(withNoUnderlying, caps);
 
         caps = new NetworkCapabilities(initialCaps);
-        mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
         assertEquals(withNoUnderlying, caps);
 
         caps = new NetworkCapabilities(initialCaps);
-        mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
         assertEquals(withMobileUnderlying, caps);
 
-        mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
         assertEquals(withWifiUnderlying, caps);
 
-        final boolean isDeclaredMetered = true;
         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
         caps = new NetworkCapabilities(initialCaps);
-        mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
         assertEquals(withWifiUnderlying, caps);
 
         caps = new NetworkCapabilities(initialCaps);
-        mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
+        mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
         assertEquals(withWifiAndMobileUnderlying, caps);
 
         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
         caps = new NetworkCapabilities(initialCaps);
         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
-                caps, notDeclaredMetered);
+                initialCapsNotMetered, caps);
         assertEquals(withWifiAndMobileUnderlying, caps);
 
         caps = new NetworkCapabilities(initialCaps);
         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
-                caps, notDeclaredMetered);
+                initialCapsNotMetered, caps);
         assertEquals(withWifiAndMobileUnderlying, caps);
 
-        mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
+        mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
         assertEquals(withWifiUnderlying, caps);
     }
 
@@ -5804,10 +5905,21 @@
         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
     }
 
+    private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
+        final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
+                userId, "com.android.calling.package");
+        final String defaultCapsString = Arrays.toString(defaultCaps);
+        assertEquals(defaultCapsString, defaultCaps.length, networks.length);
+        final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
+        for (NetworkAgentWrapper network : networks) {
+            final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
+            final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
+            assertTrue(msg, defaultCapsSet.contains(nc));
+        }
+    }
+
     @Test
     public void testVpnSetUnderlyingNetworks() throws Exception {
-        final int uid = Process.myUid();
-
         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
                 .removeCapability(NET_CAPABILITY_NOT_VPN)
@@ -5830,6 +5942,9 @@
         // A VPN without underlying networks is not suspended.
         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
+        final int userId = UserHandle.getUserId(Process.myUid());
+        assertDefaultNetworkCapabilities(userId /* no networks */);
+
         // Connect cell and use it as an underlying network.
         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5843,6 +5958,7 @@
                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -5857,6 +5973,7 @@
                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
 
         // Don't disconnect, but note the VPN is not using wifi any more.
         mService.setUnderlyingNetworksForVpn(
@@ -5867,6 +5984,9 @@
                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
+        // network (wifi) as well as the underlying networks (cell).
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
 
         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5895,6 +6015,7 @@
                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
 
         // Use both again.
         mService.setUnderlyingNetworksForVpn(
@@ -5905,6 +6026,7 @@
                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
 
         // Cell is suspended again. As WiFi is not, this should not cause a callback.
         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5922,6 +6044,7 @@
         // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never
         // been public and are deprecated and slated for removal, there is no sense in spending
         // resources fixing this bug now.
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
 
         // Use both again.
         mService.setUnderlyingNetworksForVpn(
@@ -5934,6 +6057,7 @@
                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
         // As above, the RESUMED callback not being sent here is a bug, but not a bug that's
         // worth anybody's time to fix.
+        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
 
         // Disconnect cell. Receive update without even removing the dead network from the
         // underlying networks – it's dead anyway. Not metered any more.
@@ -5942,6 +6066,7 @@
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
 
         // Disconnect wifi too. No underlying networks means this is now metered.
         mWiFiNetworkAgent.disconnect();
@@ -5949,6 +6074,11 @@
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        // When a network disconnects, the callbacks are fired before all state is updated, so for a
+        // short time, synchronous calls will behave as if the network is still connected. Wait for
+        // things to settle.
+        waitForIdle();
+        assertDefaultNetworkCapabilities(userId /* no networks */);
 
         mMockVpn.disconnect();
     }
@@ -6249,6 +6379,7 @@
         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
         assertTrue(mCm.isActiveNetworkMetered());
 
+
         // VPN explicitly declares WiFi as its underlying network.
         mService.setUnderlyingNetworksForVpn(
                 new Network[] { mWiFiNetworkAgent.getNetwork() });
@@ -6362,6 +6493,189 @@
         mCm.unregisterNetworkCallback(defaultCallback);
     }
 
+    private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
+            UidRangeParcel... expected) throws Exception {
+        inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
+    }
+
+    private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
+        assertNotNull(ni);
+        assertEquals(type, ni.getType());
+        assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
+    }
+
+    private void assertActiveNetworkInfo(int type, DetailedState state) {
+        checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
+    }
+    private void assertNetworkInfo(int type, DetailedState state) {
+        checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
+    }
+
+    @Test
+    public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
+        mServiceContext.setPermission(
+                Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
+        mServiceContext.setPermission(
+                Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
+        mServiceContext.setPermission(
+                Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+
+        final TestNetworkCallback callback = new TestNetworkCallback();
+        final NetworkRequest request = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .build();
+        mCm.registerNetworkCallback(request, callback);
+
+        final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+        mCm.registerDefaultNetworkCallback(defaultCallback);
+
+        final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
+        final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
+        registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
+
+        final int uid = Process.myUid();
+        final int userId = UserHandle.getUserId(uid);
+        final ArrayList<String> allowList = new ArrayList<>();
+        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+
+        UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
+        UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
+        InOrder inOrder = inOrder(mMockNetd);
+        expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+
+        // Connect a network when lockdown is active, expect to see it blocked.
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+        vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertNull(mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        // Mobile is BLOCKED even though it's not actually connected.
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+        // Disable lockdown, expect to see the network unblocked.
+        // There are no callbacks because they are not implemented yet.
+        mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
+        allowList.add(TEST_PACKAGE_NAME);
+        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        callback.assertNoCallback();
+        defaultCallback.assertNoCallback();
+        vpnUidCallback.assertNoCallback();
+
+        // The following requires that the UID of this test package is greater than VPN_UID. This
+        // is always true in practice because a plain AOSP build with no apps installed has almost
+        // 200 packages installed.
+        final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1);
+        final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1);
+        final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999);
+        expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3);
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        // Connect a new network, expect it to be unblocked.
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        defaultCallback.assertNoCallback();
+        vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
+        // Everything should now be blocked.
+        mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
+        allowList.clear();
+        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertNull(mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+        // Disable lockdown. Everything is unblocked.
+        mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        // Enable and disable an always-on VPN package without lockdown. Expect no changes.
+        reset(mMockNetd);
+        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList);
+        inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+        callback.assertNoCallback();
+        defaultCallback.assertNoCallback();
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+        callback.assertNoCallback();
+        defaultCallback.assertNoCallback();
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        // Enable lockdown and connect a VPN. The VPN is not blocked.
+        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        vpnUidCallback.assertNoCallback();
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertNull(mCm.getActiveNetwork());
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+        mMockVpn.establishForMyUid();
+        defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+        vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
+        assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(null, mCm.getActiveNetworkForUid(VPN_UID));  // BUG?
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+        mMockVpn.disconnect();
+        defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+        assertNull(mCm.getActiveNetwork());
+
+        mCm.unregisterNetworkCallback(callback);
+        mCm.unregisterNetworkCallback(defaultCallback);
+        mCm.unregisterNetworkCallback(vpnUidCallback);
+    }
+
     @Test
     public final void testLoseTrusted() throws Exception {
         final NetworkRequest trustedRequest = new NetworkRequest.Builder()
@@ -7795,7 +8109,16 @@
 
     @Test
     public void testDumpDoesNotCrash() {
-        StringWriter stringWriter = new StringWriter();
+        // Filing a couple requests prior to testing the dump.
+        final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+        final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest genericRequest = new NetworkRequest.Builder()
+                .clearCapabilities().build();
+        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+        mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+        final StringWriter stringWriter = new StringWriter();
 
         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
 
@@ -7817,11 +8140,11 @@
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
 
-        ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+        final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
 
         assertTrue(nriOutput.length > 1);
         for (int i = 0; i < nriOutput.length - 1; i++) {
-            boolean isRequestIdInOrder =
+            final boolean isRequestIdInOrder =
                     nriOutput[i].mRequests.get(0).requestId
                             < nriOutput[i + 1].mRequests.get(0).requestId;
             assertTrue(isRequestIdInOrder);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 529d03c..799bcc8 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
@@ -44,7 +45,6 @@
 import android.net.IpSecUdpEncapResponse;
 import android.net.LinkAddress;
 import android.net.Network;
-import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.os.ParcelFileDescriptor;
@@ -272,7 +272,7 @@
 
         IpSecSpiResponse spi =
                 mIpSecService.allocateSecurityParameterIndex(
-                        NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
+                        InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(),
                         IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
                         new Binder());
         return spi.resourceId;
diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index c53462c..950d7163 100644
--- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -130,6 +130,7 @@
 
         when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+        // Mock user id to all users that Context#registerReceiver will register with all users too.
         doReturn(UserHandle.ALL.getIdentifier()).when(mUserAllContext).getUserId();
         when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt()))
                 .thenReturn(mUserAllContext);
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index de35f91..3556c72 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -58,7 +58,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
 import android.net.INetd;
 import android.net.UidRange;
 import android.os.Build;
@@ -123,10 +122,10 @@
         MockitoAnnotations.initMocks(this);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
-        when(mUserManager.getAliveUsers()).thenReturn(
-                Arrays.asList(new UserInfo[] {
-                        new UserInfo(MOCK_USER1, "", 0),
-                        new UserInfo(MOCK_USER2, "", 0),
+        when(mUserManager.getUserHandles(eq(true))).thenReturn(
+                Arrays.asList(new UserHandle[] {
+                        new UserHandle(MOCK_USER1),
+                        new UserHandle(MOCK_USER2),
                 }));
 
         mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 337507a..cc47317 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -58,6 +58,7 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.Ikev2VpnProfile;
 import android.net.InetAddresses;
 import android.net.IpPrefix;
@@ -70,6 +71,7 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.RouteInfo;
 import android.net.UidRange;
+import android.net.UidRangeParcel;
 import android.net.VpnManager;
 import android.net.VpnService;
 import android.net.ipsec.ike.IkeSessionCallback;
@@ -172,11 +174,13 @@
             mPackages.put(PKGS[i], PKG_UIDS[i]);
         }
     }
+    private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
     @Mock private UserManager mUserManager;
     @Mock private PackageManager mPackageManager;
     @Mock private INetworkManagementService mNetService;
+    @Mock private INetd mNetd;
     @Mock private AppOpsManager mAppOps;
     @Mock private NotificationManager mNotificationManager;
     @Mock private Vpn.SystemServices mSystemServices;
@@ -224,7 +228,6 @@
                         R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
                 .thenReturn(true);
-        when(mSystemServices.isCallerSystem()).thenReturn(true);
 
         // Used by {@link Notification.Builder}
         ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -256,8 +259,7 @@
                 null, null);
 
         assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
-            UidRange.createForUser(primaryUser.id),
-            UidRange.createForUser(restrictedProfileA.id)
+                PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
         })), ranges);
     }
 
@@ -269,9 +271,7 @@
         final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
                 null, null);
 
-        assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
-            UidRange.createForUser(primaryUser.id)
-        })), ranges);
+        assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
     }
 
     @Test
@@ -282,15 +282,13 @@
         final Set<UidRange> ranges = new ArraySet<>();
         vpn.addUserToRanges(ranges, primaryUser.id, null, null);
 
-        assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
-            UidRange.createForUser(primaryUser.id)
-        })), ranges);
+        assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
     }
 
     @Test
     public void testUidAllowAndDenylist() throws Exception {
         final Vpn vpn = createVpn(primaryUser.id);
-        final UidRange user = UidRange.createForUser(primaryUser.id);
+        final UidRange user = PRI_USER_RANGE;
         final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
 
         // Allowed list
@@ -339,62 +337,67 @@
     @Test
     public void testLockdownChangingPackage() throws Exception {
         final Vpn vpn = createVpn(primaryUser.id);
-        final UidRange user = UidRange.createForUser(primaryUser.id);
+        final UidRange user = PRI_USER_RANGE;
 
         // Default state.
-        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+                user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on without lockdown.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore));
-        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+                user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on with lockdown.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-            new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
-            new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
         }));
-        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+
+        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2],
+                user.start + PKG_UIDS[3]);
         assertUnblocked(vpn, user.start + PKG_UIDS[1]);
 
         // Switch to another app.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-            new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
-            new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-            new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
-            new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
         }));
-        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
+        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+                user.start + PKG_UIDS[2]);
         assertUnblocked(vpn, user.start + PKG_UIDS[3]);
     }
 
     @Test
     public void testLockdownAllowlist() throws Exception {
         final Vpn vpn = createVpn(primaryUser.id);
-        final UidRange user = UidRange.createForUser(primaryUser.id);
+        final UidRange user = PRI_USER_RANGE;
 
         // Set always-on with lockdown and allow app PKGS[2] from lockdown.
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-                new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
-                new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
         }));
         assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
         assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
-
         // Change allowed app list to PKGS[3].
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
-                new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
         }));
         assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]);
         assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
@@ -402,25 +405,25 @@
         // Change the VPN app.
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-                new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
-                new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-                new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
         }));
         assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
 
         // Remove the list of allowed packages.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
-                new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.stop),
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
         }));
         assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2],
                 user.start + PKG_UIDS[3]);
@@ -429,12 +432,12 @@
         // Add the list of allowed packages.
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
-                new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
         }));
         assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
@@ -447,13 +450,13 @@
         // allowed package should change from PGKS[1] to PKGS[2].
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
-                new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[]{
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
         }));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{
-                new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
-                new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[]{
+                new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
         }));
     }
 
@@ -467,86 +470,86 @@
                 restrictedProfileA.flags);
         tempProfile.restrictedProfileParentId = primaryUser.id;
 
-        final UidRange user = UidRange.createForUser(primaryUser.id);
+        final UidRange user = PRI_USER_RANGE;
         final UidRange profile = UidRange.createForUser(tempProfile.id);
 
         // Set lockdown.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-            new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
-            new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
         }));
-
         // Verify restricted user isn't affected at first.
         assertUnblocked(vpn, profile.start + PKG_UIDS[0]);
 
         // Add the restricted user.
         setMockedUsers(primaryUser, tempProfile);
         vpn.onUserAdded(tempProfile.id);
-        verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
-            new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
-            new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
         }));
 
         // Remove the restricted user.
         tempProfile.partial = true;
         vpn.onUserRemoved(tempProfile.id);
-        verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
-            new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
-            new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+                new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
+                new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
         }));
     }
 
     @Test
     public void testLockdownRuleRepeatability() throws Exception {
         final Vpn vpn = createVpn(primaryUser.id);
-
+        final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
+                new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
         // Given legacy lockdown is already enabled,
         vpn.setLockdown(true);
-        verify(mNetService, times(1)).setAllowOnlyVpnForUids(
-                eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
+
+        verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(primaryUserRangeParcel));
 
         // Enabling legacy lockdown twice should do nothing.
         vpn.setLockdown(true);
-        verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
+        verify(mNetd, times(1))
+                .networkRejectNonSecureVpn(anyBoolean(), any(UidRangeParcel[].class));
 
         // And disabling should remove the rules exactly once.
         vpn.setLockdown(false);
-        verify(mNetService, times(1)).setAllowOnlyVpnForUids(
-                eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
+        verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(primaryUserRangeParcel));
 
         // Removing the lockdown again should have no effect.
         vpn.setLockdown(false);
-        verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
+        verify(mNetd, times(2)).networkRejectNonSecureVpn(
+                anyBoolean(), any(UidRangeParcel[].class));
     }
 
     @Test
     public void testLockdownRuleReversibility() throws Exception {
         final Vpn vpn = createVpn(primaryUser.id);
-
-        final UidRange[] entireUser = {
-            UidRange.createForUser(primaryUser.id)
+        final UidRangeParcel[] entireUser = {
+            new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
         };
-        final UidRange[] exceptPkg0 = {
-            new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
-            new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
+        final UidRangeParcel[] exceptPkg0 = {
+            new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
+            new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
         };
 
-        final InOrder order = inOrder(mNetService);
+        final InOrder order = inOrder(mNetd);
 
         // Given lockdown is enabled with no package (legacy VPN),
         vpn.setLockdown(true);
-        order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
+        order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
 
         // When a new VPN package is set the rules should change to cover that package.
         vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE);
-        order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser));
-        order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0));
+        order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(entireUser));
+        order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(exceptPkg0));
 
         // When that VPN package is unset, everything should be undone again in reverse.
         vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE);
-        order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0));
-        order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
+        order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(exceptPkg0));
+        order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
     }
 
     @Test
@@ -1098,6 +1101,11 @@
         }
 
         @Override
+        public boolean isCallerSystem() {
+            return true;
+        }
+
+        @Override
         public void startService(final String serviceName) {
             mRunningServices.put(serviceName, true);
         }
@@ -1186,7 +1194,7 @@
                 .thenReturn(asUserContext);
         final TestLooper testLooper = new TestLooper();
         final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
-                userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
+                mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
         verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
                 provider -> provider.getName().contains("VpnNetworkProvider")
         ));
diff --git a/tests/notification/OWNERS b/tests/notification/OWNERS
new file mode 100644
index 0000000..396fd12
--- /dev/null
+++ b/tests/notification/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
diff --git a/tests/permission/OWNERS b/tests/permission/OWNERS
new file mode 100644
index 0000000..999ea0e
--- /dev/null
+++ b/tests/permission/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/permission/OWNERS
diff --git a/tests/utils/DummyIME/OWNERS b/tests/utils/DummyIME/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/tests/utils/DummyIME/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/tests/utils/StubIME/OWNERS b/tests/utils/StubIME/OWNERS
new file mode 100644
index 0000000..5deb2ce
--- /dev/null
+++ b/tests/utils/StubIME/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/inputmethod/OWNERS
diff --git a/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS
new file mode 100644
index 0000000..d04a706
--- /dev/null
+++ b/tests/utils/hostutils/src/com/android/tests/rollback/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/rollback/OWNERS
diff --git a/tests/utils/testutils/java/com/android/server/accessibility/OWNERS b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS
new file mode 100644
index 0000000..b74281e
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/server/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
diff --git a/tests/utils/testutils/java/com/android/server/wm/OWNERS b/tests/utils/testutils/java/com/android/server/wm/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/server/wm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
new file mode 100644
index 0000000..77944de
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnConfigTest {
+    private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS =
+            Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig());
+
+    // Public visibility for VcnManagementServiceTest
+    public static VcnConfig buildTestConfig() {
+        VcnConfig.Builder builder = new VcnConfig.Builder();
+
+        for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
+            builder.addGatewayConnectionConfig(gatewayConnectionConfig);
+        }
+
+        return builder.build();
+    }
+
+    @Test
+    public void testBuilderRequiresGatewayConnectionConfig() {
+        try {
+            new VcnConfig.Builder().build();
+            fail("Expected exception due to no VcnGatewayConnectionConfigs provided");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderAndGetters() {
+        final VcnConfig config = buildTestConfig();
+
+        assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
+    }
+
+    @Test
+    public void testPersistableBundle() {
+        final VcnConfig config = buildTestConfig();
+
+        assertEquals(config, new VcnConfig(config.toPersistableBundle()));
+    }
+
+    @Test
+    public void testParceling() {
+        final VcnConfig config = buildTestConfig();
+
+        Parcel parcel = Parcel.obtain();
+        config.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        assertEquals(config, VcnConfig.CREATOR.createFromParcel(parcel));
+    }
+}
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
new file mode 100644
index 0000000..e98b6ef
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.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 android.net.vcn;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.net.NetworkCapabilities;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnGatewayConnectionConfigTest {
+    private static final int[] EXPOSED_CAPS =
+            new int[] {
+                NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS
+            };
+    private static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
+    private static final long[] RETRY_INTERVALS_MS =
+            new long[] {
+                TimeUnit.SECONDS.toMillis(5),
+                TimeUnit.SECONDS.toMillis(30),
+                TimeUnit.MINUTES.toMillis(1),
+                TimeUnit.MINUTES.toMillis(5),
+                TimeUnit.MINUTES.toMillis(15),
+                TimeUnit.MINUTES.toMillis(30)
+            };
+    private static final int MAX_MTU = 1360;
+
+    // Package protected for use in VcnConfigTest
+    static VcnGatewayConnectionConfig buildTestConfig() {
+        final VcnGatewayConnectionConfig.Builder builder =
+                new VcnGatewayConnectionConfig.Builder()
+                        .setRetryInterval(RETRY_INTERVALS_MS)
+                        .setMaxMtu(MAX_MTU);
+
+        for (int caps : EXPOSED_CAPS) {
+            builder.addExposedCapability(caps);
+        }
+
+        for (int caps : UNDERLYING_CAPS) {
+            builder.addRequiredUnderlyingCapability(caps);
+        }
+
+        return builder.build();
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyExposedCaps() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .build();
+
+            fail("Expected exception due to invalid exposed capabilities");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyUnderlyingCaps() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .build();
+
+            fail("Expected exception due to invalid required underlying capabilities");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonNullRetryInterval() {
+        try {
+            new VcnGatewayConnectionConfig.Builder().setRetryInterval(null);
+            fail("Expected exception due to invalid retryIntervalMs");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyRetryInterval() {
+        try {
+            new VcnGatewayConnectionConfig.Builder().setRetryInterval(new long[0]);
+            fail("Expected exception due to invalid retryIntervalMs");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresValidMtu() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1);
+            fail("Expected exception due to invalid mtu");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderAndGetters() {
+        final VcnGatewayConnectionConfig config = buildTestConfig();
+
+        for (int cap : EXPOSED_CAPS) {
+            config.hasExposedCapability(cap);
+        }
+        for (int cap : UNDERLYING_CAPS) {
+            config.requiresUnderlyingCapability(cap);
+        }
+
+        assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMs());
+        assertEquals(MAX_MTU, config.getMaxMtu());
+    }
+
+    @Test
+    public void testPersistableBundle() {
+        final VcnGatewayConnectionConfig config = buildTestConfig();
+
+        assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
+    }
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index c91fdbf..1cc9532 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -16,42 +16,123 @@
 
 package com.android.server;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnConfigTest;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
 import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.vcn.util.PersistableBundleUtils;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.FileNotFoundException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.UUID;
+
 /** Tests for {@link VcnManagementService}. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class VcnManagementServiceTest {
+    private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
+    private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
+    private static final VcnConfig TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig();
+    private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP =
+            Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG));
+
+    private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO =
+            new SubscriptionInfo(
+                    1 /* id */,
+                    "" /* iccId */,
+                    0 /* simSlotIndex */,
+                    "Carrier" /* displayName */,
+                    "Carrier" /* carrierName */,
+                    0 /* nameSource */,
+                    255 /* iconTint */,
+                    "12345" /* number */,
+                    0 /* roaming */,
+                    null /* icon */,
+                    "0" /* mcc */,
+                    "0" /* mnc */,
+                    "0" /* countryIso */,
+                    false /* isEmbedded */,
+                    null /* nativeAccessRules */,
+                    null /* cardString */,
+                    false /* isOpportunistic */,
+                    TEST_UUID_1.toString() /* groupUUID */,
+                    0 /* carrierId */,
+                    0 /* profileClass */);
+
     private final Context mMockContext = mock(Context.class);
     private final VcnManagementService.Dependencies mMockDeps =
             mock(VcnManagementService.Dependencies.class);
     private final TestLooper mTestLooper = new TestLooper();
     private final ConnectivityManager mConnMgr = mock(ConnectivityManager.class);
+    private final TelephonyManager mTelMgr = mock(TelephonyManager.class);
+    private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class);
     private final VcnManagementService mVcnMgmtSvc;
+    private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper =
+            mock(PersistableBundleUtils.LockingReadWriteHelper.class);
 
-    public VcnManagementServiceTest() {
-        doReturn(Context.CONNECTIVITY_SERVICE)
-                .when(mMockContext)
-                .getSystemServiceName(ConnectivityManager.class);
-        doReturn(mConnMgr).when(mMockContext).getSystemService(Context.CONNECTIVITY_SERVICE);
+    public VcnManagementServiceTest() throws Exception {
+        setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+        setupSystemService(mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+        setupSystemService(
+                mSubMgr, Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class);
 
         doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper();
+        doReturn(Process.FIRST_APPLICATION_UID).when(mMockDeps).getBinderCallingUid();
+        doReturn(mConfigReadWriteHelper)
+                .when(mMockDeps)
+                .newPersistableBundleLockingReadWriteHelper(any());
+
+        final PersistableBundle bundle =
+                PersistableBundleUtils.fromMap(
+                        TEST_VCN_CONFIG_MAP,
+                        PersistableBundleUtils::fromParcelUuid,
+                        VcnConfig::toPersistableBundle);
+        doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk();
+
+        setupMockedCarrierPrivilege(true);
         mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
     }
 
+    private void setupSystemService(Object service, String name, Class<?> serviceClass) {
+        doReturn(name).when(mMockContext).getSystemServiceName(serviceClass);
+        doReturn(service).when(mMockContext).getSystemService(name);
+    }
+
+    private void setupMockedCarrierPrivilege(boolean isPrivileged) {
+        doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
+                .when(mSubMgr)
+                .getSubscriptionsInGroup(any());
+        doReturn(isPrivileged)
+                .when(mTelMgr)
+                .hasCarrierPrivileges(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
+    }
+
     @Test
     public void testSystemReady() throws Exception {
         mVcnMgmtSvc.systemReady();
@@ -59,4 +140,119 @@
         verify(mConnMgr)
                 .registerNetworkProvider(any(VcnManagementService.VcnNetworkProvider.class));
     }
+
+    @Test
+    public void testNonSystemServerRealConfigFileAccessPermission() throws Exception {
+        // Attempt to build a real instance of the dependencies, and verify we cannot write to the
+        // file.
+        VcnManagementService.Dependencies deps = new VcnManagementService.Dependencies();
+        PersistableBundleUtils.LockingReadWriteHelper configReadWriteHelper =
+                deps.newPersistableBundleLockingReadWriteHelper(
+                        VcnManagementService.VCN_CONFIG_FILE);
+
+        // Even tests should not be able to read/write configs from disk; SELinux policies restrict
+        // it to only the system server.
+        // Reading config should always return null since the file "does not exist", and writing
+        // should throw an IOException.
+        assertNull(configReadWriteHelper.readFromDisk());
+
+        try {
+            configReadWriteHelper.writeToDisk(new PersistableBundle());
+            fail("Expected IOException due to SELinux policy");
+        } catch (FileNotFoundException expected) {
+        }
+    }
+
+    @Test
+    public void testLoadVcnConfigsOnStartup() throws Exception {
+        mTestLooper.dispatchAll();
+
+        assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
+        verify(mConfigReadWriteHelper).readFromDisk();
+    }
+
+    @Test
+    public void testSetVcnConfigRequiresNonSystemServer() throws Exception {
+        doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
+
+        try {
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+            fail("Expected IllegalStateException exception for system server");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    @Test
+    public void testSetVcnConfigRequiresSystemUser() throws Exception {
+        doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID))
+                .when(mMockDeps)
+                .getBinderCallingUid();
+
+        try {
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+            fail("Expected security exception for non system user");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    @Test
+    public void testSetVcnConfigRequiresCarrierPrivileges() throws Exception {
+        setupMockedCarrierPrivilege(false);
+
+        try {
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+            fail("Expected security exception for missing carrier privileges");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    @Test
+    public void testSetVcnConfig() throws Exception {
+        // Use a different UUID to simulate a new VCN config.
+        mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG);
+        assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2));
+        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+    }
+
+    @Test
+    public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
+        doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
+
+        try {
+            mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+            fail("Expected IllegalStateException exception for system server");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    @Test
+    public void testClearVcnConfigRequiresSystemUser() throws Exception {
+        doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID))
+                .when(mMockDeps)
+                .getBinderCallingUid();
+
+        try {
+            mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+            fail("Expected security exception for non system user");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    @Test
+    public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception {
+        setupMockedCarrierPrivilege(false);
+
+        try {
+            mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+            fail("Expected security exception for missing carrier privileges");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    @Test
+    public void testClearVcnConfig() throws Exception {
+        mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+        assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+    }
 }
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
new file mode 100644
index 0000000..17b8f64
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -0,0 +1,333 @@
+/*
+ * 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.vcn;
+
+import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
+import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
+import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.ParcelUuid;
+import android.os.test.TestLooper;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/** Tests for TelephonySubscriptionTracker */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TelephonySubscriptionTrackerTest {
+    private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
+    private static final int TEST_SIM_SLOT_INDEX = 1;
+    private static final int TEST_SUBSCRIPTION_ID_1 = 2;
+    private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
+    private static final int TEST_SUBSCRIPTION_ID_2 = 3;
+    private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
+    private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+
+    static {
+        final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
+        subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
+        subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
+        TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+    }
+
+    @NonNull private final Context mContext;
+    @NonNull private final TestLooper mTestLooper;
+    @NonNull private final Handler mHandler;
+    @NonNull private final TelephonySubscriptionTracker.Dependencies mDeps;
+
+    @NonNull private final SubscriptionManager mSubscriptionManager;
+    @NonNull private final CarrierConfigManager mCarrierConfigManager;
+
+    @NonNull private TelephonySubscriptionTrackerCallback mCallback;
+    @NonNull private TelephonySubscriptionTracker mTelephonySubscriptionTracker;
+
+    public TelephonySubscriptionTrackerTest() {
+        mContext = mock(Context.class);
+        mTestLooper = new TestLooper();
+        mHandler = new Handler(mTestLooper.getLooper());
+        mDeps = mock(TelephonySubscriptionTracker.Dependencies.class);
+
+        mSubscriptionManager = mock(SubscriptionManager.class);
+        mCarrierConfigManager = mock(CarrierConfigManager.class);
+
+        doReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
+                .when(mContext)
+                .getSystemServiceName(SubscriptionManager.class);
+        doReturn(mSubscriptionManager)
+                .when(mContext)
+                .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+
+        doReturn(Context.CARRIER_CONFIG_SERVICE)
+                .when(mContext)
+                .getSystemServiceName(CarrierConfigManager.class);
+        doReturn(mCarrierConfigManager)
+                .when(mContext)
+                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+        // subId 1, 2 are in same subGrp, only subId 1 is active
+        doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_1).getGroupUuid();
+        doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_2).getGroupUuid();
+        doReturn(TEST_SIM_SLOT_INDEX).when(TEST_SUBINFO_1).getSimSlotIndex();
+        doReturn(INVALID_SIM_SLOT_INDEX).when(TEST_SUBINFO_2).getSimSlotIndex();
+        doReturn(TEST_SUBSCRIPTION_ID_1).when(TEST_SUBINFO_1).getSubscriptionId();
+        doReturn(TEST_SUBSCRIPTION_ID_2).when(TEST_SUBINFO_2).getSubscriptionId();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        mCallback = mock(TelephonySubscriptionTrackerCallback.class);
+        mTelephonySubscriptionTracker =
+                new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps);
+        mTelephonySubscriptionTracker.register();
+
+        doReturn(true).when(mDeps).isConfigForIdentifiedCarrier(any());
+        doReturn(Arrays.asList(TEST_SUBINFO_1, TEST_SUBINFO_2))
+                .when(mSubscriptionManager)
+                .getAllSubscriptionInfoList();
+    }
+
+    private IntentFilter getIntentFilter() {
+        final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
+        verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+
+        return captor.getValue();
+    }
+
+    private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() {
+        final ArgumentCaptor<OnSubscriptionsChangedListener> captor =
+                ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
+        verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), captor.capture());
+
+        return captor.getValue();
+    }
+
+    private Intent buildTestBroadcastIntent(boolean hasValidSubscription) {
+        Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED);
+        intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX);
+        intent.putExtra(
+                EXTRA_SUBSCRIPTION_INDEX,
+                hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID);
+
+        return intent;
+    }
+
+    private TelephonySubscriptionSnapshot buildExpectedSnapshot(Set<ParcelUuid> activeSubGroups) {
+        return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, activeSubGroups);
+    }
+
+    private TelephonySubscriptionSnapshot buildExpectedSnapshot(
+            Map<Integer, ParcelUuid> subIdToGroupMap, Set<ParcelUuid> activeSubGroups) {
+        return new TelephonySubscriptionSnapshot(subIdToGroupMap, activeSubGroups);
+    }
+
+    private void verifyNoActiveSubscriptions() {
+        verify(mCallback).onNewSnapshot(
+                argThat(snapshot -> snapshot.getActiveSubscriptionGroups().isEmpty()));
+    }
+
+    private void setupReadySubIds() {
+        mTelephonySubscriptionTracker.setReadySubIdsBySlotId(
+                Collections.singletonMap(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1));
+    }
+
+    @Test
+    public void testRegister() throws Exception {
+        verify(mContext)
+                .registerReceiver(
+                        eq(mTelephonySubscriptionTracker),
+                        any(IntentFilter.class),
+                        any(),
+                        eq(mHandler));
+        final IntentFilter filter = getIntentFilter();
+        assertEquals(1, filter.countActions());
+        assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
+
+        verify(mSubscriptionManager)
+                .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any());
+        assertNotNull(getOnSubscriptionsChangedListener());
+    }
+
+    @Test
+    public void testUnregister() throws Exception {
+        mTelephonySubscriptionTracker.unregister();
+
+        verify(mContext).unregisterReceiver(eq(mTelephonySubscriptionTracker));
+
+        final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+        verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
+    }
+
+    @Test
+    public void testOnSubscriptionsChangedFired_NoReadySubIds() throws Exception {
+        final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+        listener.onSubscriptionsChanged();
+        mTestLooper.dispatchAll();
+
+        verifyNoActiveSubscriptions();
+    }
+
+    @Test
+    public void testOnSubscriptionsChangedFired_WithReadySubIds() throws Exception {
+        setupReadySubIds();
+
+        final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+        listener.onSubscriptionsChanged();
+        mTestLooper.dispatchAll();
+
+        final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+        verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+    }
+
+    @Test
+    public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception {
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+
+        final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+        verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+    }
+
+    @Test
+    public void testReceiveBroadcast_ConfigReadyNoSubscriptions() throws Exception {
+        doReturn(new ArrayList<SubscriptionInfo>())
+                .when(mSubscriptionManager)
+                .getAllSubscriptionInfoList();
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+
+        // Expect an empty snapshot
+        verify(mCallback).onNewSnapshot(
+                eq(buildExpectedSnapshot(Collections.emptyMap(), Collections.emptySet())));
+    }
+
+    @Test
+    public void testReceiveBroadcast_SlotCleared() throws Exception {
+        setupReadySubIds();
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false));
+        mTestLooper.dispatchAll();
+
+        verifyNoActiveSubscriptions();
+        assertTrue(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().isEmpty());
+    }
+
+    @Test
+    public void testReceiveBroadcast_ConfigNotReady() throws Exception {
+        doReturn(false).when(mDeps).isConfigForIdentifiedCarrier(any());
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+
+        // No interactions expected; config was not loaded
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    @Test
+    public void testSubscriptionsClearedAfterValidTriggersCallbacks() throws Exception {
+        final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+        verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+        assertNotNull(
+                mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+
+        doReturn(Collections.emptyList()).when(mSubscriptionManager).getAllSubscriptionInfoList();
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+        verify(mCallback).onNewSnapshot(
+                eq(buildExpectedSnapshot(Collections.emptyMap(), Collections.emptySet())));
+    }
+
+    @Test
+    public void testSlotClearedAfterValidTriggersCallbacks() throws Exception {
+        final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+        mTestLooper.dispatchAll();
+        verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+        assertNotNull(
+                mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+
+        mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false));
+        mTestLooper.dispatchAll();
+        verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(Collections.emptySet())));
+        assertNull(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+    }
+
+    @Test
+    public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
+        final TelephonySubscriptionSnapshot snapshot =
+                new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, Collections.emptySet());
+
+        assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
+        assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
+    }
+
+    @Test
+    public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
+        final TelephonySubscriptionSnapshot snapshot =
+                new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, Collections.emptySet());
+
+        assertEquals(
+                new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
+                snapshot.getAllSubIdsInGroup(TEST_PARCEL_UUID));
+    }
+}
diff --git a/tools/aapt/OWNERS b/tools/aapt/OWNERS
new file mode 100644
index 0000000..c232ccd
--- /dev/null
+++ b/tools/aapt/OWNERS
@@ -0,0 +1 @@
+include /tools/aapt2/OWNERS
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index 28330db..d7a8e6f 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -548,14 +548,14 @@
 }
 
 StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx) {
-  if (auto str = pool.stringAt(idx)) {
+  if (auto str = pool.stringAt(idx); str.ok()) {
     return *str;
   }
   return StringPiece16();
 }
 
 std::string GetString(const android::ResStringPool& pool, size_t idx) {
-  if (auto str = pool.string8At(idx)) {
+  if (auto str = pool.string8At(idx); str.ok()) {
     return ModifiedUtf8ToUtf8(str->to_string());
   }
   return Utf16ToUtf8(GetString16(pool, idx));
diff --git a/tools/fonts/OWNERS b/tools/fonts/OWNERS
new file mode 100644
index 0000000..a538331
--- /dev/null
+++ b/tools/fonts/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/graphics/fonts/OWNERS
diff --git a/tools/incident_report/OWNERS b/tools/incident_report/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/tools/incident_report/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/tools/incident_section_gen/OWNERS b/tools/incident_section_gen/OWNERS
new file mode 100644
index 0000000..f766115
--- /dev/null
+++ b/tools/incident_section_gen/OWNERS
@@ -0,0 +1 @@
+include /cmds/incidentd/OWNERS
diff --git a/tools/powerstats/OWNERS b/tools/powerstats/OWNERS
new file mode 100644
index 0000000..d68066b
--- /dev/null
+++ b/tools/powerstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/power/OWNERS
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/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/Android.bp b/wifi/Android.bp
index 7a9ca60..07b2ea9 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -31,9 +31,6 @@
         "java/**/*.java",
         "java/**/*.aidl",
     ],
-    exclude_srcs: [
-        ":framework-wifi-non-updatable-sources"
-    ],
     path: "java",
     visibility: ["//visibility:private"],
 }
@@ -43,20 +40,7 @@
     srcs: [
         ":framework-wifi-updatable-java-sources",
         ":framework-wifi-updatable-exported-aidl-sources",
-    ],
-}
-
-filegroup {
-    name: "framework-wifi-non-updatable-sources",
-    srcs: [
-        // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
-        // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
-        // to a separate package.
-        "java/android/net/wifi/SoftApConfToXmlMigrationUtil.java",
-        "java/android/net/wifi/WifiNetworkScoreCache.java",
-        "java/android/net/wifi/WifiMigration.java",
-        "java/android/net/wifi/nl80211/*.java",
-        ":libwificond_ipc_aidl",
+        ":module-utils-os-aidls",
     ],
 }
 
@@ -68,6 +52,7 @@
 // list of tests that are allowed to access @hide APIs from framework-wifi
 test_access_hidden_api_whitelist = [
     "//frameworks/base/wifi/tests",
+    "//frameworks/base/wifi/non-updatable/tests",
     "//frameworks/opt/net/wifi/tests/wifitests:__subpackages__",
 
     "//external/robolectric-shadows:__subpackages__",
@@ -85,13 +70,14 @@
         "framework-wifi-util-lib",
         "android.hardware.wifi-V1.0-java-constants",
         "modules-utils-build",
+        "modules-utils-os",
     ],
     libs: [
         "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
     ],
     srcs: [
         ":framework-wifi-updatable-sources",
-        ":framework-wifi-util-lib-aidls",
+        ":module-utils-os-aidls",
     ],
 }
 
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index e11b33e..1ece79a 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -35,6 +35,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR;
     field public String SSID;
     field public static final int WIFI_STANDARD_11AC = 5; // 0x5
+    field public static final int WIFI_STANDARD_11AD = 7; // 0x7
     field public static final int WIFI_STANDARD_11AX = 6; // 0x6
     field public static final int WIFI_STANDARD_11N = 4; // 0x4
     field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1
@@ -309,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);
@@ -359,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);
@@ -459,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();
@@ -1156,7 +1163,11 @@
 
   public final class RangingRequest implements android.os.Parcelable {
     method public int describeContents();
+    method public static int getDefaultRttBurstSize();
     method public static int getMaxPeers();
+    method public static int getMaxRttBurstSize();
+    method public static int getMinRttBurstSize();
+    method public int getRttBurstSize();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR;
   }
@@ -1168,6 +1179,7 @@
     method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.MacAddress);
     method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.wifi.aware.PeerHandle);
     method public android.net.wifi.rtt.RangingRequest build();
+    method @NonNull public android.net.wifi.rtt.RangingRequest.Builder setRttBurstSize(int);
   }
 
   public final class RangingResult implements android.os.Parcelable {
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index eba7443..257f9d5 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -277,6 +277,7 @@
     method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration();
     field public static final int BAND_2GHZ = 1; // 0x1
     field public static final int BAND_5GHZ = 2; // 0x2
+    field public static final int BAND_60GHZ = 8; // 0x8
     field public static final int BAND_6GHZ = 4; // 0x4
     field @Deprecated public static final int BAND_ANY = 7; // 0x7
     field public static final int RANDOMIZATION_NONE = 0; // 0x0
@@ -314,9 +315,13 @@
     field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
     field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
     field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+    field public static final int CHANNEL_WIDTH_2160MHZ = 7; // 0x7
     field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+    field public static final int CHANNEL_WIDTH_4320MHZ = 8; // 0x8
+    field public static final int CHANNEL_WIDTH_6480MHZ = 9; // 0x9
     field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
     field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+    field public static final int CHANNEL_WIDTH_8640MHZ = 10; // 0xa
     field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
   }
@@ -393,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
@@ -495,6 +502,7 @@
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback);
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) public void restartWifiSubsystem(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]);
     method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
@@ -519,11 +527,11 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp();
-    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void stopTemporarilyDisablingAllNonCarrierMergedWifi();
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopTemporarilyDisablingAllNonCarrierMergedWifi();
     method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void unregisterCoexCallback(@NonNull android.net.wifi.WifiManager.CoexCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback);
@@ -632,6 +640,7 @@
     method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
     method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
     method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
+    method public default void onInfoListChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>);
     method public default void onStateChanged(int, int);
   }
 
@@ -957,6 +966,10 @@
 
 package android.net.wifi.rtt {
 
+  public final class RangingRequest implements android.os.Parcelable {
+    method @NonNull public java.util.List<android.net.wifi.rtt.ResponderConfig> getRttPeers();
+  }
+
   public static final class RangingRequest.Builder {
     method public android.net.wifi.rtt.RangingRequest.Builder addResponder(@NonNull android.net.wifi.rtt.ResponderConfig);
   }
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index dc96df6..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
@@ -110,8 +110,6 @@
 rule fi.iki.elonen.** com.android.wifi.x.@0
 
 ## used by both framework-wifi and service-wifi ##
-rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0
-rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0
 rule android.os.HandlerExecutor* com.android.wifi.x.@0
 rule android.telephony.Annotation* com.android.wifi.x.@0
 rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index f81bcb9..a28a8fb 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -53,6 +53,12 @@
      */
     void onInfoChanged(in SoftApInfo softApInfo);
 
+    /**
+     * Service to manager callback providing informations of softap.
+     *
+     * @param softApInfoList is the list of the softap informations. {@link SoftApInfo}
+     */
+    void onInfoListChanged(in List<SoftApInfo> softApInfoList);
 
     /**
      * Service to manager callback providing capability of softap.
diff --git a/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
new file mode 100644
index 0000000..5aa3a90
--- /dev/null
+++ b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.wifi;
+
+/**
+ * Interface for suggestion user approval status listener.
+ *
+ * @hide
+ */
+oneway interface ISuggestionUserApprovalStatusListener
+{
+   void onUserApprovalStatusChange();
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 866e913..23f47ef 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -16,8 +16,6 @@
 
 package android.net.wifi;
 
-import android.content.pm.ParceledListSlice;
-
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.IProvisioningCallback;
@@ -35,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;
@@ -47,6 +46,8 @@
 import android.os.ResultReceiver;
 import android.os.WorkSource;
 
+import com.android.modules.utils.ParceledListSlice;
+
 /**
  * Interface that allows controlling and querying Wi-Fi connectivity.
  *
@@ -146,6 +147,8 @@
 
     void updateInterfaceIpState(String ifaceName, int mode);
 
+    boolean isDefaultCoexAlgorithmEnabled();
+
     void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions);
 
     List<CoexUnsafeChannel> getCoexUnsafeChannels();
@@ -300,4 +303,10 @@
     void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled);
 
     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/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 4c23286..9f8ecf1 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -320,6 +320,11 @@
     public static final int WIFI_STANDARD_11AX = 6;
 
     /**
+     * Wi-Fi 802.11ad/ay
+     */
+    public static final int WIFI_STANDARD_11AD = 7;
+
+    /**
      * AP wifi standard.
      */
     private @WifiStandard int mWifiStandard;
@@ -352,6 +357,8 @@
                 return "11ac";
             case WIFI_STANDARD_11AX:
                 return "11ax";
+            case WIFI_STANDARD_11AD:
+                return "11ad";
             case WIFI_STANDARD_UNKNOWN:
                 return "unknown";
         }
@@ -705,6 +712,13 @@
                 return UNSPECIFIED;
             }
         }
+        if (band == WifiScanner.WIFI_BAND_60_GHZ) {
+            if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) {
+                return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ;
+            } else {
+                return UNSPECIFIED;
+            }
+        }
         return UNSPECIFIED;
     }
 
diff --git a/wifi/java/android/net/wifi/SecurityParams.java b/wifi/java/android/net/wifi/SecurityParams.java
new file mode 100644
index 0000000..0ab6f57
--- /dev/null
+++ b/wifi/java/android/net/wifi/SecurityParams.java
@@ -0,0 +1,824 @@
+/*
+ * 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.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.GroupCipher;
+import android.net.wifi.WifiConfiguration.GroupMgmtCipher;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
+import android.net.wifi.WifiConfiguration.SecurityType;
+import android.net.wifi.WifiConfiguration.SuiteBCipher;
+import android.os.Parcel;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.BitSet;
+import java.util.Objects;
+
+/**
+ * A class representing a security configuration.
+ * @hide
+ */
+public class SecurityParams {
+    private static final String TAG = "SecurityParams";
+
+    /** Passpoint Release 1 */
+    public static final int PASSPOINT_R1 = 1;
+
+    /** Passpoint Release 2 */
+    public static final int PASSPOINT_R2 = 2;
+
+    /** Passpoint Release 3 */
+    public static final int PASSPOINT_R3 = 3;
+
+    @IntDef(prefix = { "PASSPOINT_" }, value = {
+        PASSPOINT_R1,
+        PASSPOINT_R2,
+        PASSPOINT_R3,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PasspointRelease {}
+
+    private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+
+    /**
+     * This indicates that this security type is enabled or disabled.
+     * Ex. While receiving Transition Disable Indication, older
+     * security should be disabled.
+     */
+    private boolean mEnabled = true;
+
+    /**
+     * The set of key management protocols supported by this configuration.
+     * See {@link KeyMgmt} for descriptions of the values.
+     * This is set automatically based on the security type.
+     */
+    private BitSet mAllowedKeyManagement = new BitSet();
+
+    /**
+     * The set of security protocols supported by this configuration.
+     * See {@link Protocol} for descriptions of the values.
+     * This is set automatically based on the security type.
+     */
+    private BitSet mAllowedProtocols = new BitSet();
+
+    /**
+     * The set of authentication protocols supported by this configuration.
+     * See {@link AuthAlgorithm} for descriptions of the values.
+     * This is set automatically based on the security type.
+     */
+    private BitSet mAllowedAuthAlgorithms = new BitSet();
+
+    /**
+     * The set of pairwise ciphers for WPA supported by this configuration.
+     * See {@link PairwiseCipher} for descriptions of the values.
+     * This is set automatically based on the security type.
+     */
+    private BitSet mAllowedPairwiseCiphers = new BitSet();
+
+    /**
+     * The set of group ciphers supported by this configuration.
+     * See {@link GroupCipher} for descriptions of the values.
+     * This is set automatically based on the security type.
+     */
+    private BitSet mAllowedGroupCiphers = new BitSet();
+
+    /**
+     * The set of group management ciphers supported by this configuration.
+     * See {@link GroupMgmtCipher} for descriptions of the values.
+     */
+    private BitSet mAllowedGroupManagementCiphers = new BitSet();
+
+    /**
+     * The set of SuiteB ciphers supported by this configuration.
+     * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the
+     * certificate type that is used in this configuration.
+     */
+    private BitSet mAllowedSuiteBCiphers = new BitSet();
+
+    /**
+     * True if the network requires Protected Management Frames (PMF), false otherwise.
+     */
+    private boolean mRequirePmf = false;
+
+    private @PasspointRelease int mPasspointRelease = PASSPOINT_R2;
+
+    /** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */
+    private boolean mIsSaeH2eOnlyMode = false;
+
+    /** Indicate that this SAE security type only accepts PK (Public Key) mode. */
+    private boolean mIsSaePkOnlyMode = false;
+
+    /** Indicate whether this is added by auto-upgrade or not. */
+    private boolean mIsAddedByAutoUpgrade = false;
+
+    /** Constructor */
+    private SecurityParams() {
+    }
+
+    /** Copy constructor */
+    public SecurityParams(@NonNull SecurityParams source) {
+        this.mSecurityType = source.mSecurityType;
+        this.mEnabled = source.mEnabled;
+        this.mAllowedKeyManagement = (BitSet) source.mAllowedKeyManagement.clone();
+        this.mAllowedProtocols = (BitSet) source.mAllowedProtocols.clone();
+        this.mAllowedAuthAlgorithms = (BitSet) source.mAllowedAuthAlgorithms.clone();
+        this.mAllowedPairwiseCiphers = (BitSet) source.mAllowedPairwiseCiphers.clone();
+        this.mAllowedGroupCiphers = (BitSet) source.mAllowedGroupCiphers.clone();
+        this.mAllowedGroupManagementCiphers =
+                (BitSet) source.mAllowedGroupManagementCiphers.clone();
+        this.mAllowedSuiteBCiphers =
+                (BitSet) source.mAllowedSuiteBCiphers.clone();
+        this.mRequirePmf = source.mRequirePmf;
+        this.mIsSaeH2eOnlyMode = source.mIsSaeH2eOnlyMode;
+        this.mIsSaePkOnlyMode = source.mIsSaePkOnlyMode;
+        this.mIsAddedByAutoUpgrade = source.mIsAddedByAutoUpgrade;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (!(thatObject instanceof SecurityParams)) {
+            return false;
+        }
+        SecurityParams that = (SecurityParams) thatObject;
+
+        if (this.mSecurityType != that.mSecurityType) return false;
+        if (this.mEnabled != that.mEnabled) return false;
+        if (!this.mAllowedKeyManagement.equals(that.mAllowedKeyManagement)) return false;
+        if (!this.mAllowedProtocols.equals(that.mAllowedProtocols)) return false;
+        if (!this.mAllowedAuthAlgorithms.equals(that.mAllowedAuthAlgorithms)) return false;
+        if (!this.mAllowedPairwiseCiphers.equals(that.mAllowedPairwiseCiphers)) return false;
+        if (!this.mAllowedGroupCiphers.equals(that.mAllowedGroupCiphers)) return false;
+        if (!this.mAllowedGroupManagementCiphers.equals(that.mAllowedGroupManagementCiphers)) {
+            return false;
+        }
+        if (!this.mAllowedSuiteBCiphers.equals(that.mAllowedSuiteBCiphers)) return false;
+        if (this.mRequirePmf != that.mRequirePmf) return false;
+        if (this.mIsSaeH2eOnlyMode != that.mIsSaeH2eOnlyMode) return false;
+        if (this.mIsSaePkOnlyMode != that.mIsSaePkOnlyMode) return false;
+        if (this.mIsAddedByAutoUpgrade != that.mIsAddedByAutoUpgrade) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mSecurityType, mEnabled,
+                mAllowedKeyManagement, mAllowedProtocols, mAllowedAuthAlgorithms,
+                mAllowedPairwiseCiphers, mAllowedGroupCiphers, mAllowedGroupManagementCiphers,
+                mAllowedSuiteBCiphers, mRequirePmf,
+                mIsSaeH2eOnlyMode, mIsSaePkOnlyMode, mIsAddedByAutoUpgrade);
+    }
+
+    /**
+     * Check the security type of this params.
+     *
+     * @param type the testing security type.
+     * @return true if this is for the corresponiding type.
+     */
+    public boolean isSecurityType(@SecurityType int type) {
+        return type == mSecurityType;
+    }
+
+    /**
+     * Check whether the security of given params is the same as this one.
+     *
+     * @param params the testing security params.
+     * @return true if their security types are the same.
+     */
+    public boolean isSameSecurityType(SecurityParams params) {
+        return params.mSecurityType == mSecurityType;
+    }
+
+    /**
+     * Update security params to legacy WifiConfiguration object.
+     *
+     * @param config the target configuration.
+     */
+    public void updateLegacyWifiConfiguration(WifiConfiguration config) {
+        config.allowedKeyManagement = (BitSet) mAllowedKeyManagement.clone();
+        config.allowedProtocols = (BitSet) mAllowedProtocols.clone();
+        config.allowedAuthAlgorithms = (BitSet) mAllowedAuthAlgorithms.clone();
+        config.allowedPairwiseCiphers = (BitSet) mAllowedPairwiseCiphers.clone();
+        config.allowedGroupCiphers = (BitSet) mAllowedGroupCiphers.clone();
+        config.allowedGroupManagementCiphers = (BitSet) mAllowedGroupManagementCiphers.clone();
+        config.allowedSuiteBCiphers = (BitSet) mAllowedSuiteBCiphers.clone();
+        config.requirePmf = mRequirePmf;
+    }
+
+    /**
+     * Set this params enabled.
+     *
+     * @param enable enable a specific security type.
+     */
+    public void setEnabled(boolean enable) {
+        mEnabled = enable;
+    }
+
+    /**
+     * Indicate this params is enabled or not.
+     */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Set the supporting Fast Initial Link Set-up (FILS) key management.
+     *
+     * FILS can be applied to all security types.
+     * @param enableFilsSha256 Enable FILS SHA256.
+     * @param enableFilsSha384 Enable FILS SHA256.
+     */
+    public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) {
+        if (enableFilsSha256) {
+            mAllowedKeyManagement.set(KeyMgmt.FILS_SHA256);
+        }
+
+        if (enableFilsSha384) {
+            mAllowedKeyManagement.set(KeyMgmt.FILS_SHA384);
+        }
+    }
+
+    /**
+     * Get the copy of allowed key management.
+     */
+    public BitSet getAllowedKeyManagement() {
+        return (BitSet) mAllowedKeyManagement.clone();
+    }
+
+    /**
+     * Get the copy of allowed protocols.
+     */
+    public BitSet getAllowedProtocols() {
+        return (BitSet) mAllowedProtocols.clone();
+    }
+
+    /**
+     * Get the copy of allowed auth algorithms.
+     */
+    public BitSet getAllowedAuthAlgorithms() {
+        return (BitSet) mAllowedAuthAlgorithms.clone();
+    }
+
+    /**
+     * Get the copy of allowed pairwise ciphers.
+     */
+    public BitSet getAllowedPairwiseCiphers() {
+        return (BitSet) mAllowedPairwiseCiphers.clone();
+    }
+
+    /**
+     * Get the copy of allowed group ciphers.
+     */
+    public BitSet getAllowedGroupCiphers() {
+        return (BitSet) mAllowedGroupCiphers.clone();
+    }
+
+    /**
+     * Get the copy of allowed group management ciphers.
+     */
+    public BitSet getAllowedGroupManagementCiphers() {
+        return (BitSet) mAllowedGroupManagementCiphers.clone();
+    }
+
+    /**
+     * Enable Suite-B ciphers.
+     *
+     * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support.
+     * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support.
+     */
+    public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) {
+        if (enableEcdheEcdsa) {
+            mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_ECDSA);
+        } else {
+            mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_ECDSA);
+        }
+
+        if (enableEcdheRsa) {
+            mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_RSA);
+        } else {
+            mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_RSA);
+        }
+    }
+
+    /**
+     * Get the copy of allowed suite-b ciphers.
+     */
+    public BitSet getAllowedSuiteBCiphers() {
+        return (BitSet) mAllowedSuiteBCiphers.clone();
+    }
+
+    /**
+     * Indicate PMF is required or not.
+     */
+    public boolean isRequirePmf() {
+        return mRequirePmf;
+    }
+
+    /**
+     * Indicate that this is open security type.
+     */
+    public boolean isOpenSecurityType() {
+        return isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)
+                || isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE);
+    }
+
+    /**
+     * Indicate that this is enterprise security type.
+     */
+    public boolean isEnterpriseSecurityType() {
+        return mAllowedKeyManagement.get(KeyMgmt.WPA_EAP)
+                || mAllowedKeyManagement.get(KeyMgmt.IEEE8021X)
+                || mAllowedKeyManagement.get(KeyMgmt.SUITE_B_192)
+                || mAllowedKeyManagement.get(KeyMgmt.WAPI_CERT);
+    }
+
+    /**
+     * Enable Hash-to-Element only mode.
+     *
+     * @param enable set H2E only mode enabled or not.
+     */
+    public void enableSaeH2eOnlyMode(boolean enable) {
+        mIsSaeH2eOnlyMode = enable;
+    }
+
+    /**
+     * Indicate whether this params is H2E only mode.
+     *
+     * @return true if this is H2E only mode params.
+     */
+    public boolean isSaeH2eOnlyMode() {
+        return mIsSaeH2eOnlyMode;
+    }
+    /**
+     * Enable Pubilc-Key only mode.
+     *
+     * @param enable set PK only mode enabled or not.
+     */
+    public void enableSaePkOnlyMode(boolean enable) {
+        mIsSaePkOnlyMode = enable;
+    }
+
+    /**
+     * Indicate whether this params is PK only mode.
+     *
+     * @return true if this is PK only mode params.
+     */
+    public boolean isSaePkOnlyMode() {
+        return mIsSaePkOnlyMode;
+    }
+
+    /**
+     * Set whether this is added by auto-upgrade.
+     *
+     * @param addedByAutoUpgrade true if added by auto-upgrade.
+     */
+    public void setIsAddedByAutoUpgrade(boolean addedByAutoUpgrade) {
+        mIsAddedByAutoUpgrade = addedByAutoUpgrade;
+    }
+
+    /**
+     * Indicate whether this is added by auto-upgrade or not.
+     *
+     * @return true if added by auto-upgrade; otherwise, false.
+     */
+    public boolean isAddedByAutoUpgrade() {
+        return mIsAddedByAutoUpgrade;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sbuf = new StringBuilder();
+        sbuf.append("Security Parameters:\n");
+        sbuf.append(" Type: ").append(mSecurityType).append("\n");
+        sbuf.append(" Enabled: ").append(mEnabled).append("\n");
+        sbuf.append(" KeyMgmt:");
+        for (int k = 0; k < mAllowedKeyManagement.size(); k++) {
+            if (mAllowedKeyManagement.get(k)) {
+                sbuf.append(" ");
+                if (k < KeyMgmt.strings.length) {
+                    sbuf.append(KeyMgmt.strings[k]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" Protocols:");
+        for (int p = 0; p < mAllowedProtocols.size(); p++) {
+            if (mAllowedProtocols.get(p)) {
+                sbuf.append(" ");
+                if (p < Protocol.strings.length) {
+                    sbuf.append(Protocol.strings[p]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" AuthAlgorithms:");
+        for (int a = 0; a < mAllowedAuthAlgorithms.size(); a++) {
+            if (mAllowedAuthAlgorithms.get(a)) {
+                sbuf.append(" ");
+                if (a < AuthAlgorithm.strings.length) {
+                    sbuf.append(AuthAlgorithm.strings[a]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" PairwiseCiphers:");
+        for (int pc = 0; pc < mAllowedPairwiseCiphers.size(); pc++) {
+            if (mAllowedPairwiseCiphers.get(pc)) {
+                sbuf.append(" ");
+                if (pc < PairwiseCipher.strings.length) {
+                    sbuf.append(PairwiseCipher.strings[pc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" GroupCiphers:");
+        for (int gc = 0; gc < mAllowedGroupCiphers.size(); gc++) {
+            if (mAllowedGroupCiphers.get(gc)) {
+                sbuf.append(" ");
+                if (gc < GroupCipher.strings.length) {
+                    sbuf.append(GroupCipher.strings[gc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" GroupMgmtCiphers:");
+        for (int gmc = 0; gmc < mAllowedGroupManagementCiphers.size(); gmc++) {
+            if (mAllowedGroupManagementCiphers.get(gmc)) {
+                sbuf.append(" ");
+                if (gmc < GroupMgmtCipher.strings.length) {
+                    sbuf.append(GroupMgmtCipher.strings[gmc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" SuiteBCiphers:");
+        for (int sbc = 0; sbc < mAllowedSuiteBCiphers.size(); sbc++) {
+            if (mAllowedSuiteBCiphers.get(sbc)) {
+                sbuf.append(" ");
+                if (sbc < SuiteBCipher.strings.length) {
+                    sbuf.append(SuiteBCipher.strings[sbc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" RequirePmf: ").append(mRequirePmf).append('\n');
+        sbuf.append(" IsAddedByAutoUpgrade: ").append(mIsAddedByAutoUpgrade).append("\n");
+        sbuf.append(" IsSaeH2eOnlyMode: ").append(mIsSaeH2eOnlyMode).append("\n");
+        sbuf.append(" IsSaePkOnlyMode: ").append(mIsSaePkOnlyMode).append("\n");
+        return sbuf.toString();
+    }
+
+    private static BitSet readBitSet(Parcel src) {
+        int cardinality = src.readInt();
+
+        BitSet set = new BitSet();
+        for (int i = 0; i < cardinality; i++) {
+            set.set(src.readInt());
+        }
+
+        return set;
+    }
+
+    private static void writeBitSet(Parcel dest, BitSet set) {
+        int nextSetBit = -1;
+
+        dest.writeInt(set.cardinality());
+
+        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
+            dest.writeInt(nextSetBit);
+        }
+    }
+
+    /** Write this object to the parcel. */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSecurityType);
+        dest.writeBoolean(mEnabled);
+        writeBitSet(dest, mAllowedKeyManagement);
+        writeBitSet(dest, mAllowedProtocols);
+        writeBitSet(dest, mAllowedAuthAlgorithms);
+        writeBitSet(dest, mAllowedPairwiseCiphers);
+        writeBitSet(dest, mAllowedGroupCiphers);
+        writeBitSet(dest, mAllowedGroupManagementCiphers);
+        writeBitSet(dest, mAllowedSuiteBCiphers);
+        dest.writeBoolean(mRequirePmf);
+        dest.writeBoolean(mIsAddedByAutoUpgrade);
+        dest.writeBoolean(mIsSaeH2eOnlyMode);
+        dest.writeBoolean(mIsSaePkOnlyMode);
+
+    }
+
+    /** Create a SecurityParams object from the parcel. */
+    public static final @NonNull SecurityParams createFromParcel(Parcel in) {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = in.readInt();
+        params.mEnabled = in.readBoolean();
+        params.mAllowedKeyManagement = readBitSet(in);
+        params.mAllowedProtocols = readBitSet(in);
+        params.mAllowedAuthAlgorithms = readBitSet(in);
+        params.mAllowedPairwiseCiphers = readBitSet(in);
+        params.mAllowedGroupCiphers = readBitSet(in);
+        params.mAllowedGroupManagementCiphers = readBitSet(in);
+        params.mAllowedSuiteBCiphers = readBitSet(in);
+        params.mRequirePmf = in.readBoolean();
+        params.mIsAddedByAutoUpgrade = in.readBoolean();
+        params.mIsSaeH2eOnlyMode = in.readBoolean();
+        params.mIsSaePkOnlyMode = in.readBoolean();
+        return params;
+    }
+
+    /**
+     * Create EAP security params.
+     */
+    public static @NonNull SecurityParams createWpaWpa2EnterpriseParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+        params.mAllowedProtocols.set(Protocol.WPA);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+        return params;
+    }
+
+    /**
+     * Create Passpoint security params.
+     */
+    public static @NonNull SecurityParams createPasspointParams(@PasspointRelease int release) {
+        SecurityParams params = new SecurityParams();
+        switch (release) {
+            case PASSPOINT_R1:
+            case PASSPOINT_R2:
+                params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+                break;
+            case PASSPOINT_R3:
+                params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+                params.mRequirePmf = true;
+                break;
+            default:
+                throw new IllegalArgumentException("invalid passpoint release " + release);
+        }
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+
+        return params;
+    }
+
+    /**
+     * Create Enhanced Open params.
+     */
+    public static @NonNull SecurityParams createEnhancedOpenParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OWE;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.OWE);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+        params.mRequirePmf = true;
+        return params;
+    }
+
+    /**
+     * Create Open params.
+     */
+    public static @NonNull SecurityParams createOpenParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.NONE);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+        params.mAllowedProtocols.set(Protocol.WPA);
+        return params;
+    }
+
+    /**
+     * Create OSEN params.
+     */
+    public static @NonNull SecurityParams createOsenParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.OSEN);
+
+        params.mAllowedProtocols.set(Protocol.OSEN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+        return params;
+    }
+
+    /**
+     * Create WAPI-CERT params.
+     */
+    public static @NonNull SecurityParams createWapiCertParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WAPI_CERT);
+
+        params.mAllowedProtocols.set(Protocol.WAPI);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.SMS4);
+        return params;
+    }
+
+    /**
+     * Create WAPI-PSK params.
+     */
+    public static @NonNull SecurityParams createWapiPskParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WAPI_PSK);
+
+        params.mAllowedProtocols.set(Protocol.WAPI);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.SMS4);
+        return params;
+    }
+
+    /**
+     * Create WEP params.
+     */
+    public static @NonNull SecurityParams createWepParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WEP;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.NONE);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+        params.mAllowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+        params.mAllowedGroupCiphers.set(GroupCipher.WEP40);
+        params.mAllowedGroupCiphers.set(GroupCipher.WEP104);
+        return params;
+    }
+
+    /**
+     * Create WPA3 Enterprise 192-bit params.
+     */
+    public static @NonNull SecurityParams createWpa3Enterprise192BitParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+        params.mAllowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+        params.mAllowedGroupManagementCiphers.set(GroupMgmtCipher.BIP_GMAC_256);
+
+        // Note: allowedSuiteBCiphers bitset will be set by the service once the
+        // certificates are attached to this profile
+
+        params.mRequirePmf = true;
+        return params;
+    }
+
+    /**
+     * Create WPA3 Enterprise params.
+     */
+    public static @NonNull SecurityParams createWpa3EnterpriseParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+        params.mRequirePmf = true;
+        return params;
+    }
+
+    /**
+     * Create WPA3 Personal params.
+     */
+    public static @NonNull SecurityParams createWpa3PersonalParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_SAE;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.SAE);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+        params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+        params.mRequirePmf = true;
+        return params;
+    }
+
+    /**
+     * Create WPA/WPA2 Personal params.
+     */
+    public static @NonNull SecurityParams createWpaWpa2PersonalParams() {
+        SecurityParams params = new SecurityParams();
+        params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+
+        params.mAllowedKeyManagement.set(KeyMgmt.WPA_PSK);
+
+        params.mAllowedProtocols.set(Protocol.RSN);
+        params.mAllowedProtocols.set(Protocol.WPA);
+
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+        params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+        params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+        params.mAllowedGroupCiphers.set(GroupCipher.WEP40);
+        params.mAllowedGroupCiphers.set(GroupCipher.WEP104);
+        return params;
+    }
+}
diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java
index d570b7e..6f72f0b 100644
--- a/wifi/java/android/net/wifi/SoftApCapability.java
+++ b/wifi/java/android/net/wifi/SoftApCapability.java
@@ -116,6 +116,11 @@
     private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY;
 
     /**
+     * A list storing supported 60G channels.
+     */
+    private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY;
+
+    /**
      * Get the maximum supported client numbers which AP resides on.
      */
     public int getMaxSupportedClients() {
@@ -147,8 +152,8 @@
      * Set supported channel list in target band type.
      *
      * @param band One of the following band types:
-     * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or
-     * {@link SoftApConfiguation#BAND_6GHZ}.
+     * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ},
+     * {@link SoftApConfiguation#BAND_6GHZ}, or {@link SoftApConfiguation#BAND_60GHZ}.
      * @param  supportedChannelList supported channel list in target band
      * @return true if band and supportedChannelList are valid, otherwise false.
      *
@@ -168,6 +173,9 @@
             case SoftApConfiguration.BAND_6GHZ:
                 mSupportedChannelListIn6g = supportedChannelList;
                 break;
+            case SoftApConfiguration.BAND_60GHZ:
+                mSupportedChannelListIn60g = supportedChannelList;
+                break;
             default:
                 throw new IllegalArgumentException("Invalid band: " + band);
         }
@@ -181,8 +189,8 @@
      * {@link SoftapConfiguration.Builder#setChannel(int, int)} API.
      *
      * @param band One of the following band types:
-     * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or
-     * {@link SoftApConfiguation#BAND_6GHZ}.
+     * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ},
+     * {@link SoftApConfiguation#BAND_6GHZ}, {@link SoftApConfiguation#BAND_60GHZ}.
      * @return List of supported channels for the band.
      *
      * @throws IllegalArgumentException when band type is invalid.
@@ -199,6 +207,8 @@
                 return mSupportedChannelListIn5g;
             case SoftApConfiguration.BAND_6GHZ:
                 return mSupportedChannelListIn6g;
+            case SoftApConfiguration.BAND_60GHZ:
+                return mSupportedChannelListIn60g;
             default:
                 throw new IllegalArgumentException("Invalid band: " + band);
         }
@@ -214,6 +224,7 @@
             mSupportedChannelListIn24g = source.mSupportedChannelListIn24g;
             mSupportedChannelListIn5g = source.mSupportedChannelListIn5g;
             mSupportedChannelListIn6g = source.mSupportedChannelListIn6g;
+            mSupportedChannelListIn60g = source.mSupportedChannelListIn60g;
         }
     }
 
@@ -244,6 +255,7 @@
         dest.writeIntArray(mSupportedChannelListIn24g);
         dest.writeIntArray(mSupportedChannelListIn5g);
         dest.writeIntArray(mSupportedChannelListIn6g);
+        dest.writeIntArray(mSupportedChannelListIn60g);
     }
 
     @NonNull
@@ -255,6 +267,7 @@
             capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray());
             capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray());
             capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray());
+            capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray());
             return capability;
         }
 
@@ -273,6 +286,8 @@
                 .append(Arrays.toString(mSupportedChannelListIn24g));
         sbuf.append("SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g));
         sbuf.append("SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g));
+        sbuf.append("SupportedChannelListIn60g")
+                .append(Arrays.toString(mSupportedChannelListIn60g));
         return sbuf.toString();
     }
 
@@ -285,7 +300,8 @@
                 && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber
                 && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g)
                 && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g)
-                && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g);
+                && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g)
+                && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g);
     }
 
     @Override
@@ -293,6 +309,7 @@
         return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber,
                 Arrays.hashCode(mSupportedChannelListIn24g),
                 Arrays.hashCode(mSupportedChannelListIn5g),
-                Arrays.hashCode(mSupportedChannelListIn6g));
+                Arrays.hashCode(mSupportedChannelListIn6g),
+                Arrays.hashCode(mSupportedChannelListIn60g));
     }
 }
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 226d1a3..d36acb7 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -88,6 +88,13 @@
     public static final int BAND_6GHZ = 1 << 2;
 
     /**
+     * 60GHz band.
+     * @hide
+     */
+    @SystemApi
+    public static final int BAND_60GHZ = 1 << 3;
+
+    /**
      * Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability,
      * operating country code and current radio conditions.
      * @hide
@@ -104,11 +111,13 @@
             BAND_2GHZ,
             BAND_5GHZ,
             BAND_6GHZ,
+            BAND_60GHZ,
     })
     public @interface BandType {}
 
     private static boolean isBandValid(@BandType int band) {
-        return ((band != 0) && ((band & ~BAND_ANY) == 0));
+        int bandAny = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ | BAND_60GHZ;
+        return ((band != 0) && ((band & ~bandAny) == 0));
     }
 
     private static final int MIN_CH_2G_BAND = 1;
@@ -117,6 +126,8 @@
     private static final int MAX_CH_5G_BAND = 196;
     private static final int MIN_CH_6G_BAND = 1;
     private static final int MAX_CH_6G_BAND = 253;
+    private static final int MIN_CH_60G_BAND = 1;
+    private static final int MAX_CH_60G_BAND = 6;
 
 
 
@@ -139,6 +150,13 @@
                     return false;
                 }
                 break;
+
+            case BAND_60GHZ:
+                if (channel < MIN_CH_60G_BAND || channel >  MAX_CH_60G_BAND) {
+                    return false;
+                }
+                break;
+
             default:
                 return false;
         }
@@ -538,15 +556,6 @@
         if (!SdkLevel.isAtLeastS()) {
             throw new UnsupportedOperationException();
         }
-        return getChannelsInternal();
-    }
-
-    /**
-     * Internal version bypassing SdkLevel checks
-     * TODO(b/173791707): find a better way to allow Wifi to call its own new S APIs.
-     * @hide
-     */
-    public @NonNull SparseIntArray getChannelsInternal() {
         return mChannels.clone();
     }
 
@@ -945,6 +954,9 @@
          */
         @NonNull
         public Builder setBands(@NonNull int[] bands) {
+            if (!SdkLevel.isAtLeastS()) {
+                throw new UnsupportedOperationException();
+            }
             if (bands.length == 0 || bands.length > 2) {
                 throw new IllegalArgumentException("Unsupported number of bands("
                         + bands.length + ") configured");
@@ -1036,6 +1048,9 @@
          */
         @NonNull
         public Builder setChannels(@NonNull SparseIntArray channels) {
+            if (!SdkLevel.isAtLeastS()) {
+                throw new UnsupportedOperationException();
+            }
             if (channels.size() == 0 || channels.size() > 2) {
                 throw new IllegalArgumentException("Unsupported number of channels("
                         + channels.size() + ") configured");
diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java
index 55c2f17..e42e786 100644
--- a/wifi/java/android/net/wifi/SoftApInfo.java
+++ b/wifi/java/android/net/wifi/SoftApInfo.java
@@ -86,6 +86,34 @@
      */
     public static final int CHANNEL_WIDTH_160MHZ = 6;
 
+    /**
+     * AP Channel bandwidth is 2160 MHZ.
+     *
+     * @see #getBandwidth()
+     */
+    public static final int CHANNEL_WIDTH_2160MHZ = 7;
+
+    /**
+     * AP Channel bandwidth is 4320 MHZ.
+     *
+     * @see #getBandwidth()
+     */
+    public static final int CHANNEL_WIDTH_4320MHZ = 8;
+
+    /**
+     * AP Channel bandwidth is 6480 MHZ.
+     *
+     * @see #getBandwidth()
+     */
+    public static final int CHANNEL_WIDTH_6480MHZ = 9;
+
+    /**
+     * AP Channel bandwidth is 8640 MHZ.
+     *
+     * @see #getBandwidth()
+     */
+    public static final int CHANNEL_WIDTH_8640MHZ = 10;
+
     /** The frequency which AP resides on.  */
     private int mFrequency = 0;
 
@@ -96,6 +124,10 @@
     @Nullable
     private MacAddress mBssid;
 
+    /** The identifier of the AP instance which AP resides on with current info. */
+    @Nullable
+    private String mApInstanceIdentifier;
+
     /**
      * The operational mode of the AP.
      */
@@ -121,7 +153,9 @@
      *
      * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
      * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
-     * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_INVALID}.
+     * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, {@link #CHANNEL_WIDTH_2160MHZ},
+     * {@link #CHANNEL_WIDTH_4320MHZ}, {@link #CHANNEL_WIDTH_6480MHZ},
+     * {@link #CHANNEL_WIDTH_8640MHZ}, or {@link #CHANNEL_WIDTH_INVALID}.
      */
     @WifiAnnotations.Bandwidth
     public int getBandwidth() {
@@ -183,16 +217,29 @@
         if (!SdkLevel.isAtLeastS()) {
             throw new UnsupportedOperationException();
         }
-        return getWifiStandardInternal();
+        return mWifiStandard;
     }
 
     /**
-     * Internal version bypassing SdkLevel checks
-     * TODO(b/173791707): find a better way to allow Wifi to call its own new S APIs.
+     * Set the AP instance identifier.
      * @hide
      */
-    public @WifiAnnotations.WifiStandard int getWifiStandardInternal() {
-        return mWifiStandard;
+    public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) {
+        mApInstanceIdentifier = apInstanceIdentifier;
+    }
+
+    /**
+     * Get the AP instance identifier.
+     *
+     * The AP instance identifier is a unique identity which can be used to
+     * associate the {@link SoftApInfo} to a specific {@link WifiClient}
+     * - see {@link WifiClient#getApInstanceIdentifier()}
+     *
+     * @hide
+     */
+    @Nullable
+    public String getApInstanceIdentifier() {
+        return mApInstanceIdentifier;
     }
 
     /**
@@ -204,6 +251,7 @@
             mBandwidth = source.mBandwidth;
             mBssid = source.mBssid;
             mWifiStandard = source.mWifiStandard;
+            mApInstanceIdentifier = source.mApInstanceIdentifier;
         }
     }
 
@@ -226,6 +274,7 @@
         dest.writeInt(mBandwidth);
         dest.writeParcelable(mBssid, flags);
         dest.writeInt(mWifiStandard);
+        dest.writeString(mApInstanceIdentifier);
     }
 
     @NonNull
@@ -237,6 +286,7 @@
             info.mBandwidth = in.readInt();
             info.mBssid = in.readParcelable(MacAddress.class.getClassLoader());
             info.mWifiStandard = in.readInt();
+            info.mApInstanceIdentifier = in.readString();
             return info;
         }
 
@@ -254,6 +304,7 @@
         sbuf.append(", frequency= ").append(mFrequency);
         if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString());
         sbuf.append(", wifiStandard= ").append(mWifiStandard);
+        sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier);
         sbuf.append("}");
         return sbuf.toString();
     }
@@ -266,11 +317,12 @@
         return mFrequency == softApInfo.mFrequency
                 && mBandwidth == softApInfo.mBandwidth
                 && Objects.equals(mBssid, softApInfo.mBssid)
-                && mWifiStandard == softApInfo.mWifiStandard;
+                && mWifiStandard == softApInfo.mWifiStandard
+                && Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard);
+        return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier);
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiAnnotations.java b/wifi/java/android/net/wifi/WifiAnnotations.java
index acda7e0..807b40b 100644
--- a/wifi/java/android/net/wifi/WifiAnnotations.java
+++ b/wifi/java/android/net/wifi/WifiAnnotations.java
@@ -57,6 +57,10 @@
             SoftApInfo.CHANNEL_WIDTH_80MHZ,
             SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
             SoftApInfo.CHANNEL_WIDTH_160MHZ,
+            SoftApInfo.CHANNEL_WIDTH_2160MHZ,
+            SoftApInfo.CHANNEL_WIDTH_4320MHZ,
+            SoftApInfo.CHANNEL_WIDTH_6480MHZ,
+            SoftApInfo.CHANNEL_WIDTH_8640MHZ,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Bandwidth {}
@@ -77,6 +81,7 @@
             ScanResult.WIFI_STANDARD_11N,
             ScanResult.WIFI_STANDARD_11AC,
             ScanResult.WIFI_STANDARD_11AX,
+            ScanResult.WIFI_STANDARD_11AD,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface WifiStandard{}
diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java
index 3794566..85e2b33 100644
--- a/wifi/java/android/net/wifi/WifiClient.java
+++ b/wifi/java/android/net/wifi/WifiClient.java
@@ -30,6 +30,9 @@
 
     private final MacAddress mMacAddress;
 
+    /** The identifier of the AP instance which the client connected. */
+    private final String mApInstanceIdentifier;
+
     /**
      * The mac address of this client.
      */
@@ -38,15 +41,30 @@
         return mMacAddress;
     }
 
+    /**
+     * Get AP instance identifier.
+     *
+     * The AP instance identifier is a unique identity which can be used to
+     * associate the {@link SoftApInfo} to a specific {@link WifiClient}
+     * - see {@link SoftApInfo#getApInstanceIdentifier()}
+     * @hide
+     */
+    @NonNull
+    public String getApInstanceIdentifier() {
+        return mApInstanceIdentifier;
+    }
+
     private WifiClient(Parcel in) {
         mMacAddress = in.readParcelable(null);
+        mApInstanceIdentifier = in.readString();
     }
 
     /** @hide */
-    public WifiClient(@NonNull MacAddress macAddress) {
+    public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) {
         Objects.requireNonNull(macAddress, "mMacAddress must not be null.");
 
         this.mMacAddress = macAddress;
+        this.mApInstanceIdentifier = apInstanceIdentifier;
     }
 
     @Override
@@ -57,6 +75,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelable(mMacAddress, flags);
+        dest.writeString(mApInstanceIdentifier);
     }
 
     @NonNull
@@ -75,6 +94,7 @@
     public String toString() {
         return "WifiClient{"
                 + "mMacAddress=" + mMacAddress
+                + "mApInstanceIdentifier=" + mApInstanceIdentifier
                 + '}';
     }
 
@@ -83,13 +103,12 @@
         if (this == o) return true;
         if (!(o instanceof WifiClient)) return false;
         WifiClient client = (WifiClient) o;
-        return mMacAddress.equals(client.mMacAddress);
+        return Objects.equals(mMacAddress, client.mMacAddress)
+                && mApInstanceIdentifier.equals(client.mApInstanceIdentifier);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mMacAddress);
+        return Objects.hash(mMacAddress, mApInstanceIdentifier);
     }
 }
-
-
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 85b3170..ba4a54f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.PackageManager;
@@ -46,10 +47,13 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * A class representing a configured Wi-Fi network, including the
@@ -250,6 +254,11 @@
          */
         public static final int WAPI = 3;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {WPA, RSN, OSEN, WAPI})
+        public @interface ProtocolScheme {};
+
         public static final String varName = "proto";
 
         public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" };
@@ -274,6 +283,11 @@
         /** SAE (Used only for WPA3-Personal) */
         public static final int SAE = 3;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {OPEN, SHARED, LEAP, SAE})
+        public @interface AuthAlgorithmScheme {};
+
         public static final String varName = "auth_alg";
 
         public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" };
@@ -308,6 +322,10 @@
          */
         public static final int GCMP_128 = 5;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128})
+        public @interface PairwiseCipherScheme {};
 
         public static final String varName = "pairwise";
 
@@ -359,6 +377,11 @@
          */
         public static final int GCMP_128 = 7;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128})
+        public @interface GroupCipherScheme {};
+
         public static final String varName = "group";
 
         public static final String[] strings =
@@ -387,9 +410,16 @@
         /** GMAC-256 = Galois Message Authentication Code */
         public static final int BIP_GMAC_256 = 2;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256})
+        public @interface GroupMgmtCipherScheme {};
+
         private static final String varName = "groupMgmt";
 
-        private static final String[] strings = { "BIP_CMAC_256",
+        /** @hide */
+        @SuppressLint("AllUpper")
+        public static final @NonNull String[] strings = { "BIP_CMAC_256",
                 "BIP_GMAC_128", "BIP_GMAC_256"};
     }
 
@@ -410,9 +440,16 @@
         /** Diffie-Hellman with_RSA signature */
         public static final int ECDHE_RSA = 1;
 
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA})
+        public @interface SuiteBCipherScheme {};
+
         private static final String varName = "SuiteB";
 
-        private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
+        /** @hide */
+        @SuppressLint("AllUpper")
+        public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
     }
 
     /** Possible status of a network configuration. */
@@ -460,6 +497,25 @@
     public static final int SECURITY_TYPE_WAPI_CERT = 8;
     /** Security type for a WPA3-Enterprise network. */
     public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9;
+    /**
+     * Security type for an OSEN network.
+     * @hide
+     */
+    public static final int SECURITY_TYPE_OSEN = 10;
+    /**
+     * Security type for a Passpoint R1/R2 network.
+     * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed.
+     * @hide
+     */
+    public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11;
+
+    /**
+     * Security type for a Passpoint R3 network.
+     * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed,
+     * and PMF must be set to Required.
+     * @hide
+     */
+    public static final int SECURITY_TYPE_PASSPOINT_R3 = 12;
 
     /**
      * Security types we support.
@@ -478,12 +534,57 @@
             SECURITY_TYPE_WAPI_CERT,
             SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
             SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+            SECURITY_TYPE_PASSPOINT_R1_R2,
+            SECURITY_TYPE_PASSPOINT_R3,
     })
     public @interface SecurityType {}
 
+    private List<SecurityParams> mSecurityParamsList = new ArrayList<>();
+
+    private void updateLegacySecurityParams() {
+        if (mSecurityParamsList.isEmpty()) return;
+        mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this);
+    }
+
     /**
      * Set the various security params to correspond to the provided security type.
      * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
+     * <br>
+     * This API would clear existing security types and add a default one.
+     *
+     * @param securityType One of the following security types:
+     * {@link #SECURITY_TYPE_OPEN},
+     * {@link #SECURITY_TYPE_WEP},
+     * {@link #SECURITY_TYPE_PSK},
+     * {@link #SECURITY_TYPE_EAP},
+     * {@link #SECURITY_TYPE_SAE},
+     * {@link #SECURITY_TYPE_OWE},
+     * {@link #SECURITY_TYPE_WAPI_PSK},
+     * {@link #SECURITY_TYPE_WAPI_CERT},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+     */
+    public void setSecurityParams(@SecurityType int securityType) {
+        // Clear existing data.
+        mSecurityParamsList = new ArrayList<>();
+        addSecurityParams(securityType);
+    }
+
+    /**
+     * Add the various security params.
+     * <br>
+     * This API would clear existing security types and add a default one.
+     * @hide
+     */
+    public void setSecurityParams(SecurityParams params) {
+        // Clear existing data.
+        mSecurityParamsList = new ArrayList<>();
+        addSecurityParams(params);
+    }
+
+    /**
+     * Add the various security params to correspond to the provided security type.
+     * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
      *
      * @param securityType One of the following security types:
      * {@link #SECURITY_TYPE_OPEN},
@@ -491,103 +592,324 @@
      * {@link #SECURITY_TYPE_PSK},
      * {@link #SECURITY_TYPE_EAP},
      * {@link #SECURITY_TYPE_SAE},
-     * {@link #SECURITY_TYPE_EAP_SUITE_B},
      * {@link #SECURITY_TYPE_OWE},
      * {@link #SECURITY_TYPE_WAPI_PSK},
      * {@link #SECURITY_TYPE_WAPI_CERT},
      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
-     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+     *
+     * @hide
      */
-    public void setSecurityParams(@SecurityType int securityType) {
-        // Clear all the bitsets.
-        allowedKeyManagement.clear();
-        allowedProtocols.clear();
-        allowedAuthAlgorithms.clear();
-        allowedPairwiseCiphers.clear();
-        allowedGroupCiphers.clear();
-        allowedGroupManagementCiphers.clear();
-        allowedSuiteBCiphers.clear();
-
+    public void addSecurityParams(@SecurityType int securityType) {
+        // This ensures that there won't be duplicate security types.
+        if (mSecurityParamsList.stream().anyMatch(params -> params.isSecurityType(securityType))) {
+            throw new IllegalArgumentException("duplicate security type " + securityType);
+        }
+        SecurityParams params = null;
         switch (securityType) {
             case SECURITY_TYPE_OPEN:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                params = SecurityParams.createOpenParams();
                 break;
             case SECURITY_TYPE_WEP:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
-                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+                params = SecurityParams.createWepParams();
                 break;
             case SECURITY_TYPE_PSK:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                params = SecurityParams.createWpaWpa2PersonalParams();
                 break;
             case SECURITY_TYPE_EAP:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                params = SecurityParams.createWpaWpa2EnterpriseParams();
                 break;
             case SECURITY_TYPE_SAE:
-                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                requirePmf = true;
+                params = SecurityParams.createWpa3PersonalParams();
                 break;
             // The value of {@link SECURITY_TYPE_EAP_SUITE_B} is the same as
-            // {@link SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid
+            // {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid
             // duplicate case label errors.
             case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
-                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
-                // Note: allowedSuiteBCiphers bitset will be set by the service once the
-                // certificates are attached to this profile
-                requirePmf = true;
+                params = SecurityParams.createWpa3Enterprise192BitParams();
                 break;
             case SECURITY_TYPE_OWE:
-                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                requirePmf = true;
+                params = SecurityParams.createEnhancedOpenParams();
                 break;
             case SECURITY_TYPE_WAPI_PSK:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK);
-                allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
+                params = SecurityParams.createWapiPskParams();
                 break;
             case SECURITY_TYPE_WAPI_CERT:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT);
-                allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
+                params = SecurityParams.createWapiCertParams();
                 break;
             case SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
-                allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-                requirePmf = true;
+                params = SecurityParams.createWpa3EnterpriseParams();
+                break;
+            case SECURITY_TYPE_OSEN:
+                params = SecurityParams.createOsenParams();
+                break;
+            case SECURITY_TYPE_PASSPOINT_R1_R2:
+                params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2);
+                break;
+            case SECURITY_TYPE_PASSPOINT_R3:
+                params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3);
                 break;
             default:
                 throw new IllegalArgumentException("unknown security type " + securityType);
         }
+
+        addSecurityParams(params);
+    }
+
+    /** @hide */
+    public void addSecurityParams(@NonNull SecurityParams newParams) {
+        if (mSecurityParamsList.stream().anyMatch(params -> params.isSameSecurityType(newParams))) {
+            throw new IllegalArgumentException("duplicate security params " + newParams);
+        }
+        if (!mSecurityParamsList.isEmpty()) {
+            if (newParams.isEnterpriseSecurityType() && !isEnterprise()) {
+                throw new IllegalArgumentException(
+                        "An enterprise security type cannot be added to a personal configuation.");
+            }
+            if (!newParams.isEnterpriseSecurityType() && isEnterprise()) {
+                throw new IllegalArgumentException(
+                        "A personal security type cannot be added to an enterprise configuation.");
+            }
+            if (newParams.isOpenSecurityType() && !isOpenNetwork()) {
+                throw new IllegalArgumentException(
+                        "An open security type cannot be added to a non-open configuation.");
+            }
+            if (!newParams.isOpenSecurityType() && isOpenNetwork()) {
+                throw new IllegalArgumentException(
+                        "A non-open security type cannot be added to an open configuation.");
+            }
+            if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) {
+                throw new IllegalArgumentException(
+                        "An OSEN security type must be the only one type.");
+            }
+        }
+        mSecurityParamsList.add(new SecurityParams(newParams));
+        updateLegacySecurityParams();
+    }
+
+    /**
+     * If there is no security params, generate one according to legacy fields.
+     * @hide
+     */
+    public void convertLegacyFieldsToSecurityParamsIfNeeded() {
+        if (!mSecurityParamsList.isEmpty()) return;
+
+        if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
+            setSecurityParams(SECURITY_TYPE_WAPI_CERT);
+        } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
+            setSecurityParams(SECURITY_TYPE_WAPI_PSK);
+        } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+            setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+        } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+            setSecurityParams(SECURITY_TYPE_OWE);
+        } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+            setSecurityParams(SECURITY_TYPE_SAE);
+        } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
+            setSecurityParams(SECURITY_TYPE_OSEN);
+        } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
+            setSecurityParams(SECURITY_TYPE_PSK);
+        } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
+            if (requirePmf) {
+                setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+            } else {
+                setSecurityParams(SECURITY_TYPE_EAP);
+            }
+        } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+            setSecurityParams(SECURITY_TYPE_PSK);
+        } else if (allowedKeyManagement.get(KeyMgmt.NONE)) {
+            if (hasWepKeys()) {
+                setSecurityParams(SECURITY_TYPE_WEP);
+            } else {
+                setSecurityParams(SECURITY_TYPE_OPEN);
+            }
+        } else {
+            setSecurityParams(SECURITY_TYPE_OPEN);
+        }
+    }
+
+    /**
+     * Disable the various security params to correspond to the provided security type.
+     * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
+     *
+     * @param securityType One of the following security types:
+     * {@link #SECURITY_TYPE_OPEN},
+     * {@link #SECURITY_TYPE_WEP},
+     * {@link #SECURITY_TYPE_PSK},
+     * {@link #SECURITY_TYPE_EAP},
+     * {@link #SECURITY_TYPE_SAE},
+     * {@link #SECURITY_TYPE_OWE},
+     * {@link #SECURITY_TYPE_WAPI_PSK},
+     * {@link #SECURITY_TYPE_WAPI_CERT},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+     *
+     * @hide
+     */
+    public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) {
+        mSecurityParamsList.stream()
+                .filter(params -> params.isSecurityType(securityType))
+                .findAny()
+                .ifPresent(params -> params.setEnabled(enable));
+    }
+
+    /**
+     * Get the specific security param.
+     *
+     * @param securityType One of the following security types:
+     * {@link #SECURITY_TYPE_OPEN},
+     * {@link #SECURITY_TYPE_WEP},
+     * {@link #SECURITY_TYPE_PSK},
+     * {@link #SECURITY_TYPE_EAP},
+     * {@link #SECURITY_TYPE_SAE},
+     * {@link #SECURITY_TYPE_OWE},
+     * {@link #SECURITY_TYPE_WAPI_PSK},
+     * {@link #SECURITY_TYPE_WAPI_CERT},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+     *
+     * @return the copy of specific security params if found; otherwise null.
+     * @hide
+     */
+    public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) {
+        SecurityParams p = mSecurityParamsList.stream()
+                .filter(params -> params.isSecurityType(securityType))
+                .findAny()
+                .orElse(null);
+        return (p != null) ? new SecurityParams(p) : null;
+    }
+
+    /**
+     * Indicate whether this configuration is the specific security type.
+     *
+     * @param securityType One of the following security types:
+     * {@link #SECURITY_TYPE_OPEN},
+     * {@link #SECURITY_TYPE_WEP},
+     * {@link #SECURITY_TYPE_PSK},
+     * {@link #SECURITY_TYPE_EAP},
+     * {@link #SECURITY_TYPE_SAE},
+     * {@link #SECURITY_TYPE_OWE},
+     * {@link #SECURITY_TYPE_WAPI_PSK},
+     * {@link #SECURITY_TYPE_WAPI_CERT},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+     * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+     *
+     * @return true if there is a security params matches the type.
+     * @hide
+     */
+    public boolean isSecurityType(@SecurityType int securityType) {
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.isSecurityType(securityType));
+    }
+
+    /**
+     * Get the security params list of this configuration.
+     *
+     * The returning list is a priority list, the first is the lowest priority and default one.
+     *
+     * @return this list of security params.
+     * @hide
+     */
+    public List<SecurityParams> getSecurityParamsList() {
+        return Collections.unmodifiableList(mSecurityParamsList);
+    }
+
+    /**
+     * Enable the support of Fast Initial Link Set-up (FILS).
+     *
+     * FILS can be applied to all security types.
+     * @param enableFilsSha256 Enable FILS SHA256.
+     * @param enableFilsSha384 Enable FILS SHA256.
+     * @hide
+     */
+    public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) {
+        mSecurityParamsList.stream()
+                .forEach(params -> params.enableFils(enableFilsSha256, enableFilsSha384));
+        updateLegacySecurityParams();
+    }
+
+    /**
+     * Indicate FILS SHA256 is enabled.
+     *
+     * @return true if FILS SHA256 is enabled.
+     * @hide
+     */
+    public boolean isFilsSha256Enabled() {
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256));
+    }
+
+    /**
+     * Indicate FILS SHA384 is enabled.
+     *
+     * @return true if FILS SHA384 is enabled.
+     * @hide
+     */
+    public boolean isFilsSha384Enabled() {
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384));
+    }
+
+    /**
+     * Enable Suite-B ciphers.
+     *
+     * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support.
+     * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support.
+     * @hide
+     */
+    public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) {
+        mSecurityParamsList.stream()
+                .filter(params -> params.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT))
+                .findAny()
+                .ifPresent(params -> params.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa));
+        updateLegacySecurityParams();
+    }
+
+    /**
+     * Indicate ECDHE_ECDSA is enabled.
+     *
+     * @return true if enabled.
+     * @hide
+     */
+    public boolean isSuiteBCipherEcdheEcdsaEnabled() {
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA));
+    }
+
+    /**
+     * Indicate ECDHE_RSA is enabled.
+     *
+     * @return true if enabled.
+     * @hide
+     */
+    public boolean isSuiteBCipherEcdheRsaEnabled() {
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA));
+    }
+
+    /**
+     * Set SAE Hash-toElement only mode enabled.
+     *
+     * @param enable true if enabled; false otherwise.
+     * @hide
+     */
+    public void enableSaeH2eOnlyMode(boolean enable) {
+        mSecurityParamsList.stream()
+                .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE))
+                .findAny()
+                .ifPresent(params -> params.enableSaeH2eOnlyMode(enable));
+    }
+
+    /**
+     * Set SAE Public-Key only mode enabled.
+     *
+     * @param enable true if enabled; false otherwise.
+     * @hide
+     */
+    public void enableSaePkOnlyMode(boolean enable) {
+        mSecurityParamsList.stream()
+                .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE))
+                .findAny()
+                .ifPresent(params -> params.enableSaePkOnlyMode(enable));
     }
 
     /** @hide */
@@ -1161,27 +1483,25 @@
         return metered;
     }
 
-    /**
-     * @hide
-     * Returns true if this WiFi config is for an open network.
-     */
-    public boolean isOpenNetwork() {
-        final int cardinality = allowedKeyManagement.cardinality();
-        final boolean hasNoKeyMgmt = cardinality == 0
-                || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
-                || allowedKeyManagement.get(KeyMgmt.OWE)));
-
-        boolean hasNoWepKeys = true;
-        if (wepKeys != null) {
-            for (int i = 0; i < wepKeys.length; i++) {
-                if (wepKeys[i] != null) {
-                    hasNoWepKeys = false;
-                    break;
-                }
+    /** Check whether wep keys exist. */
+    private boolean hasWepKeys() {
+        if (wepKeys == null) return false;
+        for (int i = 0; i < wepKeys.length; i++) {
+            if (wepKeys[i] != null) {
+                return true;
             }
         }
+        return false;
+    }
 
-        return hasNoKeyMgmt && hasNoWepKeys;
+    /**
+     * @hide
+     * Returns true if this WiFi config is for an Open or Enhanced Open network.
+     */
+    public boolean isOpenNetwork() {
+        boolean hasNonOpenSecurityType = mSecurityParamsList.stream()
+                .anyMatch(params -> !params.isOpenSecurityType());
+        return !hasNonOpenSecurityType && !hasWepKeys();
     }
 
     /**
@@ -1388,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
@@ -1401,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. */
@@ -1420,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
@@ -1564,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;
         }
 
@@ -1638,6 +1982,11 @@
         private String mConnectChoice;
 
         /**
+         * The RSSI when the user made the connectChoice.
+         */
+        private int mConnectChoiceRssi;
+
+        /**
          * Used to cache the temporary candidate during the network selection procedure. It will be
          * kept updating once a new scan result has a higher score than current one
          */
@@ -1748,6 +2097,23 @@
             mConnectChoice = newConnectChoice;
         }
 
+        /**
+         * Associate a RSSI with the user connect choice network.
+         * @param rssi signal strength
+         * @hide
+         */
+        public void setConnectChoiceRssi(int rssi) {
+            mConnectChoiceRssi = rssi;
+        }
+
+        /**
+         * @return returns the RSSI of the last time the user made the connect choice.
+         * @hide
+         */
+        public int getConnectChoiceRssi() {
+            return mConnectChoiceRssi;
+        }
+
         /** Get the current Quality network selection status as a String (for debugging). */
         @NonNull
         public String getNetworkStatusString() {
@@ -2051,6 +2417,7 @@
             setCandidate(source.getCandidate());
             setCandidateScore(source.getCandidateScore());
             setConnectChoice(source.getConnectChoice());
+            setConnectChoiceRssi(source.getConnectChoiceRssi());
             setHasEverConnected(source.hasEverConnected());
             setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
         }
@@ -2068,6 +2435,7 @@
             if (getConnectChoice() != null) {
                 dest.writeInt(CONNECT_CHOICE_EXISTS);
                 dest.writeString(getConnectChoice());
+                dest.writeInt(getConnectChoiceRssi());
             } else {
                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
             }
@@ -2087,6 +2455,7 @@
             setNetworkSelectionBSSID(in.readString());
             if (in.readInt() == CONNECT_CHOICE_EXISTS) {
                 setConnectChoice(in.readString());
+                setConnectChoiceRssi(in.readInt());
             } else {
                 setConnectChoice(null);
             }
@@ -2340,12 +2709,11 @@
      */
     @UnsupportedAppUsage
     public boolean isEnterprise() {
-        return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
-                || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
-                || allowedKeyManagement.get(KeyMgmt.SUITE_B_192)
-                || allowedKeyManagement.get(KeyMgmt.WAPI_CERT))
+        boolean hasEnterpriseSecurityType = mSecurityParamsList.stream()
+                .anyMatch(params -> params.isEnterpriseSecurityType());
+        return (hasEnterpriseSecurityType
                 && enterpriseConfig != null
-                && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
+                && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE);
     }
 
     private static String logTimeOfDay(long millis) {
@@ -2398,6 +2766,8 @@
         }
         if (mNetworkSelectionStatus.getConnectChoice() != null) {
             sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
+            sbuf.append(" connect choice rssi: ")
+                    .append(mNetworkSelectionStatus.getConnectChoiceRssi());
         }
         sbuf.append(" hasEverConnected: ")
                 .append(mNetworkSelectionStatus.hasEverConnected()).append("\n");
@@ -2525,6 +2895,10 @@
             sbuf.append('*');
         }
 
+        sbuf.append("\nSecurityParams List:\n");
+        mSecurityParamsList.stream()
+                .forEach(params -> sbuf.append(params.toString()));
+
         sbuf.append("\nEnterprise config:\n");
         sbuf.append(enterpriseConfig);
 
@@ -2973,6 +3347,7 @@
             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
             allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone();
             allowedSuiteBCiphers    = (BitSet) source.allowedSuiteBCiphers.clone();
+            mSecurityParamsList = new ArrayList(source.mSecurityParamsList);
             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
 
             defaultGwMacAddress = source.defaultGwMacAddress;
@@ -3063,6 +3438,10 @@
         writeBitSet(dest, allowedGroupManagementCiphers);
         writeBitSet(dest, allowedSuiteBCiphers);
 
+        dest.writeInt(mSecurityParamsList.size());
+        mSecurityParamsList.stream()
+                .forEach(params -> params.writeToParcel(dest, flags));
+
         dest.writeParcelable(enterpriseConfig, flags);
 
         dest.writeParcelable(mIpConfiguration, flags);
@@ -3144,6 +3523,11 @@
                 config.allowedGroupManagementCiphers = readBitSet(in);
                 config.allowedSuiteBCiphers   = readBitSet(in);
 
+                int numSecurityParams = in.readInt();
+                for (int i = 0; i < numSecurityParams; i++) {
+                    config.mSecurityParamsList.add(SecurityParams.createFromParcel(in));
+                }
+
                 config.enterpriseConfig = in.readParcelable(null);
                 config.setIpConfiguration(in.readParcelable(null));
                 config.dhcpServer = in.readString();
@@ -3226,9 +3610,10 @@
      * @hide
      */
     public boolean needsPreSharedKey() {
-        return allowedKeyManagement.get(KeyMgmt.WPA_PSK)
-                || allowedKeyManagement.get(KeyMgmt.SAE)
-                || allowedKeyManagement.get(KeyMgmt.WAPI_PSK);
+        return mSecurityParamsList.stream()
+                .anyMatch(params -> params.isSecurityType(SECURITY_TYPE_PSK)
+                        || params.isSecurityType(SECURITY_TYPE_SAE)
+                        || params.isSecurityType(SECURITY_TYPE_WAPI_PSK));
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2b931a3..6496cc7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -34,7 +34,6 @@
 import android.app.ActivityManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.content.pm.ParceledListSlice;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
 import android.net.MacAddress;
@@ -63,6 +62,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.ParceledListSlice;
 import com.android.modules.utils.build.SdkLevel;
 
 import java.lang.annotation.Retention;
@@ -3041,6 +3041,37 @@
     }
 
     /**
+     * Restart the Wi-Fi subsystem.
+     *
+     * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing
+     * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and
+     * Wi-Fi Aware are disabled.
+     *
+     * The state of the system after restart is not guaranteed to match its state before the API is
+     * called - for instance the device may associate to a different Access Point (AP), and tethered
+     * hotspots may or may not be restored.
+     *
+     * @param reason If non-null, requests a bug report and attaches the reason string to it. A bug
+     *               report may still not be generated based on framework criteria - for instance,
+     *               build type or throttling. The WiFi subsystem is restarted whether or not a bug
+     *               report is requested or generated.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE)
+    public void restartWifiSubsystem(@Nullable String reason) {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        try {
+            mService.restartWifiSubsystem(reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets the Wi-Fi enabled state.
      * @return One of {@link #WIFI_STATE_DISABLED},
      *         {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
@@ -3194,6 +3225,19 @@
     public @interface CoexRestriction {}
 
     /**
+     * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise.
+     *
+     * @hide
+     */
+    public boolean isDefaultCoexAlgorithmEnabled() {
+        try {
+            return mService.isDefaultCoexAlgorithmEnabled();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Specify the set of {@link CoexUnsafeChannel} to propagate through the framework for
      * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay
      * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing.
@@ -3985,6 +4029,11 @@
         /**
          * Called when information of softap changes.
          *
+         * Note: this API is only valid when the Soft AP is configured as a single AP
+         * - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP
+         * this callback will not be triggered -  use the
+         * {@link #onInfoListChanged(List<SoftApInfo>)} callback in bridged AP mode.
+         *
          * @param softApInfo is the softap information. {@link SoftApInfo}
          */
         default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
@@ -3992,6 +4041,24 @@
         }
 
         /**
+         * Called when information of softap changes.
+         *
+         * The number of the information elements in the list depends on Soft AP configuration
+         * and state.
+         * For instance, an empty list will be returned when the Soft AP is disabled.
+         * One information element will be returned in the list when the Soft AP is configured
+         * as a single AP, and two information elements will be returned in the list
+         * when the Soft AP is configured in bridged mode.
+         *
+         * See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP.
+         *
+         * @param softApInfoList is the list of the softap information elements. {@link SoftApInfo}
+         */
+        default void onInfoListChanged(@NonNull List<SoftApInfo> softApInfoList) {
+            // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
+        }
+
+        /**
          * Called when capability of softap changes.
          *
          * @param softApCapability is the softap capability. {@link SoftApCapability}
@@ -4071,6 +4138,19 @@
         }
 
         @Override
+        public void onInfoListChanged(List<SoftApInfo> softApInfoList) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "SoftApCallbackProxy: onInfoListChange: softApInfoList="
+                        + softApInfoList);
+            }
+
+            Binder.clearCallingIdentity();
+            mExecutor.execute(() -> {
+                mCallback.onInfoListChanged(softApInfoList);
+            });
+        }
+
+        @Override
         public void onCapabilityChanged(SoftApCapability capability) {
             if (mVerboseLoggingEnabled) {
                 Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability="
@@ -4580,7 +4660,9 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public void startTemporarilyDisablingAllNonCarrierMergedWifi(int subscriptionId) {
         try {
             mService.startTemporarilyDisablingAllNonCarrierMergedWifi(subscriptionId);
@@ -4595,7 +4677,9 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public void stopTemporarilyDisablingAllNonCarrierMergedWifi() {
         try {
             mService.stopTemporarilyDisablingAllNonCarrierMergedWifi();
@@ -6821,4 +6905,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/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
deleted file mode 100755
index 378549d..0000000
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import android.Manifest.permission;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.net.INetworkScoreCache;
-import android.net.NetworkKey;
-import android.net.ScoredNetwork;
-import android.os.Handler;
-import android.os.Process;
-import android.util.Log;
-import android.util.LruCache;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * {@link INetworkScoreCache} implementation for Wifi Networks.
- *
- * TODO: This should not be part of wifi mainline module.
- * @hide
- */
-public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
-    private static final String TAG = "WifiNetworkScoreCache";
-    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
-    // A Network scorer returns a score in the range [-128, +127]
-    // We treat the lowest possible score as though there were no score, effectively allowing the
-    // scorer to provide an RSSI threshold below which a network should not be used.
-    public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE;
-
-    /** Default number entries to be stored in the {@link LruCache}. */
-    private static final int DEFAULT_MAX_CACHE_SIZE = 100;
-
-    // See {@link #CacheListener}.
-    @Nullable
-    @GuardedBy("mLock")
-    private CacheListener mListener;
-
-    private final Context mContext;
-    private final Object mLock = new Object();
-
-    // The key is of the form "<ssid>"<bssid>
-    // TODO: What about SSIDs that can't be encoded as UTF-8?
-    @GuardedBy("mLock")
-    private final LruCache<String, ScoredNetwork> mCache;
-
-    public WifiNetworkScoreCache(Context context) {
-        this(context, null /* listener */);
-    }
-
-    /**
-     * Instantiates a WifiNetworkScoreCache.
-     *
-     * @param context Application context
-     * @param listener CacheListener for cache updates
-     */
-    public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) {
-        this(context, listener, DEFAULT_MAX_CACHE_SIZE);
-    }
-
-    public WifiNetworkScoreCache(
-            Context context, @Nullable CacheListener listener, int maxCacheSize) {
-        mContext = context.getApplicationContext();
-        mListener = listener;
-        mCache = new LruCache<>(maxCacheSize);
-    }
-
-    @Override public final void updateScores(List<ScoredNetwork> networks) {
-        if (networks == null || networks.isEmpty()) {
-           return;
-        }
-        if (DBG) {
-            Log.d(TAG, "updateScores list size=" + networks.size());
-        }
-
-        boolean changed = false;
-
-        synchronized(mLock) {
-            for (ScoredNetwork network : networks) {
-                String networkKey = buildNetworkKey(network);
-                if (networkKey == null) {
-                    if (DBG) {
-                        Log.d(TAG, "Failed to build network key for ScoredNetwork" + network);
-                    }
-                    continue;
-                }
-                mCache.put(networkKey, network);
-                changed = true;
-            }
-
-            if (mListener != null && changed) {
-                mListener.post(networks);
-            }
-        }
-    }
-
-    @Override public final void clearScores() {
-        synchronized (mLock) {
-            mCache.evictAll();
-        }
-    }
-
-    /**
-     * Returns whether there is any score info for the given ScanResult.
-     *
-     * This includes null-score info, so it should only be used when determining whether to request
-     * scores from the network scorer.
-     */
-    public boolean isScoredNetwork(ScanResult result) {
-        return getScoredNetwork(result) != null;
-    }
-
-    /**
-     * Returns whether there is a non-null score curve for the given ScanResult.
-     *
-     * A null score curve has special meaning - we should never connect to an ephemeral network if
-     * the score curve is null.
-     */
-    public boolean hasScoreCurve(ScanResult result) {
-        ScoredNetwork network = getScoredNetwork(result);
-        return network != null && network.rssiCurve != null;
-    }
-
-    public int getNetworkScore(ScanResult result) {
-        int score = INVALID_NETWORK_SCORE;
-
-        ScoredNetwork network = getScoredNetwork(result);
-        if (network != null && network.rssiCurve != null) {
-            score = network.rssiCurve.lookupScore(result.level);
-            if (DBG) {
-                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
-                        + " score " + Integer.toString(score)
-                        + " RSSI " + result.level);
-            }
-        }
-        return score;
-    }
-
-    /**
-     * Returns the ScoredNetwork metered hint for a given ScanResult.
-     *
-     * If there is no ScoredNetwork associated with the ScanResult then false will be returned.
-     */
-    public boolean getMeteredHint(ScanResult result) {
-        ScoredNetwork network = getScoredNetwork(result);
-        return network != null && network.meteredHint;
-    }
-
-    public int getNetworkScore(ScanResult result, boolean isActiveNetwork) {
-        int score = INVALID_NETWORK_SCORE;
-
-        ScoredNetwork network = getScoredNetwork(result);
-        if (network != null && network.rssiCurve != null) {
-            score = network.rssiCurve.lookupScore(result.level, isActiveNetwork);
-            if (DBG) {
-                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
-                        + " score " + Integer.toString(score)
-                        + " RSSI " + result.level
-                        + " isActiveNetwork " + isActiveNetwork);
-            }
-        }
-        return score;
-    }
-
-    @Nullable
-    public ScoredNetwork getScoredNetwork(ScanResult result) {
-        String key = buildNetworkKey(result);
-        if (key == null) return null;
-
-        synchronized(mLock) {
-            ScoredNetwork network = mCache.get(key);
-            return network;
-        }
-    }
-
-    /** Returns the ScoredNetwork for the given key. */
-    @Nullable
-    public ScoredNetwork getScoredNetwork(NetworkKey networkKey) {
-        String key = buildNetworkKey(networkKey);
-        if (key == null) {
-            if (DBG) {
-                Log.d(TAG, "Could not build key string for Network Key: " + networkKey);
-            }
-            return null;
-        }
-        synchronized (mLock) {
-            return mCache.get(key);
-        }
-    }
-
-    private String buildNetworkKey(ScoredNetwork network) {
-        if (network == null) {
-            return null;
-        }
-        return buildNetworkKey(network.networkKey);
-    }
-
-    private String buildNetworkKey(NetworkKey networkKey) {
-        if (networkKey == null) {
-            return null;
-        }
-        if (networkKey.wifiKey == null) return null;
-        if (networkKey.type == NetworkKey.TYPE_WIFI) {
-            String key = networkKey.wifiKey.ssid;
-            if (key == null) return null;
-            if (networkKey.wifiKey.bssid != null) {
-                key = key + networkKey.wifiKey.bssid;
-            }
-            return key;
-        }
-        return null;
-    }
-
-    private String buildNetworkKey(ScanResult result) {
-        if (result == null || result.SSID == null) {
-            return null;
-        }
-        StringBuilder key = new StringBuilder("\"");
-        key.append(result.SSID);
-        key.append("\"");
-        if (result.BSSID != null) {
-            key.append(result.BSSID);
-        }
-        return key.toString();
-    }
-
-    @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
-        String header = String.format("WifiNetworkScoreCache (%s/%d)",
-                mContext.getPackageName(), Process.myUid());
-        writer.println(header);
-        writer.println("  All score curves:");
-        synchronized (mLock) {
-            for (ScoredNetwork score : mCache.snapshot().values()) {
-                writer.println("    " + score);
-            }
-            writer.println("  Network scores for latest ScanResults:");
-            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-            for (ScanResult scanResult : wifiManager.getScanResults()) {
-                writer.println(
-                        "    " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
-            }
-        }
-    }
-
-    /** Registers a CacheListener instance, replacing the previous listener if it existed. */
-    public void registerListener(CacheListener listener) {
-        synchronized (mLock) {
-            mListener = listener;
-        }
-    }
-
-    /** Removes the registered CacheListener. */
-    public void unregisterListener() {
-        synchronized (mLock) {
-            mListener = null;
-        }
-    }
-
-    /** Listener for updates to the cache inside WifiNetworkScoreCache. */
-    public abstract static class CacheListener {
-        private Handler mHandler;
-
-        /**
-         * Constructor for CacheListener.
-         *
-         * @param handler the Handler on which to invoke the {@link #networkCacheUpdated} method.
-         *          This cannot be null.
-         */
-        public CacheListener(@NonNull Handler handler) {
-            Objects.requireNonNull(handler);
-            mHandler = handler;
-        }
-
-        /** Invokes the {@link #networkCacheUpdated(List<ScoredNetwork>)} method on the handler. */
-        void post(List<ScoredNetwork> updatedNetworks) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    networkCacheUpdated(updatedNetworks);
-                }
-            });
-        }
-
-        /**
-         * Invoked whenever the cache is updated.
-         *
-         * <p>Clearing the cache does not invoke this method.
-         *
-         * @param updatedNetworks the networks that were updated
-         */
-        public abstract void networkCacheUpdated(List<ScoredNetwork> updatedNetworks);
-    }
-}
diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
deleted file mode 100644
index 91d25f9..0000000
--- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
+++ /dev/null
@@ -1,1336 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.nl80211;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.app.AlarmManager;
-import android.content.Context;
-import android.net.wifi.SoftApInfo;
-import android.net.wifi.WifiAnnotations;
-import android.net.wifi.WifiScanner;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * This class encapsulates the interface the wificond daemon presents to the Wi-Fi framework - used
- * to encapsulate the Wi-Fi 80211nl management interface. The
- * interface is only for use by the Wi-Fi framework and access is protected by SELinux permissions.
- *
- * @hide
- */
-@SystemApi
-@SystemService(Context.WIFI_NL80211_SERVICE)
-public class WifiNl80211Manager {
-    private static final String TAG = "WifiNl80211Manager";
-    private boolean mVerboseLoggingEnabled = false;
-
-    /**
-     * The {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
-     * timeout, in milliseconds, after which
-     * {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason
-     * {@link #SEND_MGMT_FRAME_ERROR_TIMEOUT}.
-     */
-    private static final int SEND_MGMT_FRAME_TIMEOUT_MS = 1000;
-
-    private static final String TIMEOUT_ALARM_TAG = TAG + " Send Management Frame Timeout";
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"SCAN_TYPE_"},
-            value = {SCAN_TYPE_SINGLE_SCAN,
-                    SCAN_TYPE_PNO_SCAN})
-    public @interface ScanResultType {}
-
-    /**
-     * Specifies a scan type: single scan initiated by the framework. Can be used in
-     * {@link #getScanResults(String, int)} to specify the type of scan result to fetch.
-     */
-    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
-
-    /**
-     * Specifies a scan type: PNO scan. Can be used in {@link #getScanResults(String, int)} to
-     * specify the type of scan result to fetch.
-     */
-    public static final int SCAN_TYPE_PNO_SCAN = 1;
-
-    private AlarmManager mAlarmManager;
-    private Handler mEventHandler;
-
-    // Cached wificond binder handlers.
-    private IWificond mWificond;
-    private HashMap<String, IClientInterface> mClientInterfaces = new HashMap<>();
-    private HashMap<String, IApInterface> mApInterfaces = new HashMap<>();
-    private HashMap<String, IWifiScannerImpl> mWificondScanners = new HashMap<>();
-    private HashMap<String, IScanEvent> mScanEventHandlers = new HashMap<>();
-    private HashMap<String, IPnoScanEvent> mPnoScanEventHandlers = new HashMap<>();
-    private HashMap<String, IApInterfaceEventCallback> mApInterfaceListeners = new HashMap<>();
-    private Runnable mDeathEventHandler;
-    /**
-     * Ensures that no more than one sendMgmtFrame operation runs concurrently.
-     */
-    private AtomicBoolean mSendMgmtFrameInProgress = new AtomicBoolean(false);
-
-    /**
-     * Interface used when waiting for scans to be completed (with results).
-     */
-    public interface ScanEventCallback {
-        /**
-         * Called when scan results are available. Scans results should then be obtained from
-         * {@link #getScanResults(String, int)}.
-         */
-        void onScanResultReady();
-
-        /**
-         * Called when a scan has failed.
-         */
-        void onScanFailed();
-    }
-
-    /**
-     * Interface for a callback to provide information about PNO scan request requested with
-     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. Note that the
-     * callback are for the status of the request - not the scan itself. The results of the scan
-     * are returned with {@link ScanEventCallback}.
-     */
-    public interface PnoScanRequestCallback {
-        /**
-         * Called when a PNO scan request has been successfully submitted.
-         */
-        void onPnoRequestSucceeded();
-
-        /**
-         * Called when a PNO scan request fails.
-         */
-        void onPnoRequestFailed();
-    }
-
-    private class ScanEventHandler extends IScanEvent.Stub {
-        private Executor mExecutor;
-        private ScanEventCallback mCallback;
-
-        ScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
-            mExecutor = executor;
-            mCallback = callback;
-        }
-
-        @Override
-        public void OnScanResultReady() {
-            Log.d(TAG, "Scan result ready event");
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onScanResultReady());
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void OnScanFailed() {
-            Log.d(TAG, "Scan failed event");
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onScanFailed());
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-
-    /**
-     * Result of a signal poll requested using {@link #signalPoll(String)}.
-     */
-    public static class SignalPollResult {
-        /** @hide */
-        public SignalPollResult(int currentRssiDbm, int txBitrateMbps, int rxBitrateMbps,
-                int associationFrequencyMHz) {
-            this.currentRssiDbm = currentRssiDbm;
-            this.txBitrateMbps = txBitrateMbps;
-            this.rxBitrateMbps = rxBitrateMbps;
-            this.associationFrequencyMHz = associationFrequencyMHz;
-        }
-
-        /**
-         * RSSI value in dBM.
-         */
-        public final int currentRssiDbm;
-
-        /**
-         * Transmission bit rate in Mbps.
-         */
-        public final int txBitrateMbps;
-
-        /**
-         * Last received packet bit rate in Mbps.
-         */
-        public final int rxBitrateMbps;
-
-        /**
-         * Association frequency in MHz.
-         */
-        public final int associationFrequencyMHz;
-    }
-
-    /**
-     * Transmission counters obtained using {@link #getTxPacketCounters(String)}.
-     */
-    public static class TxPacketCounters {
-        /** @hide */
-        public TxPacketCounters(int txPacketSucceeded, int txPacketFailed) {
-            this.txPacketSucceeded = txPacketSucceeded;
-            this.txPacketFailed = txPacketFailed;
-        }
-
-        /**
-         * Number of successfully transmitted packets.
-         */
-        public final int txPacketSucceeded;
-
-        /**
-         * Number of packet transmission failures.
-         */
-        public final int txPacketFailed;
-    }
-
-    /**
-     * Callbacks for SoftAp interface registered using
-     * {@link #registerApCallback(String, Executor, SoftApCallback)}.
-     *
-     * @deprecated The usage is replaced by vendor HAL
-     * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}.
-     */
-    @Deprecated
-    public interface SoftApCallback {
-        /**
-         * Invoked when there is a fatal failure and the SoftAp is shutdown.
-         */
-        void onFailure();
-
-        /**
-         * Invoked when there is a change in the associated station (STA).
-         * @param client Information about the client whose status has changed.
-         * @param isConnected Indication as to whether the client is connected (true), or
-         *                    disconnected (false).
-         */
-        void onConnectedClientsChanged(@NonNull NativeWifiClient client, boolean isConnected);
-
-        /**
-         * Invoked when a channel switch event happens - i.e. the SoftAp is moved to a different
-         * channel. Also called on initial registration.
-         * @param frequencyMhz The new frequency of the SoftAp. A value of 0 is invalid and is an
-         *                     indication that the SoftAp is not enabled.
-         * @param bandwidth The new bandwidth of the SoftAp.
-         */
-        void onSoftApChannelSwitched(int frequencyMhz, @WifiAnnotations.Bandwidth int bandwidth);
-    }
-
-    /**
-     * Callback to notify the results of a
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} call.
-     * Note: no callbacks will be triggered if the interface dies while sending a frame.
-     */
-    public interface SendMgmtFrameCallback {
-        /**
-         * Called when the management frame was successfully sent and ACKed by the recipient.
-         * @param elapsedTimeMs The elapsed time between when the management frame was sent and when
-         *                      the ACK was processed, in milliseconds, as measured by wificond.
-         *                      This includes the time that the send frame spent queuing before it
-         *                      was sent, any firmware retries, and the time the received ACK spent
-         *                      queuing before it was processed.
-         */
-        void onAck(int elapsedTimeMs);
-
-        /**
-         * Called when the send failed.
-         * @param reason The error code for the failure.
-         */
-        void onFailure(@SendMgmtFrameError int reason);
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"SEND_MGMT_FRAME_ERROR_"},
-            value = {SEND_MGMT_FRAME_ERROR_UNKNOWN,
-                    SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED,
-                    SEND_MGMT_FRAME_ERROR_NO_ACK,
-                    SEND_MGMT_FRAME_ERROR_TIMEOUT,
-                    SEND_MGMT_FRAME_ERROR_ALREADY_STARTED})
-    public @interface SendMgmtFrameError {}
-
-    // Send management frame error codes
-
-    /**
-     * Unknown error occurred during call to
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
-     */
-    public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1;
-
-    /**
-     * Specifying the MCS rate in
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} is not
-     * supported by this device.
-     */
-    public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2;
-
-    /**
-     * Driver reported that no ACK was received for the frame transmitted using
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
-     */
-    public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3;
-
-    /**
-     * Error code for when the driver fails to report on the status of the frame sent by
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
-     * after {@link #SEND_MGMT_FRAME_TIMEOUT_MS} milliseconds.
-     */
-    public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4;
-
-    /**
-     * An existing call to
-     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
-     * is in progress. Another frame cannot be sent until the first call completes.
-     */
-    public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5;
-
-    /** @hide */
-    public WifiNl80211Manager(Context context) {
-        mAlarmManager = context.getSystemService(AlarmManager.class);
-        mEventHandler = new Handler(context.getMainLooper());
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public WifiNl80211Manager(Context context, IWificond wificond) {
-        this(context);
-        mWificond = wificond;
-    }
-
-    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
-        private Executor mExecutor;
-        private ScanEventCallback mCallback;
-
-        PnoScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
-            mExecutor = executor;
-            mCallback = callback;
-        }
-
-        @Override
-        public void OnPnoNetworkFound() {
-            Log.d(TAG, "Pno scan result event");
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onScanResultReady());
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void OnPnoScanFailed() {
-            Log.d(TAG, "Pno Scan failed event");
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onScanFailed());
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-
-    /**
-     * Listener for AP Interface events.
-     */
-    private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub {
-        private Executor mExecutor;
-        private SoftApCallback mSoftApListener;
-
-        ApInterfaceEventCallback(Executor executor, SoftApCallback listener) {
-            mExecutor = executor;
-            mSoftApListener = listener;
-        }
-
-        @Override
-        public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) {
-            if (mVerboseLoggingEnabled) {
-                Log.d(TAG, "onConnectedClientsChanged called with "
-                        + client.getMacAddress() + " isConnected: " + isConnected);
-            }
-
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(
-                        () -> mSoftApListener.onConnectedClientsChanged(client, isConnected));
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onSoftApChannelSwitched(int frequency, int bandwidth) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mSoftApListener.onSoftApChannelSwitched(frequency,
-                        toFrameworkBandwidth(bandwidth)));
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        private @WifiAnnotations.Bandwidth int toFrameworkBandwidth(int bandwidth) {
-            switch(bandwidth) {
-                case IApInterfaceEventCallback.BANDWIDTH_INVALID:
-                    return SoftApInfo.CHANNEL_WIDTH_INVALID;
-                case IApInterfaceEventCallback.BANDWIDTH_20_NOHT:
-                    return SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT;
-                case IApInterfaceEventCallback.BANDWIDTH_20:
-                    return SoftApInfo.CHANNEL_WIDTH_20MHZ;
-                case IApInterfaceEventCallback.BANDWIDTH_40:
-                    return SoftApInfo.CHANNEL_WIDTH_40MHZ;
-                case IApInterfaceEventCallback.BANDWIDTH_80:
-                    return SoftApInfo.CHANNEL_WIDTH_80MHZ;
-                case IApInterfaceEventCallback.BANDWIDTH_80P80:
-                    return SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
-                case IApInterfaceEventCallback.BANDWIDTH_160:
-                    return SoftApInfo.CHANNEL_WIDTH_160MHZ;
-                default:
-                    return SoftApInfo.CHANNEL_WIDTH_INVALID;
-            }
-        }
-    }
-
-    /**
-     * Callback triggered by wificond.
-     */
-    private class SendMgmtFrameEvent extends ISendMgmtFrameEvent.Stub {
-        private Executor mExecutor;
-        private SendMgmtFrameCallback mCallback;
-        private AlarmManager.OnAlarmListener mTimeoutCallback;
-        /**
-         * ensures that mCallback is only called once
-         */
-        private boolean mWasCalled;
-
-        private void runIfFirstCall(Runnable r) {
-            if (mWasCalled) return;
-            mWasCalled = true;
-
-            mSendMgmtFrameInProgress.set(false);
-            r.run();
-        }
-
-        SendMgmtFrameEvent(@NonNull Executor executor, @NonNull SendMgmtFrameCallback callback) {
-            mExecutor = executor;
-            mCallback = callback;
-            // called in main thread
-            mTimeoutCallback = () -> runIfFirstCall(() -> {
-                if (mVerboseLoggingEnabled) {
-                    Log.e(TAG, "Timed out waiting for ACK");
-                }
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    mExecutor.execute(() -> mCallback.onFailure(SEND_MGMT_FRAME_ERROR_TIMEOUT));
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            });
-            mWasCalled = false;
-
-            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                    SystemClock.elapsedRealtime() + SEND_MGMT_FRAME_TIMEOUT_MS,
-                    TIMEOUT_ALARM_TAG, mTimeoutCallback, mEventHandler);
-        }
-
-        // called in binder thread
-        @Override
-        public void OnAck(int elapsedTimeMs) {
-            // post to main thread
-            mEventHandler.post(() -> runIfFirstCall(() -> {
-                mAlarmManager.cancel(mTimeoutCallback);
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    mExecutor.execute(() -> mCallback.onAck(elapsedTimeMs));
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }));
-        }
-
-        // called in binder thread
-        @Override
-        public void OnFailure(int reason) {
-            // post to main thread
-            mEventHandler.post(() -> runIfFirstCall(() -> {
-                mAlarmManager.cancel(mTimeoutCallback);
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    mExecutor.execute(() -> mCallback.onFailure(reason));
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            }));
-        }
-    }
-
-    /**
-     * Called by the binder subsystem upon remote object death.
-     * Invoke all the register death handlers and clear state.
-     * @hide
-     */
-    @VisibleForTesting
-    public void binderDied() {
-        mEventHandler.post(() -> {
-            Log.e(TAG, "Wificond died!");
-            clearState();
-            // Invalidate the global wificond handle on death. Will be refreshed
-            // on the next setup call.
-            mWificond = null;
-            if (mDeathEventHandler != null) {
-                mDeathEventHandler.run();
-            }
-        });
-    }
-
-    /**
-     * Enable or disable verbose logging of the WifiNl80211Manager module.
-     * @param enable True to enable verbose logging. False to disable verbose logging.
-     */
-    public void enableVerboseLogging(boolean enable) {
-        mVerboseLoggingEnabled = enable;
-    }
-
-    /**
-     * Register a death notification for the WifiNl80211Manager which acts as a proxy for the
-     * wificond daemon (i.e. the death listener will be called when and if the wificond daemon
-     * dies).
-     *
-     * @param deathEventHandler A {@link Runnable} to be called whenever the wificond daemon dies.
-     */
-    public void setOnServiceDeadCallback(@NonNull Runnable deathEventHandler) {
-        if (mDeathEventHandler != null) {
-            Log.e(TAG, "Death handler already present");
-        }
-        mDeathEventHandler = deathEventHandler;
-    }
-
-    /**
-     * Helper method to retrieve the global wificond handle and register for
-     * death notifications.
-     */
-    private boolean retrieveWificondAndRegisterForDeath() {
-        if (mWificond != null) {
-            if (mVerboseLoggingEnabled) {
-                Log.d(TAG, "Wificond handle already retrieved");
-            }
-            // We already have a wificond handle.
-            return true;
-        }
-        IBinder binder = ServiceManager.getService(Context.WIFI_NL80211_SERVICE);
-        mWificond = IWificond.Stub.asInterface(binder);
-        if (mWificond == null) {
-            Log.e(TAG, "Failed to get reference to wificond");
-            return false;
-        }
-        try {
-            mWificond.asBinder().linkToDeath(() -> binderDied(), 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to register death notification for wificond");
-            // The remote has already died.
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Set up an interface for client (STA) mode.
-     *
-     * @param ifaceName Name of the interface to configure.
-     * @param executor The Executor on which to execute the callbacks.
-     * @param scanCallback A callback for framework initiated scans.
-     * @param pnoScanCallback A callback for PNO (offloaded) scans.
-     * @return true on success.
-     */
-    public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
-        Log.d(TAG, "Setting up interface for client mode");
-        if (!retrieveWificondAndRegisterForDeath()) {
-            return false;
-        }
-
-        if (scanCallback == null || pnoScanCallback == null || executor == null) {
-            Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks");
-            return false;
-        }
-
-        IClientInterface clientInterface = null;
-        try {
-            clientInterface = mWificond.createClientInterface(ifaceName);
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
-            return false;
-        }
-
-        if (clientInterface == null) {
-            Log.e(TAG, "Could not get IClientInterface instance from wificond");
-            return false;
-        }
-        Binder.allowBlocking(clientInterface.asBinder());
-
-        // Refresh Handlers
-        mClientInterfaces.put(ifaceName, clientInterface);
-        try {
-            IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
-            if (wificondScanner == null) {
-                Log.e(TAG, "Failed to get WificondScannerImpl");
-                return false;
-            }
-            mWificondScanners.put(ifaceName, wificondScanner);
-            Binder.allowBlocking(wificondScanner.asBinder());
-            ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
-            mScanEventHandlers.put(ifaceName,  scanEventHandler);
-            wificondScanner.subscribeScanEvents(scanEventHandler);
-            PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
-                    pnoScanCallback);
-            mPnoScanEventHandlers.put(ifaceName,  pnoScanEventHandler);
-            wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
-        }
-
-        return true;
-    }
-
-    /**
-     * Tear down a specific client (STA) interface configured using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
-     *
-     * @param ifaceName Name of the interface to tear down.
-     * @return Returns true on success, false on failure (e.g. when called before an interface was
-     * set up).
-     */
-    public boolean tearDownClientInterface(@NonNull String ifaceName) {
-        if (getClientInterface(ifaceName) == null) {
-            Log.e(TAG, "No valid wificond client interface handler");
-            return false;
-        }
-        try {
-            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
-            if (scannerImpl != null) {
-                scannerImpl.unsubscribeScanEvents();
-                scannerImpl.unsubscribePnoScanEvents();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
-            return false;
-        }
-
-        if (mWificond == null) {
-            Log.e(TAG, "Reference to wifiCond is null");
-            return false;
-        }
-
-        boolean success;
-        try {
-            success = mWificond.tearDownClientInterface(ifaceName);
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to teardown client interface due to remote exception");
-            return false;
-        }
-        if (!success) {
-            Log.e(TAG, "Failed to teardown client interface");
-            return false;
-        }
-
-        mClientInterfaces.remove(ifaceName);
-        mWificondScanners.remove(ifaceName);
-        mScanEventHandlers.remove(ifaceName);
-        mPnoScanEventHandlers.remove(ifaceName);
-        return true;
-    }
-
-    /**
-     * Set up interface as a Soft AP.
-     *
-     * @param ifaceName Name of the interface to configure.
-     * @return true on success.
-     */
-    public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) {
-        Log.d(TAG, "Setting up interface for soft ap mode");
-        if (!retrieveWificondAndRegisterForDeath()) {
-            return false;
-        }
-
-        IApInterface apInterface = null;
-        try {
-            apInterface = mWificond.createApInterface(ifaceName);
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to get IApInterface due to remote exception");
-            return false;
-        }
-
-        if (apInterface == null) {
-            Log.e(TAG, "Could not get IApInterface instance from wificond");
-            return false;
-        }
-        Binder.allowBlocking(apInterface.asBinder());
-
-        // Refresh Handlers
-        mApInterfaces.put(ifaceName, apInterface);
-        return true;
-    }
-
-    /**
-     * Tear down a Soft AP interface configured using
-     * {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface to tear down.
-     * @return Returns true on success, false on failure (e.g. when called before an interface was
-     * set up).
-     */
-    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
-        if (getApInterface(ifaceName) == null) {
-            Log.e(TAG, "No valid wificond ap interface handler");
-            return false;
-        }
-
-        if (mWificond == null) {
-            Log.e(TAG, "Reference to wifiCond is null");
-            return false;
-        }
-
-        boolean success;
-        try {
-            success = mWificond.tearDownApInterface(ifaceName);
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
-            return false;
-        }
-        if (!success) {
-            Log.e(TAG, "Failed to teardown AP interface");
-            return false;
-        }
-        mApInterfaces.remove(ifaceName);
-        mApInterfaceListeners.remove(ifaceName);
-        return true;
-    }
-
-    /**
-    * Tear down all interfaces, whether clients (STA) or Soft AP.
-     *
-    * @return Returns true on success.
-    */
-    public boolean tearDownInterfaces() {
-        Log.d(TAG, "tearing down interfaces in wificond");
-        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
-        // could be used to cleanup before we setup any interfaces.
-        if (!retrieveWificondAndRegisterForDeath()) {
-            return false;
-        }
-
-        try {
-            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
-                entry.getValue().unsubscribeScanEvents();
-                entry.getValue().unsubscribePnoScanEvents();
-            }
-            mWificond.tearDownInterfaces();
-            clearState();
-            return true;
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
-        }
-
-        return false;
-    }
-
-    /** Helper function to look up the interface handle using name */
-    private IClientInterface getClientInterface(@NonNull String ifaceName) {
-        return mClientInterfaces.get(ifaceName);
-    }
-
-    /**
-     * Request signal polling.
-     *
-     * @param ifaceName Name of the interface on which to poll. The interface must have been
-     *                  already set up using
-     *{@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     *                  or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @return A {@link SignalPollResult} object containing interface statistics, or a null on
-     * error (e.g. the interface hasn't been set up yet).
-     */
-    @Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) {
-        IClientInterface iface = getClientInterface(ifaceName);
-        if (iface == null) {
-            Log.e(TAG, "No valid wificond client interface handler");
-            return null;
-        }
-
-        int[] resultArray;
-        try {
-            resultArray = iface.signalPoll();
-            if (resultArray == null || resultArray.length != 4) {
-                Log.e(TAG, "Invalid signal poll result from wificond");
-                return null;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to do signal polling due to remote exception");
-            return null;
-        }
-        return new SignalPollResult(resultArray[0], resultArray[1], resultArray[3], resultArray[2]);
-    }
-
-    /**
-     * Get current transmit (Tx) packet counters of the specified interface. The interface must
-     * have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface.
-     * @return {@link TxPacketCounters} of the current interface or null on error (e.g. when
-     * called before the interface has been set up).
-     */
-    @Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
-        IClientInterface iface = getClientInterface(ifaceName);
-        if (iface == null) {
-            Log.e(TAG, "No valid wificond client interface handler");
-            return null;
-        }
-
-        int[] resultArray;
-        try {
-            resultArray = iface.getPacketCounters();
-            if (resultArray == null || resultArray.length != 2) {
-                Log.e(TAG, "Invalid signal poll result from wificond");
-                return null;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to do signal polling due to remote exception");
-            return null;
-        }
-        return new TxPacketCounters(resultArray[0], resultArray[1]);
-    }
-
-    /** Helper function to look up the scanner impl handle using name */
-    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
-        return mWificondScanners.get(ifaceName);
-    }
-
-    /**
-     * Fetch the latest scan results of the indicated type for the specified interface. Note that
-     * this method fetches the latest results - it does not initiate a scan. Initiating a scan can
-     * be done using {@link #startScan(String, int, Set, List)} or
-     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface.
-     * @param scanType The type of scan result to be returned, can be
-     * {@link #SCAN_TYPE_SINGLE_SCAN} or {@link #SCAN_TYPE_PNO_SCAN}.
-     * @return Returns an array of {@link NativeScanResult} or an empty array on failure (e.g. when
-     * called before the interface has been set up).
-     */
-    @NonNull public List<NativeScanResult> getScanResults(@NonNull String ifaceName,
-            @ScanResultType int scanType) {
-        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
-        if (scannerImpl == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return new ArrayList<>();
-        }
-        List<NativeScanResult> results = null;
-        try {
-            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
-                results = Arrays.asList(scannerImpl.getScanResults());
-            } else {
-                results = Arrays.asList(scannerImpl.getPnoScanResults());
-            }
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to create ScanDetail ArrayList");
-        }
-        if (results == null) {
-            results = new ArrayList<>();
-        }
-        if (mVerboseLoggingEnabled) {
-            Log.d(TAG, "get " + results.size() + " scan results from wificond");
-        }
-
-        return results;
-    }
-
-    /**
-     * Return scan type for the parcelable {@link SingleScanSettings}
-     */
-    private static int getScanType(@WifiAnnotations.ScanType int scanType) {
-        switch (scanType) {
-            case WifiScanner.SCAN_TYPE_LOW_LATENCY:
-                return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN;
-            case WifiScanner.SCAN_TYPE_LOW_POWER:
-                return IWifiScannerImpl.SCAN_TYPE_LOW_POWER;
-            case WifiScanner.SCAN_TYPE_HIGH_ACCURACY:
-                return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY;
-            default:
-                throw new IllegalArgumentException("Invalid scan type " + scanType);
-        }
-    }
-
-    /**
-     * Start a scan using the specified parameters. A scan is an asynchronous operation. The
-     * result of the operation is returned in the {@link ScanEventCallback} registered when
-     * setting up an interface using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
-     * The latest scans can be obtained using {@link #getScanResults(String, int)} and using a
-     * {@link #SCAN_TYPE_SINGLE_SCAN} for the {@code scanType}.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface on which to initiate the scan.
-     * @param scanType Type of scan to perform, can be any of
-     * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, {@link WifiScanner#SCAN_TYPE_LOW_POWER}, or
-     * {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}.
-     * @param freqs list of frequencies to scan for, if null scan all supported channels.
-     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for, a null indicates that
-     *                           no hidden frequencies will be scanned for.
-     * @return Returns true on success, false on failure (e.g. when called before the interface
-     * has been set up).
-     */
-    public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
-            @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) {
-        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
-        if (scannerImpl == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return false;
-        }
-        SingleScanSettings settings = new SingleScanSettings();
-        try {
-            settings.scanType = getScanType(scanType);
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "Invalid scan type ", e);
-            return false;
-        }
-        settings.channelSettings  = new ArrayList<>();
-        settings.hiddenNetworks  = new ArrayList<>();
-
-        if (freqs != null) {
-            for (Integer freq : freqs) {
-                ChannelSettings channel = new ChannelSettings();
-                channel.frequency = freq;
-                settings.channelSettings.add(channel);
-            }
-        }
-        if (hiddenNetworkSSIDs != null) {
-            for (byte[] ssid : hiddenNetworkSSIDs) {
-                HiddenNetwork network = new HiddenNetwork();
-                network.ssid = ssid;
-
-                // settings.hiddenNetworks is expected to be very small, so this shouldn't cause
-                // any performance issues.
-                if (!settings.hiddenNetworks.contains(network)) {
-                    settings.hiddenNetworks.add(network);
-                }
-            }
-        }
-
-        try {
-            return scannerImpl.scan(settings);
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to request scan due to remote exception");
-        }
-        return false;
-    }
-
-    /**
-     * Request a PNO (Preferred Network Offload). The offload request and the scans are asynchronous
-     * operations. The result of the request are returned in the {@code callback} parameter which
-     * is an {@link PnoScanRequestCallback}. The scan results are are return in the
-     * {@link ScanEventCallback} which is registered when setting up an interface using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
-     * The latest PNO scans can be obtained using {@link #getScanResults(String, int)} with the
-     * {@code scanType} set to {@link #SCAN_TYPE_PNO_SCAN}.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface on which to request a PNO.
-     * @param pnoSettings PNO scan configuration.
-     * @param executor The Executor on which to execute the callback.
-     * @param callback Callback for the results of the offload request.
-     * @return true on success, false on failure (e.g. when called before the interface has been set
-     * up).
-     */
-    public boolean startPnoScan(@NonNull String ifaceName, @NonNull PnoSettings pnoSettings,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull PnoScanRequestCallback callback) {
-        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
-        if (scannerImpl == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return false;
-        }
-
-        if (callback == null || executor == null) {
-            Log.e(TAG, "startPnoScan called with a null callback");
-            return false;
-        }
-
-        try {
-            boolean success = scannerImpl.startPnoScan(pnoSettings);
-            if (success) {
-                executor.execute(callback::onPnoRequestSucceeded);
-            } else {
-                executor.execute(callback::onPnoRequestFailed);
-            }
-            return success;
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to start pno scan due to remote exception");
-        }
-        return false;
-    }
-
-    /**
-     * Stop PNO scan configured with
-     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName Name of the interface on which the PNO scan was configured.
-     * @return true on success, false on failure (e.g. when called before the interface has been
-     * set up).
-     */
-    public boolean stopPnoScan(@NonNull String ifaceName) {
-        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
-        if (scannerImpl == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return false;
-        }
-        try {
-            return scannerImpl.stopPnoScan();
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to stop pno scan due to remote exception");
-        }
-        return false;
-    }
-
-    /**
-     * Abort ongoing single scan started with {@link #startScan(String, int, Set, List)}. No failure
-     * callback, e.g. {@link ScanEventCallback#onScanFailed()}, is triggered by this operation.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}. If the interface has not been set up then
-     * this method has no impact.
-     *
-     * @param ifaceName Name of the interface on which the scan was started.
-     */
-    public void abortScan(@NonNull String ifaceName) {
-        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
-        if (scannerImpl == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return;
-        }
-        try {
-            scannerImpl.abortScan();
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to request abortScan due to remote exception");
-        }
-    }
-
-    /**
-     * Query the list of valid frequencies (in MHz) for the provided band.
-     * The result depends on the on the country code that has been set.
-     *
-     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
-     * The following bands are supported:
-     * {@link WifiScanner#WIFI_BAND_24_GHZ},
-     * {@link WifiScanner#WIFI_BAND_5_GHZ},
-     * {@link WifiScanner#WIFI_BAND_5_GHZ_DFS_ONLY},
-     * {@link WifiScanner#WIFI_BAND_6_GHZ}
-     * {@link WifiScanner.WIFI_BAND_60_GHZ}
-     * @return frequencies vector of valid frequencies (MHz), or an empty array for error.
-     * @throws IllegalArgumentException if band is not recognized.
-     */
-    public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) {
-        if (mWificond == null) {
-            Log.e(TAG, "No valid wificond scanner interface handler");
-            return new int[0];
-        }
-        int[] result = null;
-        try {
-            switch (band) {
-                case WifiScanner.WIFI_BAND_24_GHZ:
-                    result = mWificond.getAvailable2gChannels();
-                    break;
-                case WifiScanner.WIFI_BAND_5_GHZ:
-                    result = mWificond.getAvailable5gNonDFSChannels();
-                    break;
-                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
-                    result = mWificond.getAvailableDFSChannels();
-                    break;
-                case WifiScanner.WIFI_BAND_6_GHZ:
-                    result = mWificond.getAvailable6gChannels();
-                    break;
-                case WifiScanner.WIFI_BAND_60_GHZ:
-                    result = mWificond.getAvailable60gChannels();
-                    break;
-                default:
-                    throw new IllegalArgumentException("unsupported band " + band);
-            }
-        } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
-        }
-        if (result == null) {
-            result = new int[0];
-        }
-        return result;
-    }
-
-    /** Helper function to look up the interface handle using name */
-    private IApInterface getApInterface(@NonNull String ifaceName) {
-        return mApInterfaces.get(ifaceName);
-    }
-
-    /**
-     * Get the device phy capabilities for a given interface.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @return DeviceWiphyCapabilities or null on error (e.g. when called on an interface which has
-     * not been set up).
-     */
-    @Nullable public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) {
-        if (mWificond == null) {
-            Log.e(TAG, "Can not query for device wiphy capabilities at this time");
-            return null;
-        }
-
-        try {
-            return mWificond.getDeviceWiphyCapabilities(ifaceName);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Register the provided callback handler for SoftAp events. The interface must first be created
-     * using {@link #setupInterfaceForSoftApMode(String)}. The callback registration is valid until
-     * the interface is deleted using {@link #tearDownSoftApInterface(String)} (no deregistration
-     * method is provided).
-     * <p>
-     * Note that only one callback can be registered at a time - any registration overrides previous
-     * registrations.
-     *
-     * @param ifaceName Name of the interface on which to register the callback.
-     * @param executor The Executor on which to execute the callbacks.
-     * @param callback Callback for AP events.
-     * @return true on success, false on failure (e.g. when called on an interface which has not
-     * been set up).
-     *
-     * @deprecated The usage is replaced by vendor HAL
-     * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}.
-     */
-    @Deprecated
-    public boolean registerApCallback(@NonNull String ifaceName,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull SoftApCallback callback) {
-        IApInterface iface = getApInterface(ifaceName);
-        if (iface == null) {
-            Log.e(TAG, "No valid ap interface handler");
-            return false;
-        }
-
-        if (callback == null || executor == null) {
-            Log.e(TAG, "registerApCallback called with a null callback");
-            return false;
-        }
-
-        try {
-            IApInterfaceEventCallback wificondCallback = new ApInterfaceEventCallback(executor,
-                    callback);
-            mApInterfaceListeners.put(ifaceName, wificondCallback);
-            boolean success = iface.registerCallback(wificondCallback);
-            if (!success) {
-                Log.e(TAG, "Failed to register ap callback.");
-                return false;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Exception in registering AP callback: " + e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Send a management frame on the specified interface at the specified rate. Useful for probing
-     * the link with arbitrary frames.
-     *
-     * Note: The interface must have been already set up using
-     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
-     * or {@link #setupInterfaceForSoftApMode(String)}.
-     *
-     * @param ifaceName The interface on which to send the frame.
-     * @param frame The raw byte array of the management frame to tramit.
-     * @param mcs The MCS (modulation and coding scheme), i.e. rate, at which to transmit the
-     *            frame. Specified per IEEE 802.11.
-     * @param executor The Executor on which to execute the callbacks.
-     * @param callback A {@link SendMgmtFrameCallback} callback for results of the operation.
-     */
-    public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, int mcs,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull SendMgmtFrameCallback callback) {
-
-        if (callback == null || executor == null) {
-            Log.e(TAG, "callback cannot be null!");
-            return;
-        }
-
-        if (frame == null) {
-            Log.e(TAG, "frame cannot be null!");
-            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
-            return;
-        }
-
-        // TODO (b/112029045) validate mcs
-        IClientInterface clientInterface = getClientInterface(ifaceName);
-        if (clientInterface == null) {
-            Log.e(TAG, "No valid wificond client interface handler");
-            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
-            return;
-        }
-
-        if (!mSendMgmtFrameInProgress.compareAndSet(false, true)) {
-            Log.e(TAG, "An existing management frame transmission is in progress!");
-            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_ALREADY_STARTED));
-            return;
-        }
-
-        SendMgmtFrameEvent sendMgmtFrameEvent = new SendMgmtFrameEvent(executor, callback);
-        try {
-            clientInterface.SendMgmtFrame(frame, sendMgmtFrameEvent, mcs);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Exception while starting link probe: " + e);
-            // Call sendMgmtFrameEvent.OnFailure() instead of callback.onFailure() so that
-            // sendMgmtFrameEvent can clean up internal state, such as cancelling the timer.
-            sendMgmtFrameEvent.OnFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN);
-        }
-    }
-
-    /**
-     * Clear all internal handles.
-     */
-    private void clearState() {
-        // Refresh handlers
-        mClientInterfaces.clear();
-        mWificondScanners.clear();
-        mPnoScanEventHandlers.clear();
-        mScanEventHandlers.clear();
-        mApInterfaces.clear();
-        mApInterfaceListeners.clear();
-        mSendMgmtFrameInProgress.set(false);
-    }
-
-    /**
-     * OEM parsed security type
-     */
-    public static class OemSecurityType {
-        /** The protocol defined in {@link android.net.wifi.WifiAnnotations.Protocol}. */
-        public final @WifiAnnotations.Protocol int protocol;
-        /**
-         * Supported key management types defined
-         * in {@link android.net.wifi.WifiAnnotations.KeyMgmt}.
-         */
-        @NonNull public final List<Integer> keyManagement;
-        /**
-         * Supported pairwise cipher types defined
-         * in {@link android.net.wifi.WifiAnnotations.Cipher}.
-         */
-        @NonNull public final List<Integer> pairwiseCipher;
-        /** The group cipher type defined in {@link android.net.wifi.WifiAnnotations.Cipher}. */
-        public final @WifiAnnotations.Cipher int groupCipher;
-        /**
-         * Default constructor for OemSecurityType
-         *
-         * @param protocol The protocol defined in
-         *                 {@link android.net.wifi.WifiAnnotations.Protocol}.
-         * @param keyManagement Supported key management types defined
-         *                      in {@link android.net.wifi.WifiAnnotations.KeyMgmt}.
-         * @param pairwiseCipher Supported pairwise cipher types defined
-         *                       in {@link android.net.wifi.WifiAnnotations.Cipher}.
-         * @param groupCipher The group cipher type defined
-         *                    in {@link android.net.wifi.WifiAnnotations.Cipher}.
-         */
-        public OemSecurityType(
-                @WifiAnnotations.Protocol int protocol,
-                @NonNull List<Integer> keyManagement,
-                @NonNull List<Integer> pairwiseCipher,
-                @WifiAnnotations.Cipher int groupCipher) {
-            this.protocol = protocol;
-            this.keyManagement = (keyManagement != null)
-                ? keyManagement : new ArrayList<Integer>();
-            this.pairwiseCipher = (pairwiseCipher != null)
-                ? pairwiseCipher : new ArrayList<Integer>();
-            this.groupCipher = groupCipher;
-        }
-    }
-
-    /**
-     * OEM information element parser for security types not parsed by the framework.
-     *
-     * The OEM method should use the method inputs {@code id}, {@code idExt}, and {@code bytes}
-     * to perform the parsing. The method should place the results in an OemSecurityType objct.
-     *
-     * @param id The information element id.
-     * @param idExt The information element extension id. This is valid only when id is
-     *        the extension id, {@code 255}.
-     * @param bytes The raw bytes of information element data, 'Element ID' and 'Length' are
-     *              stripped off already.
-     * @return an OemSecurityType object if this IE is parsed successfully, null otherwise.
-     */
-    @Nullable public static OemSecurityType parseOemSecurityTypeElement(
-            int id,
-            int idExt,
-            @NonNull byte[] bytes) {
-        return null;
-    }
-}
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java
index 318efa6..04dfcf2 100644
--- a/wifi/java/android/net/wifi/rtt/RangingRequest.java
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -30,8 +30,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.modules.utils.build.SdkLevel;
+
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.StringJoiner;
 
 /**
@@ -46,6 +49,9 @@
  */
 public final class RangingRequest implements Parcelable {
     private static final int MAX_PEERS = 10;
+    private static final int DEFAULT_RTT_BURST_SIZE = 8;
+    private static final int MIN_RTT_BURST_SIZE = 2;
+    private static final int MAX_RTT_BURST_SIZE = 17;
 
     /**
      * Returns the maximum number of peers to range which can be specified in a single {@code
@@ -59,12 +65,80 @@
         return MAX_PEERS;
     }
 
+    /**
+     * Returns the default RTT burst size used to determine the average range.
+     *
+     * @return the RTT burst size used by default
+     */
+    public static int getDefaultRttBurstSize() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return DEFAULT_RTT_BURST_SIZE;
+    }
+
+    /**
+     * Returns the minimum RTT burst size that can be used to determine a average range.
+     *
+     * @return the minimum RTT burst size that can be used
+     */
+    public static int getMinRttBurstSize() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return MIN_RTT_BURST_SIZE;
+    }
+
+    /**
+     * Returns the minimum RTT burst size that can be used to determine a average range.
+     *
+     * @return the maximum RTT burst size that can be used
+     */
+    public static int getMaxRttBurstSize() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return MAX_RTT_BURST_SIZE;
+    }
+
     /** @hide */
     public final List<ResponderConfig> mRttPeers;
 
     /** @hide */
-    private RangingRequest(List<ResponderConfig> rttPeers) {
+    public final int mRttBurstSize;
+
+    /** @hide */
+    private RangingRequest(List<ResponderConfig> rttPeers, int rttBurstSize) {
         mRttPeers = rttPeers;
+        mRttBurstSize = rttBurstSize;
+    }
+
+    /**
+     * Returns the list of RTT capable peers.
+     *
+     * @return the list of RTT capable peers in a common system representation
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public List<ResponderConfig> getRttPeers() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return mRttPeers;
+    }
+
+    /**
+     * Returns the RTT burst size used to determine the average range.
+     *
+     * @return the RTT burst size used
+     */
+    public int getRttBurstSize() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return mRttBurstSize;
     }
 
     @Override
@@ -75,6 +149,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeList(mRttPeers);
+        dest.writeInt(mRttBurstSize);
     }
 
     public static final @android.annotation.NonNull Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() {
@@ -85,7 +160,7 @@
 
         @Override
         public RangingRequest createFromParcel(Parcel in) {
-            return new RangingRequest(in.readArrayList(null));
+            return new RangingRequest(in.readArrayList(null), in.readInt());
         }
     };
 
@@ -105,12 +180,20 @@
             throw new IllegalArgumentException(
                     "Ranging to too many peers requested. Use getMaxPeers() API to get limit.");
         }
-
         for (ResponderConfig peer: mRttPeers) {
             if (!peer.isValid(awareSupported)) {
                 throw new IllegalArgumentException("Invalid Responder specification");
             }
         }
+        if (SdkLevel.isAtLeastS()) {
+            if (mRttBurstSize < getMinRttBurstSize() || mRttBurstSize > getMaxRttBurstSize()) {
+                throw new IllegalArgumentException("RTT burst size is out of range");
+            }
+        } else {
+            if (mRttBurstSize != DEFAULT_RTT_BURST_SIZE) {
+                throw new IllegalArgumentException("RTT burst size is not the default value");
+            }
+        }
     }
 
     /**
@@ -118,6 +201,32 @@
      */
     public static final class Builder {
         private List<ResponderConfig> mRttPeers = new ArrayList<>();
+        private int mRttBurstSize = DEFAULT_RTT_BURST_SIZE;
+
+        /**
+         * Set the RTT Burst size for the ranging request.
+         * <p>
+         * If not set, the default RTT burst size given by
+         * {@link #getDefaultRttBurstSize()} is used to determine the default value.
+         * If set, the value must be in the range {@link #getMinRttBurstSize()} and
+         * {@link #getMaxRttBurstSize()} inclusively, or a
+         * {@link java.lang.IllegalArgumentException} will be thrown.
+         *
+         * @param rttBurstSize The number of FTM packets used to estimate a range.
+         * @return The builder to facilitate chaining
+         * {@code builder.setXXX(..).setXXX(..)}.
+         */
+        @NonNull
+        public Builder setRttBurstSize(int rttBurstSize) {
+            if (!SdkLevel.isAtLeastS()) {
+                throw new UnsupportedOperationException();
+            }
+            if (rttBurstSize < MIN_RTT_BURST_SIZE || rttBurstSize > MAX_RTT_BURST_SIZE) {
+                throw new IllegalArgumentException("RTT burst size out of range.");
+            }
+            mRttBurstSize = rttBurstSize;
+            return this;
+        }
 
         /**
          * Add the device specified by the {@link ScanResult} to the list of devices with
@@ -241,7 +350,7 @@
          * builder.
          */
         public RangingRequest build() {
-            return new RangingRequest(mRttPeers);
+            return new RangingRequest(mRttPeers, mRttBurstSize);
         }
     }
 
@@ -257,11 +366,13 @@
 
         RangingRequest lhs = (RangingRequest) o;
 
-        return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers);
+        return mRttPeers.size() == lhs.mRttPeers.size()
+                && mRttPeers.containsAll(lhs.mRttPeers)
+                && mRttBurstSize == lhs.mRttBurstSize;
     }
 
     @Override
     public int hashCode() {
-        return mRttPeers.hashCode();
+        return Objects.hash(mRttPeers, mRttBurstSize);
     }
 }
diff --git a/wifi/non-updatable/java/Android.bp b/wifi/non-updatable/java/Android.bp
new file mode 100644
index 0000000..b35b4be
--- /dev/null
+++ b/wifi/non-updatable/java/Android.bp
@@ -0,0 +1,35 @@
+// 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.
+
+// This directory contains framework Wifi APIs that are not part of the Wifi module (i.e. not
+// updatable), and are generally only called by the Wifi module.
+
+// necessary since we only want the `path` property to only refer to these files
+filegroup {
+    name: "framework-wifi-non-updatable-sources-internal",
+    srcs: ["src/**/*.java"],
+    path: "src",
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "framework-wifi-non-updatable-sources",
+    srcs: [
+        // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
+        // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
+        // to a separate package.
+        ":framework-wifi-non-updatable-sources-internal",
+        ":libwificond_ipc_aidl",
+    ],
+}
diff --git a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java b/wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java
similarity index 100%
rename from wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
rename to wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java
diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java
similarity index 100%
rename from wifi/java/android/net/wifi/WifiMigration.java
rename to wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java
diff --git a/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java
new file mode 100755
index 0000000..3903658
--- /dev/null
+++ b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.Manifest.permission;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.INetworkScoreCache;
+import android.net.NetworkKey;
+import android.net.ScoredNetwork;
+import android.os.Handler;
+import android.os.Process;
+import android.util.Log;
+import android.util.LruCache;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * {@link INetworkScoreCache} implementation for Wifi Networks.
+ *
+ * TODO: This should not be part of wifi mainline module.
+ * @hide
+ */
+public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
+    private static final String TAG = "WifiNetworkScoreCache";
+    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+
+    // A Network scorer returns a score in the range [-128, +127]
+    // We treat the lowest possible score as though there were no score, effectively allowing the
+    // scorer to provide an RSSI threshold below which a network should not be used.
+    public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE;
+
+    /** Default number entries to be stored in the {@link LruCache}. */
+    private static final int DEFAULT_MAX_CACHE_SIZE = 100;
+
+    // See {@link #CacheListener}.
+    @Nullable
+    @GuardedBy("mLock")
+    private CacheListener mListener;
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+
+    // The key is of the form "<ssid>"<bssid>
+    // TODO: What about SSIDs that can't be encoded as UTF-8?
+    @GuardedBy("mLock")
+    private final LruCache<String, ScoredNetwork> mCache;
+
+    public WifiNetworkScoreCache(Context context) {
+        this(context, null /* listener */);
+    }
+
+    /**
+     * Instantiates a WifiNetworkScoreCache.
+     *
+     * @param context Application context
+     * @param listener CacheListener for cache updates
+     */
+    public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) {
+        this(context, listener, DEFAULT_MAX_CACHE_SIZE);
+    }
+
+    public WifiNetworkScoreCache(
+            Context context, @Nullable CacheListener listener, int maxCacheSize) {
+        mContext = context.getApplicationContext();
+        mListener = listener;
+        mCache = new LruCache<>(maxCacheSize);
+    }
+
+    @Override public final void updateScores(List<ScoredNetwork> networks) {
+        if (networks == null || networks.isEmpty()) {
+            return;
+        }
+        if (DBG) {
+            Log.d(TAG, "updateScores list size=" + networks.size());
+        }
+
+        boolean changed = false;
+
+        synchronized (mLock) {
+            for (ScoredNetwork network : networks) {
+                String networkKey = buildNetworkKey(network);
+                if (networkKey == null) {
+                    if (DBG) {
+                        Log.d(TAG, "Failed to build network key for ScoredNetwork" + network);
+                    }
+                    continue;
+                }
+                mCache.put(networkKey, network);
+                changed = true;
+            }
+
+            if (mListener != null && changed) {
+                mListener.post(networks);
+            }
+        }
+    }
+
+    @Override public final void clearScores() {
+        synchronized (mLock) {
+            mCache.evictAll();
+        }
+    }
+
+    /**
+     * Returns whether there is any score info for the given ScanResult.
+     *
+     * This includes null-score info, so it should only be used when determining whether to request
+     * scores from the network scorer.
+     */
+    public boolean isScoredNetwork(ScanResult result) {
+        return getScoredNetwork(result) != null;
+    }
+
+    /**
+     * Returns whether there is a non-null score curve for the given ScanResult.
+     *
+     * A null score curve has special meaning - we should never connect to an ephemeral network if
+     * the score curve is null.
+     */
+    public boolean hasScoreCurve(ScanResult result) {
+        ScoredNetwork network = getScoredNetwork(result);
+        return network != null && network.rssiCurve != null;
+    }
+
+    public int getNetworkScore(ScanResult result) {
+        int score = INVALID_NETWORK_SCORE;
+
+        ScoredNetwork network = getScoredNetwork(result);
+        if (network != null && network.rssiCurve != null) {
+            score = network.rssiCurve.lookupScore(result.level);
+            if (DBG) {
+                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
+                        + " score " + Integer.toString(score)
+                        + " RSSI " + result.level);
+            }
+        }
+        return score;
+    }
+
+    /**
+     * Returns the ScoredNetwork metered hint for a given ScanResult.
+     *
+     * If there is no ScoredNetwork associated with the ScanResult then false will be returned.
+     */
+    public boolean getMeteredHint(ScanResult result) {
+        ScoredNetwork network = getScoredNetwork(result);
+        return network != null && network.meteredHint;
+    }
+
+    public int getNetworkScore(ScanResult result, boolean isActiveNetwork) {
+        int score = INVALID_NETWORK_SCORE;
+
+        ScoredNetwork network = getScoredNetwork(result);
+        if (network != null && network.rssiCurve != null) {
+            score = network.rssiCurve.lookupScore(result.level, isActiveNetwork);
+            if (DBG) {
+                Log.d(TAG, "getNetworkScore found scored network " + network.networkKey
+                        + " score " + Integer.toString(score)
+                        + " RSSI " + result.level
+                        + " isActiveNetwork " + isActiveNetwork);
+            }
+        }
+        return score;
+    }
+
+    @Nullable
+    public ScoredNetwork getScoredNetwork(ScanResult result) {
+        String key = buildNetworkKey(result);
+        if (key == null) return null;
+
+        synchronized (mLock) {
+            ScoredNetwork network = mCache.get(key);
+            return network;
+        }
+    }
+
+    /** Returns the ScoredNetwork for the given key. */
+    @Nullable
+    public ScoredNetwork getScoredNetwork(NetworkKey networkKey) {
+        String key = buildNetworkKey(networkKey);
+        if (key == null) {
+            if (DBG) {
+                Log.d(TAG, "Could not build key string for Network Key: " + networkKey);
+            }
+            return null;
+        }
+        synchronized (mLock) {
+            return mCache.get(key);
+        }
+    }
+
+    private String buildNetworkKey(ScoredNetwork network) {
+        if (network == null) {
+            return null;
+        }
+        return buildNetworkKey(network.networkKey);
+    }
+
+    private String buildNetworkKey(NetworkKey networkKey) {
+        if (networkKey == null) {
+            return null;
+        }
+        if (networkKey.wifiKey == null) return null;
+        if (networkKey.type == NetworkKey.TYPE_WIFI) {
+            String key = networkKey.wifiKey.ssid;
+            if (key == null) return null;
+            if (networkKey.wifiKey.bssid != null) {
+                key = key + networkKey.wifiKey.bssid;
+            }
+            return key;
+        }
+        return null;
+    }
+
+    private String buildNetworkKey(ScanResult result) {
+        if (result == null || result.SSID == null) {
+            return null;
+        }
+        StringBuilder key = new StringBuilder("\"");
+        key.append(result.SSID);
+        key.append("\"");
+        if (result.BSSID != null) {
+            key.append(result.BSSID);
+        }
+        return key.toString();
+    }
+
+    @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+        String header = String.format("WifiNetworkScoreCache (%s/%d)",
+                mContext.getPackageName(), Process.myUid());
+        writer.println(header);
+        writer.println("  All score curves:");
+        synchronized (mLock) {
+            for (ScoredNetwork score : mCache.snapshot().values()) {
+                writer.println("    " + score);
+            }
+            writer.println("  Network scores for latest ScanResults:");
+            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+            for (ScanResult scanResult : wifiManager.getScanResults()) {
+                writer.println(
+                        "    " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
+            }
+        }
+    }
+
+    /** Registers a CacheListener instance, replacing the previous listener if it existed. */
+    public void registerListener(CacheListener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+    }
+
+    /** Removes the registered CacheListener. */
+    public void unregisterListener() {
+        synchronized (mLock) {
+            mListener = null;
+        }
+    }
+
+    /** Listener for updates to the cache inside WifiNetworkScoreCache. */
+    public abstract static class CacheListener {
+        private Handler mHandler;
+
+        /**
+         * Constructor for CacheListener.
+         *
+         * @param handler the Handler on which to invoke the {@link #networkCacheUpdated} method.
+         *          This cannot be null.
+         */
+        public CacheListener(@NonNull Handler handler) {
+            Objects.requireNonNull(handler);
+            mHandler = handler;
+        }
+
+        /** Invokes the {@link #networkCacheUpdated(List<ScoredNetwork>)} method on the handler. */
+        void post(List<ScoredNetwork> updatedNetworks) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    networkCacheUpdated(updatedNetworks);
+                }
+            });
+        }
+
+        /**
+         * Invoked whenever the cache is updated.
+         *
+         * <p>Clearing the cache does not invoke this method.
+         *
+         * @param updatedNetworks the networks that were updated
+         */
+        public abstract void networkCacheUpdated(List<ScoredNetwork> updatedNetworks);
+    }
+}
diff --git a/wifi/java/android/net/wifi/nl80211/ChannelSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/ChannelSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java
diff --git a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
diff --git a/wifi/java/android/net/wifi/nl80211/HiddenNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/HiddenNetwork.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java
diff --git a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/NativeScanResult.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java
diff --git a/wifi/java/android/net/wifi/nl80211/NativeWifiClient.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/NativeWifiClient.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java
diff --git a/wifi/java/android/net/wifi/nl80211/PnoNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/PnoNetwork.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java
diff --git a/wifi/java/android/net/wifi/nl80211/PnoSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/PnoSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java
diff --git a/wifi/java/android/net/wifi/nl80211/RadioChainInfo.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/RadioChainInfo.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java
diff --git a/wifi/java/android/net/wifi/nl80211/SingleScanSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/SingleScanSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java
diff --git a/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
new file mode 100644
index 0000000..db2eb99
--- /dev/null
+++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
@@ -0,0 +1,1336 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nl80211;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.net.wifi.SoftApInfo;
+import android.net.wifi.WifiAnnotations;
+import android.net.wifi.WifiScanner;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class encapsulates the interface the wificond daemon presents to the Wi-Fi framework - used
+ * to encapsulate the Wi-Fi 80211nl management interface. The
+ * interface is only for use by the Wi-Fi framework and access is protected by SELinux permissions.
+ *
+ * @hide
+ */
+@SystemApi
+@SystemService(Context.WIFI_NL80211_SERVICE)
+public class WifiNl80211Manager {
+    private static final String TAG = "WifiNl80211Manager";
+    private boolean mVerboseLoggingEnabled = false;
+
+    /**
+     * The {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
+     * timeout, in milliseconds, after which
+     * {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason
+     * {@link #SEND_MGMT_FRAME_ERROR_TIMEOUT}.
+     */
+    private static final int SEND_MGMT_FRAME_TIMEOUT_MS = 1000;
+
+    private static final String TIMEOUT_ALARM_TAG = TAG + " Send Management Frame Timeout";
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SCAN_TYPE_"},
+            value = {SCAN_TYPE_SINGLE_SCAN,
+                    SCAN_TYPE_PNO_SCAN})
+    public @interface ScanResultType {}
+
+    /**
+     * Specifies a scan type: single scan initiated by the framework. Can be used in
+     * {@link #getScanResults(String, int)} to specify the type of scan result to fetch.
+     */
+    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
+
+    /**
+     * Specifies a scan type: PNO scan. Can be used in {@link #getScanResults(String, int)} to
+     * specify the type of scan result to fetch.
+     */
+    public static final int SCAN_TYPE_PNO_SCAN = 1;
+
+    private AlarmManager mAlarmManager;
+    private Handler mEventHandler;
+
+    // Cached wificond binder handlers.
+    private IWificond mWificond;
+    private HashMap<String, IClientInterface> mClientInterfaces = new HashMap<>();
+    private HashMap<String, IApInterface> mApInterfaces = new HashMap<>();
+    private HashMap<String, IWifiScannerImpl> mWificondScanners = new HashMap<>();
+    private HashMap<String, IScanEvent> mScanEventHandlers = new HashMap<>();
+    private HashMap<String, IPnoScanEvent> mPnoScanEventHandlers = new HashMap<>();
+    private HashMap<String, IApInterfaceEventCallback> mApInterfaceListeners = new HashMap<>();
+    private Runnable mDeathEventHandler;
+    /**
+     * Ensures that no more than one sendMgmtFrame operation runs concurrently.
+     */
+    private AtomicBoolean mSendMgmtFrameInProgress = new AtomicBoolean(false);
+
+    /**
+     * Interface used when waiting for scans to be completed (with results).
+     */
+    public interface ScanEventCallback {
+        /**
+         * Called when scan results are available. Scans results should then be obtained from
+         * {@link #getScanResults(String, int)}.
+         */
+        void onScanResultReady();
+
+        /**
+         * Called when a scan has failed.
+         */
+        void onScanFailed();
+    }
+
+    /**
+     * Interface for a callback to provide information about PNO scan request requested with
+     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. Note that the
+     * callback are for the status of the request - not the scan itself. The results of the scan
+     * are returned with {@link ScanEventCallback}.
+     */
+    public interface PnoScanRequestCallback {
+        /**
+         * Called when a PNO scan request has been successfully submitted.
+         */
+        void onPnoRequestSucceeded();
+
+        /**
+         * Called when a PNO scan request fails.
+         */
+        void onPnoRequestFailed();
+    }
+
+    private class ScanEventHandler extends IScanEvent.Stub {
+        private Executor mExecutor;
+        private ScanEventCallback mCallback;
+
+        ScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void OnScanResultReady() {
+            Log.d(TAG, "Scan result ready event");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mCallback.onScanResultReady());
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void OnScanFailed() {
+            Log.d(TAG, "Scan failed event");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mCallback.onScanFailed());
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    }
+
+    /**
+     * Result of a signal poll requested using {@link #signalPoll(String)}.
+     */
+    public static class SignalPollResult {
+        /** @hide */
+        public SignalPollResult(int currentRssiDbm, int txBitrateMbps, int rxBitrateMbps,
+                int associationFrequencyMHz) {
+            this.currentRssiDbm = currentRssiDbm;
+            this.txBitrateMbps = txBitrateMbps;
+            this.rxBitrateMbps = rxBitrateMbps;
+            this.associationFrequencyMHz = associationFrequencyMHz;
+        }
+
+        /**
+         * RSSI value in dBM.
+         */
+        public final int currentRssiDbm;
+
+        /**
+         * Transmission bit rate in Mbps.
+         */
+        public final int txBitrateMbps;
+
+        /**
+         * Last received packet bit rate in Mbps.
+         */
+        public final int rxBitrateMbps;
+
+        /**
+         * Association frequency in MHz.
+         */
+        public final int associationFrequencyMHz;
+    }
+
+    /**
+     * Transmission counters obtained using {@link #getTxPacketCounters(String)}.
+     */
+    public static class TxPacketCounters {
+        /** @hide */
+        public TxPacketCounters(int txPacketSucceeded, int txPacketFailed) {
+            this.txPacketSucceeded = txPacketSucceeded;
+            this.txPacketFailed = txPacketFailed;
+        }
+
+        /**
+         * Number of successfully transmitted packets.
+         */
+        public final int txPacketSucceeded;
+
+        /**
+         * Number of packet transmission failures.
+         */
+        public final int txPacketFailed;
+    }
+
+    /**
+     * Callbacks for SoftAp interface registered using
+     * {@link #registerApCallback(String, Executor, SoftApCallback)}.
+     *
+     * @deprecated The usage is replaced by vendor HAL
+     * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}.
+     */
+    @Deprecated
+    public interface SoftApCallback {
+        /**
+         * Invoked when there is a fatal failure and the SoftAp is shutdown.
+         */
+        void onFailure();
+
+        /**
+         * Invoked when there is a change in the associated station (STA).
+         * @param client Information about the client whose status has changed.
+         * @param isConnected Indication as to whether the client is connected (true), or
+         *                    disconnected (false).
+         */
+        void onConnectedClientsChanged(@NonNull NativeWifiClient client, boolean isConnected);
+
+        /**
+         * Invoked when a channel switch event happens - i.e. the SoftAp is moved to a different
+         * channel. Also called on initial registration.
+         * @param frequencyMhz The new frequency of the SoftAp. A value of 0 is invalid and is an
+         *                     indication that the SoftAp is not enabled.
+         * @param bandwidth The new bandwidth of the SoftAp.
+         */
+        void onSoftApChannelSwitched(int frequencyMhz, @WifiAnnotations.Bandwidth int bandwidth);
+    }
+
+    /**
+     * Callback to notify the results of a
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} call.
+     * Note: no callbacks will be triggered if the interface dies while sending a frame.
+     */
+    public interface SendMgmtFrameCallback {
+        /**
+         * Called when the management frame was successfully sent and ACKed by the recipient.
+         * @param elapsedTimeMs The elapsed time between when the management frame was sent and when
+         *                      the ACK was processed, in milliseconds, as measured by wificond.
+         *                      This includes the time that the send frame spent queuing before it
+         *                      was sent, any firmware retries, and the time the received ACK spent
+         *                      queuing before it was processed.
+         */
+        void onAck(int elapsedTimeMs);
+
+        /**
+         * Called when the send failed.
+         * @param reason The error code for the failure.
+         */
+        void onFailure(@SendMgmtFrameError int reason);
+    }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SEND_MGMT_FRAME_ERROR_"},
+            value = {SEND_MGMT_FRAME_ERROR_UNKNOWN,
+                    SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED,
+                    SEND_MGMT_FRAME_ERROR_NO_ACK,
+                    SEND_MGMT_FRAME_ERROR_TIMEOUT,
+                    SEND_MGMT_FRAME_ERROR_ALREADY_STARTED})
+    public @interface SendMgmtFrameError {}
+
+    // Send management frame error codes
+
+    /**
+     * Unknown error occurred during call to
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
+     */
+    public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1;
+
+    /**
+     * Specifying the MCS rate in
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} is not
+     * supported by this device.
+     */
+    public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2;
+
+    /**
+     * Driver reported that no ACK was received for the frame transmitted using
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
+     */
+    public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3;
+
+    /**
+     * Error code for when the driver fails to report on the status of the frame sent by
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
+     * after {@link #SEND_MGMT_FRAME_TIMEOUT_MS} milliseconds.
+     */
+    public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4;
+
+    /**
+     * An existing call to
+     * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
+     * is in progress. Another frame cannot be sent until the first call completes.
+     */
+    public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5;
+
+    /** @hide */
+    public WifiNl80211Manager(Context context) {
+        mAlarmManager = context.getSystemService(AlarmManager.class);
+        mEventHandler = new Handler(context.getMainLooper());
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public WifiNl80211Manager(Context context, IWificond wificond) {
+        this(context);
+        mWificond = wificond;
+    }
+
+    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
+        private Executor mExecutor;
+        private ScanEventCallback mCallback;
+
+        PnoScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void OnPnoNetworkFound() {
+            Log.d(TAG, "Pno scan result event");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mCallback.onScanResultReady());
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void OnPnoScanFailed() {
+            Log.d(TAG, "Pno Scan failed event");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mCallback.onScanFailed());
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    }
+
+    /**
+     * Listener for AP Interface events.
+     */
+    private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub {
+        private Executor mExecutor;
+        private SoftApCallback mSoftApListener;
+
+        ApInterfaceEventCallback(Executor executor, SoftApCallback listener) {
+            mExecutor = executor;
+            mSoftApListener = listener;
+        }
+
+        @Override
+        public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) {
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "onConnectedClientsChanged called with "
+                        + client.getMacAddress() + " isConnected: " + isConnected);
+            }
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(
+                        () -> mSoftApListener.onConnectedClientsChanged(client, isConnected));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onSoftApChannelSwitched(int frequency, int bandwidth) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mSoftApListener.onSoftApChannelSwitched(frequency,
+                        toFrameworkBandwidth(bandwidth)));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        private @WifiAnnotations.Bandwidth int toFrameworkBandwidth(int bandwidth) {
+            switch(bandwidth) {
+                case IApInterfaceEventCallback.BANDWIDTH_INVALID:
+                    return SoftApInfo.CHANNEL_WIDTH_INVALID;
+                case IApInterfaceEventCallback.BANDWIDTH_20_NOHT:
+                    return SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT;
+                case IApInterfaceEventCallback.BANDWIDTH_20:
+                    return SoftApInfo.CHANNEL_WIDTH_20MHZ;
+                case IApInterfaceEventCallback.BANDWIDTH_40:
+                    return SoftApInfo.CHANNEL_WIDTH_40MHZ;
+                case IApInterfaceEventCallback.BANDWIDTH_80:
+                    return SoftApInfo.CHANNEL_WIDTH_80MHZ;
+                case IApInterfaceEventCallback.BANDWIDTH_80P80:
+                    return SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
+                case IApInterfaceEventCallback.BANDWIDTH_160:
+                    return SoftApInfo.CHANNEL_WIDTH_160MHZ;
+                default:
+                    return SoftApInfo.CHANNEL_WIDTH_INVALID;
+            }
+        }
+    }
+
+    /**
+     * Callback triggered by wificond.
+     */
+    private class SendMgmtFrameEvent extends ISendMgmtFrameEvent.Stub {
+        private Executor mExecutor;
+        private SendMgmtFrameCallback mCallback;
+        private AlarmManager.OnAlarmListener mTimeoutCallback;
+        /**
+         * ensures that mCallback is only called once
+         */
+        private boolean mWasCalled;
+
+        private void runIfFirstCall(Runnable r) {
+            if (mWasCalled) return;
+            mWasCalled = true;
+
+            mSendMgmtFrameInProgress.set(false);
+            r.run();
+        }
+
+        SendMgmtFrameEvent(@NonNull Executor executor, @NonNull SendMgmtFrameCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+            // called in main thread
+            mTimeoutCallback = () -> runIfFirstCall(() -> {
+                if (mVerboseLoggingEnabled) {
+                    Log.e(TAG, "Timed out waiting for ACK");
+                }
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onFailure(SEND_MGMT_FRAME_ERROR_TIMEOUT));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            });
+            mWasCalled = false;
+
+            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime() + SEND_MGMT_FRAME_TIMEOUT_MS,
+                    TIMEOUT_ALARM_TAG, mTimeoutCallback, mEventHandler);
+        }
+
+        // called in binder thread
+        @Override
+        public void OnAck(int elapsedTimeMs) {
+            // post to main thread
+            mEventHandler.post(() -> runIfFirstCall(() -> {
+                mAlarmManager.cancel(mTimeoutCallback);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onAck(elapsedTimeMs));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }));
+        }
+
+        // called in binder thread
+        @Override
+        public void OnFailure(int reason) {
+            // post to main thread
+            mEventHandler.post(() -> runIfFirstCall(() -> {
+                mAlarmManager.cancel(mTimeoutCallback);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onFailure(reason));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }));
+        }
+    }
+
+    /**
+     * Called by the binder subsystem upon remote object death.
+     * Invoke all the register death handlers and clear state.
+     * @hide
+     */
+    @VisibleForTesting
+    public void binderDied() {
+        mEventHandler.post(() -> {
+            Log.e(TAG, "Wificond died!");
+            clearState();
+            // Invalidate the global wificond handle on death. Will be refreshed
+            // on the next setup call.
+            mWificond = null;
+            if (mDeathEventHandler != null) {
+                mDeathEventHandler.run();
+            }
+        });
+    }
+
+    /**
+     * Enable or disable verbose logging of the WifiNl80211Manager module.
+     * @param enable True to enable verbose logging. False to disable verbose logging.
+     */
+    public void enableVerboseLogging(boolean enable) {
+        mVerboseLoggingEnabled = enable;
+    }
+
+    /**
+     * Register a death notification for the WifiNl80211Manager which acts as a proxy for the
+     * wificond daemon (i.e. the death listener will be called when and if the wificond daemon
+     * dies).
+     *
+     * @param deathEventHandler A {@link Runnable} to be called whenever the wificond daemon dies.
+     */
+    public void setOnServiceDeadCallback(@NonNull Runnable deathEventHandler) {
+        if (mDeathEventHandler != null) {
+            Log.e(TAG, "Death handler already present");
+        }
+        mDeathEventHandler = deathEventHandler;
+    }
+
+    /**
+     * Helper method to retrieve the global wificond handle and register for
+     * death notifications.
+     */
+    private boolean retrieveWificondAndRegisterForDeath() {
+        if (mWificond != null) {
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Wificond handle already retrieved");
+            }
+            // We already have a wificond handle.
+            return true;
+        }
+        IBinder binder = ServiceManager.getService(Context.WIFI_NL80211_SERVICE);
+        mWificond = IWificond.Stub.asInterface(binder);
+        if (mWificond == null) {
+            Log.e(TAG, "Failed to get reference to wificond");
+            return false;
+        }
+        try {
+            mWificond.asBinder().linkToDeath(() -> binderDied(), 0);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to register death notification for wificond");
+            // The remote has already died.
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Set up an interface for client (STA) mode.
+     *
+     * @param ifaceName Name of the interface to configure.
+     * @param executor The Executor on which to execute the callbacks.
+     * @param scanCallback A callback for framework initiated scans.
+     * @param pnoScanCallback A callback for PNO (offloaded) scans.
+     * @return true on success.
+     */
+    public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
+        Log.d(TAG, "Setting up interface for client mode: " + ifaceName);
+        if (!retrieveWificondAndRegisterForDeath()) {
+            return false;
+        }
+
+        if (scanCallback == null || pnoScanCallback == null || executor == null) {
+            Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks");
+            return false;
+        }
+
+        IClientInterface clientInterface = null;
+        try {
+            clientInterface = mWificond.createClientInterface(ifaceName);
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
+            return false;
+        }
+
+        if (clientInterface == null) {
+            Log.e(TAG, "Could not get IClientInterface instance from wificond");
+            return false;
+        }
+        Binder.allowBlocking(clientInterface.asBinder());
+
+        // Refresh Handlers
+        mClientInterfaces.put(ifaceName, clientInterface);
+        try {
+            IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
+            if (wificondScanner == null) {
+                Log.e(TAG, "Failed to get WificondScannerImpl");
+                return false;
+            }
+            mWificondScanners.put(ifaceName, wificondScanner);
+            Binder.allowBlocking(wificondScanner.asBinder());
+            ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
+            mScanEventHandlers.put(ifaceName,  scanEventHandler);
+            wificondScanner.subscribeScanEvents(scanEventHandler);
+            PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
+                    pnoScanCallback);
+            mPnoScanEventHandlers.put(ifaceName,  pnoScanEventHandler);
+            wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
+        }
+
+        return true;
+    }
+
+    /**
+     * Tear down a specific client (STA) interface configured using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
+     *
+     * @param ifaceName Name of the interface to tear down.
+     * @return Returns true on success, false on failure (e.g. when called before an interface was
+     * set up).
+     */
+    public boolean tearDownClientInterface(@NonNull String ifaceName) {
+        if (getClientInterface(ifaceName) == null) {
+            Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
+            return false;
+        }
+        try {
+            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
+            if (scannerImpl != null) {
+                scannerImpl.unsubscribeScanEvents();
+                scannerImpl.unsubscribePnoScanEvents();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
+            return false;
+        }
+
+        if (mWificond == null) {
+            Log.e(TAG, "tearDownClientInterface: mWificond binder is null! Did wificond die?");
+            return false;
+        }
+
+        boolean success;
+        try {
+            success = mWificond.tearDownClientInterface(ifaceName);
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to teardown client interface due to remote exception");
+            return false;
+        }
+        if (!success) {
+            Log.e(TAG, "Failed to teardown client interface");
+            return false;
+        }
+
+        mClientInterfaces.remove(ifaceName);
+        mWificondScanners.remove(ifaceName);
+        mScanEventHandlers.remove(ifaceName);
+        mPnoScanEventHandlers.remove(ifaceName);
+        return true;
+    }
+
+    /**
+     * Set up interface as a Soft AP.
+     *
+     * @param ifaceName Name of the interface to configure.
+     * @return true on success.
+     */
+    public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) {
+        Log.d(TAG, "Setting up interface for soft ap mode for iface=" + ifaceName);
+        if (!retrieveWificondAndRegisterForDeath()) {
+            return false;
+        }
+
+        IApInterface apInterface = null;
+        try {
+            apInterface = mWificond.createApInterface(ifaceName);
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to get IApInterface due to remote exception");
+            return false;
+        }
+
+        if (apInterface == null) {
+            Log.e(TAG, "Could not get IApInterface instance from wificond");
+            return false;
+        }
+        Binder.allowBlocking(apInterface.asBinder());
+
+        // Refresh Handlers
+        mApInterfaces.put(ifaceName, apInterface);
+        return true;
+    }
+
+    /**
+     * Tear down a Soft AP interface configured using
+     * {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface to tear down.
+     * @return Returns true on success, false on failure (e.g. when called before an interface was
+     * set up).
+     */
+    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
+        if (getApInterface(ifaceName) == null) {
+            Log.e(TAG, "No valid wificond ap interface handler for iface=" + ifaceName);
+            return false;
+        }
+
+        if (mWificond == null) {
+            Log.e(TAG, "tearDownSoftApInterface: mWificond binder is null! Did wificond die?");
+            return false;
+        }
+
+        boolean success;
+        try {
+            success = mWificond.tearDownApInterface(ifaceName);
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
+            return false;
+        }
+        if (!success) {
+            Log.e(TAG, "Failed to teardown AP interface");
+            return false;
+        }
+        mApInterfaces.remove(ifaceName);
+        mApInterfaceListeners.remove(ifaceName);
+        return true;
+    }
+
+    /**
+    * Tear down all interfaces, whether clients (STA) or Soft AP.
+     *
+    * @return Returns true on success.
+    */
+    public boolean tearDownInterfaces() {
+        Log.d(TAG, "tearing down interfaces in wificond");
+        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
+        // could be used to cleanup before we setup any interfaces.
+        if (!retrieveWificondAndRegisterForDeath()) {
+            return false;
+        }
+
+        try {
+            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
+                entry.getValue().unsubscribeScanEvents();
+                entry.getValue().unsubscribePnoScanEvents();
+            }
+            mWificond.tearDownInterfaces();
+            clearState();
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
+        }
+
+        return false;
+    }
+
+    /** Helper function to look up the interface handle using name */
+    private IClientInterface getClientInterface(@NonNull String ifaceName) {
+        return mClientInterfaces.get(ifaceName);
+    }
+
+    /**
+     * Request signal polling.
+     *
+     * @param ifaceName Name of the interface on which to poll. The interface must have been
+     *                  already set up using
+     *{@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     *                  or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @return A {@link SignalPollResult} object containing interface statistics, or a null on
+     * error (e.g. the interface hasn't been set up yet).
+     */
+    @Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) {
+        IClientInterface iface = getClientInterface(ifaceName);
+        if (iface == null) {
+            Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
+            return null;
+        }
+
+        int[] resultArray;
+        try {
+            resultArray = iface.signalPoll();
+            if (resultArray == null || resultArray.length != 4) {
+                Log.e(TAG, "Invalid signal poll result from wificond");
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to do signal polling due to remote exception");
+            return null;
+        }
+        return new SignalPollResult(resultArray[0], resultArray[1], resultArray[3], resultArray[2]);
+    }
+
+    /**
+     * Get current transmit (Tx) packet counters of the specified interface. The interface must
+     * have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface.
+     * @return {@link TxPacketCounters} of the current interface or null on error (e.g. when
+     * called before the interface has been set up).
+     */
+    @Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
+        IClientInterface iface = getClientInterface(ifaceName);
+        if (iface == null) {
+            Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
+            return null;
+        }
+
+        int[] resultArray;
+        try {
+            resultArray = iface.getPacketCounters();
+            if (resultArray == null || resultArray.length != 2) {
+                Log.e(TAG, "Invalid signal poll result from wificond");
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to do signal polling due to remote exception");
+            return null;
+        }
+        return new TxPacketCounters(resultArray[0], resultArray[1]);
+    }
+
+    /** Helper function to look up the scanner impl handle using name */
+    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
+        return mWificondScanners.get(ifaceName);
+    }
+
+    /**
+     * Fetch the latest scan results of the indicated type for the specified interface. Note that
+     * this method fetches the latest results - it does not initiate a scan. Initiating a scan can
+     * be done using {@link #startScan(String, int, Set, List)} or
+     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface.
+     * @param scanType The type of scan result to be returned, can be
+     * {@link #SCAN_TYPE_SINGLE_SCAN} or {@link #SCAN_TYPE_PNO_SCAN}.
+     * @return Returns an array of {@link NativeScanResult} or an empty array on failure (e.g. when
+     * called before the interface has been set up).
+     */
+    @NonNull public List<NativeScanResult> getScanResults(@NonNull String ifaceName,
+            @ScanResultType int scanType) {
+        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
+        if (scannerImpl == null) {
+            Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
+            return new ArrayList<>();
+        }
+        List<NativeScanResult> results = null;
+        try {
+            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
+                results = Arrays.asList(scannerImpl.getScanResults());
+            } else {
+                results = Arrays.asList(scannerImpl.getPnoScanResults());
+            }
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to create ScanDetail ArrayList");
+        }
+        if (results == null) {
+            results = new ArrayList<>();
+        }
+        if (mVerboseLoggingEnabled) {
+            Log.d(TAG, "get " + results.size() + " scan results from wificond");
+        }
+
+        return results;
+    }
+
+    /**
+     * Return scan type for the parcelable {@link SingleScanSettings}
+     */
+    private static int getScanType(@WifiAnnotations.ScanType int scanType) {
+        switch (scanType) {
+            case WifiScanner.SCAN_TYPE_LOW_LATENCY:
+                return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN;
+            case WifiScanner.SCAN_TYPE_LOW_POWER:
+                return IWifiScannerImpl.SCAN_TYPE_LOW_POWER;
+            case WifiScanner.SCAN_TYPE_HIGH_ACCURACY:
+                return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY;
+            default:
+                throw new IllegalArgumentException("Invalid scan type " + scanType);
+        }
+    }
+
+    /**
+     * Start a scan using the specified parameters. A scan is an asynchronous operation. The
+     * result of the operation is returned in the {@link ScanEventCallback} registered when
+     * setting up an interface using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
+     * The latest scans can be obtained using {@link #getScanResults(String, int)} and using a
+     * {@link #SCAN_TYPE_SINGLE_SCAN} for the {@code scanType}.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface on which to initiate the scan.
+     * @param scanType Type of scan to perform, can be any of
+     * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, {@link WifiScanner#SCAN_TYPE_LOW_POWER}, or
+     * {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}.
+     * @param freqs list of frequencies to scan for, if null scan all supported channels.
+     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for, a null indicates that
+     *                           no hidden frequencies will be scanned for.
+     * @return Returns true on success, false on failure (e.g. when called before the interface
+     * has been set up).
+     */
+    public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
+            @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) {
+        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
+        if (scannerImpl == null) {
+            Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
+            return false;
+        }
+        SingleScanSettings settings = new SingleScanSettings();
+        try {
+            settings.scanType = getScanType(scanType);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Invalid scan type ", e);
+            return false;
+        }
+        settings.channelSettings  = new ArrayList<>();
+        settings.hiddenNetworks  = new ArrayList<>();
+
+        if (freqs != null) {
+            for (Integer freq : freqs) {
+                ChannelSettings channel = new ChannelSettings();
+                channel.frequency = freq;
+                settings.channelSettings.add(channel);
+            }
+        }
+        if (hiddenNetworkSSIDs != null) {
+            for (byte[] ssid : hiddenNetworkSSIDs) {
+                HiddenNetwork network = new HiddenNetwork();
+                network.ssid = ssid;
+
+                // settings.hiddenNetworks is expected to be very small, so this shouldn't cause
+                // any performance issues.
+                if (!settings.hiddenNetworks.contains(network)) {
+                    settings.hiddenNetworks.add(network);
+                }
+            }
+        }
+
+        try {
+            return scannerImpl.scan(settings);
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to request scan due to remote exception");
+        }
+        return false;
+    }
+
+    /**
+     * Request a PNO (Preferred Network Offload). The offload request and the scans are asynchronous
+     * operations. The result of the request are returned in the {@code callback} parameter which
+     * is an {@link PnoScanRequestCallback}. The scan results are are return in the
+     * {@link ScanEventCallback} which is registered when setting up an interface using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
+     * The latest PNO scans can be obtained using {@link #getScanResults(String, int)} with the
+     * {@code scanType} set to {@link #SCAN_TYPE_PNO_SCAN}.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface on which to request a PNO.
+     * @param pnoSettings PNO scan configuration.
+     * @param executor The Executor on which to execute the callback.
+     * @param callback Callback for the results of the offload request.
+     * @return true on success, false on failure (e.g. when called before the interface has been set
+     * up).
+     */
+    public boolean startPnoScan(@NonNull String ifaceName, @NonNull PnoSettings pnoSettings,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull PnoScanRequestCallback callback) {
+        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
+        if (scannerImpl == null) {
+            Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
+            return false;
+        }
+
+        if (callback == null || executor == null) {
+            Log.e(TAG, "startPnoScan called with a null callback");
+            return false;
+        }
+
+        try {
+            boolean success = scannerImpl.startPnoScan(pnoSettings);
+            if (success) {
+                executor.execute(callback::onPnoRequestSucceeded);
+            } else {
+                executor.execute(callback::onPnoRequestFailed);
+            }
+            return success;
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to start pno scan due to remote exception");
+        }
+        return false;
+    }
+
+    /**
+     * Stop PNO scan configured with
+     * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName Name of the interface on which the PNO scan was configured.
+     * @return true on success, false on failure (e.g. when called before the interface has been
+     * set up).
+     */
+    public boolean stopPnoScan(@NonNull String ifaceName) {
+        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
+        if (scannerImpl == null) {
+            Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
+            return false;
+        }
+        try {
+            return scannerImpl.stopPnoScan();
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to stop pno scan due to remote exception");
+        }
+        return false;
+    }
+
+    /**
+     * Abort ongoing single scan started with {@link #startScan(String, int, Set, List)}. No failure
+     * callback, e.g. {@link ScanEventCallback#onScanFailed()}, is triggered by this operation.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}. If the interface has not been set up then
+     * this method has no impact.
+     *
+     * @param ifaceName Name of the interface on which the scan was started.
+     */
+    public void abortScan(@NonNull String ifaceName) {
+        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
+        if (scannerImpl == null) {
+            Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
+            return;
+        }
+        try {
+            scannerImpl.abortScan();
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to request abortScan due to remote exception");
+        }
+    }
+
+    /**
+     * Query the list of valid frequencies (in MHz) for the provided band.
+     * The result depends on the on the country code that has been set.
+     *
+     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
+     * The following bands are supported:
+     * {@link WifiScanner#WIFI_BAND_24_GHZ},
+     * {@link WifiScanner#WIFI_BAND_5_GHZ},
+     * {@link WifiScanner#WIFI_BAND_5_GHZ_DFS_ONLY},
+     * {@link WifiScanner#WIFI_BAND_6_GHZ}
+     * {@link WifiScanner.WIFI_BAND_60_GHZ}
+     * @return frequencies vector of valid frequencies (MHz), or an empty array for error.
+     * @throws IllegalArgumentException if band is not recognized.
+     */
+    public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) {
+        if (mWificond == null) {
+            Log.e(TAG, "getChannelsMhzForBand: mWificond binder is null! Did wificond die?");
+            return new int[0];
+        }
+        int[] result = null;
+        try {
+            switch (band) {
+                case WifiScanner.WIFI_BAND_24_GHZ:
+                    result = mWificond.getAvailable2gChannels();
+                    break;
+                case WifiScanner.WIFI_BAND_5_GHZ:
+                    result = mWificond.getAvailable5gNonDFSChannels();
+                    break;
+                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
+                    result = mWificond.getAvailableDFSChannels();
+                    break;
+                case WifiScanner.WIFI_BAND_6_GHZ:
+                    result = mWificond.getAvailable6gChannels();
+                    break;
+                case WifiScanner.WIFI_BAND_60_GHZ:
+                    result = mWificond.getAvailable60gChannels();
+                    break;
+                default:
+                    throw new IllegalArgumentException("unsupported band " + band);
+            }
+        } catch (RemoteException e1) {
+            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
+        }
+        if (result == null) {
+            result = new int[0];
+        }
+        return result;
+    }
+
+    /** Helper function to look up the interface handle using name */
+    private IApInterface getApInterface(@NonNull String ifaceName) {
+        return mApInterfaces.get(ifaceName);
+    }
+
+    /**
+     * Get the device phy capabilities for a given interface.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @return DeviceWiphyCapabilities or null on error (e.g. when called on an interface which has
+     * not been set up).
+     */
+    @Nullable public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) {
+        if (mWificond == null) {
+            Log.e(TAG, "getDeviceWiphyCapabilities: mWificond binder is null! Did wificond die?");
+            return null;
+        }
+
+        try {
+            return mWificond.getDeviceWiphyCapabilities(ifaceName);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Register the provided callback handler for SoftAp events. The interface must first be created
+     * using {@link #setupInterfaceForSoftApMode(String)}. The callback registration is valid until
+     * the interface is deleted using {@link #tearDownSoftApInterface(String)} (no deregistration
+     * method is provided).
+     * <p>
+     * Note that only one callback can be registered at a time - any registration overrides previous
+     * registrations.
+     *
+     * @param ifaceName Name of the interface on which to register the callback.
+     * @param executor The Executor on which to execute the callbacks.
+     * @param callback Callback for AP events.
+     * @return true on success, false on failure (e.g. when called on an interface which has not
+     * been set up).
+     *
+     * @deprecated The usage is replaced by vendor HAL
+     * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}.
+     */
+    @Deprecated
+    public boolean registerApCallback(@NonNull String ifaceName,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SoftApCallback callback) {
+        IApInterface iface = getApInterface(ifaceName);
+        if (iface == null) {
+            Log.e(TAG, "No valid ap interface handler for iface=" + ifaceName);
+            return false;
+        }
+
+        if (callback == null || executor == null) {
+            Log.e(TAG, "registerApCallback called with a null callback");
+            return false;
+        }
+
+        try {
+            IApInterfaceEventCallback wificondCallback = new ApInterfaceEventCallback(executor,
+                    callback);
+            mApInterfaceListeners.put(ifaceName, wificondCallback);
+            boolean success = iface.registerCallback(wificondCallback);
+            if (!success) {
+                Log.e(TAG, "Failed to register ap callback.");
+                return false;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in registering AP callback: " + e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Send a management frame on the specified interface at the specified rate. Useful for probing
+     * the link with arbitrary frames.
+     *
+     * Note: The interface must have been already set up using
+     * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}
+     * or {@link #setupInterfaceForSoftApMode(String)}.
+     *
+     * @param ifaceName The interface on which to send the frame.
+     * @param frame The raw byte array of the management frame to tramit.
+     * @param mcs The MCS (modulation and coding scheme), i.e. rate, at which to transmit the
+     *            frame. Specified per IEEE 802.11.
+     * @param executor The Executor on which to execute the callbacks.
+     * @param callback A {@link SendMgmtFrameCallback} callback for results of the operation.
+     */
+    public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, int mcs,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SendMgmtFrameCallback callback) {
+
+        if (callback == null || executor == null) {
+            Log.e(TAG, "callback cannot be null!");
+            return;
+        }
+
+        if (frame == null) {
+            Log.e(TAG, "frame cannot be null!");
+            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
+            return;
+        }
+
+        // TODO (b/112029045) validate mcs
+        IClientInterface clientInterface = getClientInterface(ifaceName);
+        if (clientInterface == null) {
+            Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
+            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
+            return;
+        }
+
+        if (!mSendMgmtFrameInProgress.compareAndSet(false, true)) {
+            Log.e(TAG, "An existing management frame transmission is in progress!");
+            executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_ALREADY_STARTED));
+            return;
+        }
+
+        SendMgmtFrameEvent sendMgmtFrameEvent = new SendMgmtFrameEvent(executor, callback);
+        try {
+            clientInterface.SendMgmtFrame(frame, sendMgmtFrameEvent, mcs);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception while starting link probe: " + e);
+            // Call sendMgmtFrameEvent.OnFailure() instead of callback.onFailure() so that
+            // sendMgmtFrameEvent can clean up internal state, such as cancelling the timer.
+            sendMgmtFrameEvent.OnFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN);
+        }
+    }
+
+    /**
+     * Clear all internal handles.
+     */
+    private void clearState() {
+        // Refresh handlers
+        mClientInterfaces.clear();
+        mWificondScanners.clear();
+        mPnoScanEventHandlers.clear();
+        mScanEventHandlers.clear();
+        mApInterfaces.clear();
+        mApInterfaceListeners.clear();
+        mSendMgmtFrameInProgress.set(false);
+    }
+
+    /**
+     * OEM parsed security type
+     */
+    public static class OemSecurityType {
+        /** The protocol defined in {@link android.net.wifi.WifiAnnotations.Protocol}. */
+        public final @WifiAnnotations.Protocol int protocol;
+        /**
+         * Supported key management types defined
+         * in {@link android.net.wifi.WifiAnnotations.KeyMgmt}.
+         */
+        @NonNull public final List<Integer> keyManagement;
+        /**
+         * Supported pairwise cipher types defined
+         * in {@link android.net.wifi.WifiAnnotations.Cipher}.
+         */
+        @NonNull public final List<Integer> pairwiseCipher;
+        /** The group cipher type defined in {@link android.net.wifi.WifiAnnotations.Cipher}. */
+        public final @WifiAnnotations.Cipher int groupCipher;
+        /**
+         * Default constructor for OemSecurityType
+         *
+         * @param protocol The protocol defined in
+         *                 {@link android.net.wifi.WifiAnnotations.Protocol}.
+         * @param keyManagement Supported key management types defined
+         *                      in {@link android.net.wifi.WifiAnnotations.KeyMgmt}.
+         * @param pairwiseCipher Supported pairwise cipher types defined
+         *                       in {@link android.net.wifi.WifiAnnotations.Cipher}.
+         * @param groupCipher The group cipher type defined
+         *                    in {@link android.net.wifi.WifiAnnotations.Cipher}.
+         */
+        public OemSecurityType(
+                @WifiAnnotations.Protocol int protocol,
+                @NonNull List<Integer> keyManagement,
+                @NonNull List<Integer> pairwiseCipher,
+                @WifiAnnotations.Cipher int groupCipher) {
+            this.protocol = protocol;
+            this.keyManagement = (keyManagement != null)
+                ? keyManagement : new ArrayList<Integer>();
+            this.pairwiseCipher = (pairwiseCipher != null)
+                ? pairwiseCipher : new ArrayList<Integer>();
+            this.groupCipher = groupCipher;
+        }
+    }
+
+    /**
+     * OEM information element parser for security types not parsed by the framework.
+     *
+     * The OEM method should use the method inputs {@code id}, {@code idExt}, and {@code bytes}
+     * to perform the parsing. The method should place the results in an OemSecurityType objct.
+     *
+     * @param id The information element id.
+     * @param idExt The information element extension id. This is valid only when id is
+     *        the extension id, {@code 255}.
+     * @param bytes The raw bytes of information element data, 'Element ID' and 'Length' are
+     *              stripped off already.
+     * @return an OemSecurityType object if this IE is parsed successfully, null otherwise.
+     */
+    @Nullable public static OemSecurityType parseOemSecurityTypeElement(
+            int id,
+            int idExt,
+            @NonNull byte[] bytes) {
+        return null;
+    }
+}
diff --git a/wifi/non-updatable/tests/Android.bp b/wifi/non-updatable/tests/Android.bp
new file mode 100644
index 0000000..3f5cacf
--- /dev/null
+++ b/wifi/non-updatable/tests/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "FrameworksWifiNonUpdatableApiTests",
+
+    defaults: ["framework-wifi-test-defaults"],
+
+    srcs: ["src/**/*.java"],
+
+    jacoco: {
+        include_filter: ["android.net.wifi.*"],
+        // TODO(b/147521214) need to exclude test classes
+        exclude_filter: [],
+    },
+
+    static_libs: [
+        "androidx.test.rules",
+        "frameworks-base-testutils",
+        "guava",
+        "mockito-target-minus-junit4",
+        "truth-prebuilt",
+    ],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    test_suites: [
+        "general-tests",
+    ],
+}
diff --git a/wifi/non-updatable/tests/AndroidManifest.xml b/wifi/non-updatable/tests/AndroidManifest.xml
new file mode 100644
index 0000000..b4b6b2d
--- /dev/null
+++ b/wifi/non-updatable/tests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="android.net.wifi.test">
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+        <activity android:label="WifiTestDummyLabel"
+             android:name="WifiTestDummyName"
+             android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+         android:targetPackage="android.net.wifi.test"
+         android:label="Frameworks Wifi Non-updatable API Tests">
+    </instrumentation>
+
+</manifest>
diff --git a/wifi/non-updatable/tests/AndroidTest.xml b/wifi/non-updatable/tests/AndroidTest.xml
new file mode 100644
index 0000000..5f3fdd4
--- /dev/null
+++ b/wifi/non-updatable/tests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs Frameworks Wifi Non-updatable API Tests.">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="test-file-name" value="FrameworksWifiNonUpdatableApiTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-tag" value="FrameworksWifiNonUpdatableApiTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.net.wifi.test" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/wifi/non-updatable/tests/README.md b/wifi/non-updatable/tests/README.md
new file mode 100644
index 0000000..ad535f4
--- /dev/null
+++ b/wifi/non-updatable/tests/README.md
@@ -0,0 +1,32 @@
+# Wifi Non-Updatable Framework Unit Tests
+This package contains unit tests for the non-updatable part (i.e. outside the Wifi module) of the
+Android Wifi framework APIs based on the
+[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html).
+The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/)
+libraries.
+
+## Running Tests
+The easiest way to run tests is simply run
+
+```
+atest android.net.wifi
+```
+
+To pick up changes in framework/base, you will need to:
+1. rebuild the framework library 'make -j32'
+2. sync over the updated library to the device 'adb sync'
+3. restart framework on the device 'adb shell stop' then 'adb shell start'
+
+To enable syncing data to the device for first time after clean reflash:
+1. adb disable-verity
+2. adb reboot
+3. adb remount
+
+## Adding Tests
+Tests can be added by adding classes to the src directory. JUnit4 style test cases can
+be written by simply annotating test methods with `org.junit.Test`.
+
+## Debugging Tests
+If you are trying to debug why tests are not doing what you expected, you can add android log
+statements and use logcat to view them. The beginning and end of every tests is automatically logged
+with the tag `TestRunner`.
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java b/wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
diff --git a/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
new file mode 100644
index 0000000..c4967eb
--- /dev/null
+++ b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.NetworkKey;
+import android.net.RssiCurve;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.net.wifi.WifiNetworkScoreCache.CacheListener;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/** Unit tests for {@link WifiNetworkScoreCache}. */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WifiNetworkScoreCacheTest {
+
+    public static final String SSID = "ssid";
+    public static final String SSID2 = "ssid2";
+    public static final String SSID3 = "ssid3";
+    public static final String FORMATTED_SSID = "\"" + SSID + "\"";
+    public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\"";
+    public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\"";
+    public static final String BSSID = "AA:AA:AA:AA:AA:AA";
+
+    public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID);
+
+    public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID);
+
+    @Mock private Context mockApplicationContext;
+    @Mock private Context mockContext; // isn't used, can be null
+    @Mock private RssiCurve mockRssiCurve;
+
+
+    private CacheListener mCacheListener;
+    private CountDownLatch mLatch;
+    private Handler mHandler;
+    private List<ScoredNetwork> mUpdatedNetworksCaptor;
+    private ScoredNetwork mValidScoredNetwork;
+    private WifiNetworkScoreCache mScoreCache;
+
+    private static ScanResult buildScanResult(String ssid, String bssid) {
+        return new ScanResult(
+                WifiSsid.createFromAsciiEncoded(ssid),
+                bssid,
+                "" /* caps */,
+                0 /* level */,
+                0 /* frequency */,
+                0 /* tsf */,
+                0 /* distCm */,
+                0 /* distSdCm*/);
+    }
+
+    private static ScoredNetwork buildScoredNetwork(WifiKey key, RssiCurve curve) {
+        return new ScoredNetwork(new NetworkKey(key), curve);
+    }
+
+    // Called from setup
+    private void initializeCacheWithValidScoredNetwork() {
+        mScoreCache.updateScores(ImmutableList.of(mValidScoredNetwork));
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mockContext.getApplicationContext()).thenReturn(mockApplicationContext);
+
+        mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mockRssiCurve);
+        mScoreCache = new WifiNetworkScoreCache(mockContext);
+        initializeCacheWithValidScoredNetwork();
+
+        HandlerThread thread = new HandlerThread("WifiNetworkScoreCacheTest Handler Thread");
+        thread.start();
+        mHandler = new Handler(thread.getLooper());
+        mLatch = new CountDownLatch(1);
+        mCacheListener = new CacheListener(mHandler) {
+            @Override
+            public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
+                mUpdatedNetworksCaptor = updatedNetworks;
+                mLatch.countDown();
+            }
+        };
+    }
+
+
+    @Test
+    public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() {
+        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue();
+    }
+
+    @Test
+    public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() {
+        mScoreCache.clearScores();
+        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse();
+    }
+
+    @Test
+    public void updateScoresShouldAddNewNetwork() {
+        WifiKey key2 = new WifiKey("\"ssid2\"", BSSID);
+        ScoredNetwork network2 = buildScoredNetwork(key2, mockRssiCurve);
+        ScanResult result2 = buildScanResult("ssid2", BSSID);
+
+        mScoreCache.updateScores(ImmutableList.of(network2));
+
+        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue();
+        assertThat(mScoreCache.isScoredNetwork(result2)).isTrue();
+    }
+
+    @Test
+    public void hasScoreCurveShouldReturnTrue() {
+        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue();
+    }
+
+    @Test
+    public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() {
+        ScanResult unscored = buildScanResult("fake", BSSID);
+        assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse();
+    }
+
+    @Test
+    public void hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve() {
+        ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */);
+        mScoreCache.updateScores(ImmutableList.of(noCurve));
+
+        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse();
+    }
+
+    @Test
+    public void getNetworkScoreShouldReturnScore() {
+        final byte score = 50;
+        final int rssi = -70;
+        ScanResult result = new ScanResult(VALID_SCAN_RESULT);
+        result.level = rssi;
+
+        when(mockRssiCurve.lookupScore(rssi)).thenReturn(score);
+
+        assertThat(mScoreCache.getNetworkScore(result)).isEqualTo(score);
+    }
+
+    @Test
+    public void getMeteredHintShouldReturnFalse() {
+        assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse();
+    }
+
+    @Test
+    public void getMeteredHintShouldReturnTrue() {
+        ScoredNetwork network =
+                new ScoredNetwork(
+                    new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */);
+        mScoreCache.updateScores(ImmutableList.of(network));
+
+        assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue();
+    }
+
+    @Test
+    public void updateScoresShouldInvokeCacheListener_networkCacheUpdated() {
+        mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener);
+        initializeCacheWithValidScoredNetwork();
+
+        try {
+            mLatch.await(1, TimeUnit.SECONDS); // wait for listener to be executed
+        } catch (InterruptedException e) {
+            fail("Interrupted Exception while waiting for listener to be invoked.");
+        }
+        // One network should be updated.
+        assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1);
+        assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork);
+    }
+
+    @Test
+    public void leastRecentlyUsedScore_shouldBeEvictedFromCache() {
+        mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener, 2 /* maxCacheSize */);
+
+        ScoredNetwork network1 = mValidScoredNetwork;
+        ScoredNetwork network2 = buildScoredNetwork(
+                new WifiKey(FORMATTED_SSID2, BSSID), mockRssiCurve);
+        ScoredNetwork network3 = buildScoredNetwork(
+                new WifiKey(FORMATTED_SSID3, BSSID), mockRssiCurve);
+        mScoreCache.updateScores(ImmutableList.of(network1));
+        mScoreCache.updateScores(ImmutableList.of(network2));
+
+        // First score should be evicted because max cache size has been reached.
+        mScoreCache.updateScores(ImmutableList.of(network3));
+
+        assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue();
+        assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue();
+        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse();
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
diff --git a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java
new file mode 100644
index 0000000..2f6b724
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java
@@ -0,0 +1,502 @@
+/*
+ * 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.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.GroupCipher;
+import android.net.wifi.WifiConfiguration.GroupMgmtCipher;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.BitSet;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiInfo}.
+ */
+@SmallTest
+public class SecurityParamsTest {
+
+    private void verifySecurityParams(SecurityParams params,
+            int expectedSecurityType,
+            int[] expectedAllowedKeyManagement,
+            int[] expectedAllowedProtocols,
+            int[] expectedAllowedAuthAlgorithms,
+            int[] expectedAllowedPairwiseCiphers,
+            int[] expectedAllowedGroupCiphers,
+            boolean expectedRequirePmf) {
+        assertTrue(params.isSecurityType(expectedSecurityType));
+        for (int b: expectedAllowedKeyManagement) {
+            assertTrue(params.getAllowedKeyManagement().get(b));
+        }
+        for (int b: expectedAllowedProtocols) {
+            assertTrue(params.getAllowedProtocols().get(b));
+        }
+        for (int b: expectedAllowedAuthAlgorithms) {
+            assertTrue(params.getAllowedAuthAlgorithms().get(b));
+        }
+        for (int b: expectedAllowedPairwiseCiphers) {
+            assertTrue(params.getAllowedPairwiseCiphers().get(b));
+        }
+        for (int b: expectedAllowedGroupCiphers) {
+            assertTrue(params.getAllowedGroupCiphers().get(b));
+        }
+        assertEquals(expectedRequirePmf, params.isRequirePmf());
+    }
+
+    /** Verify EAP params creator. */
+    @Test
+    public void testEapCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWpaWpa2EnterpriseParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify Passpoint R1 params creator. */
+    @Test
+    public void testEapPasspointR1Creator() throws Exception {
+        SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1);
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify Passpoint R2 params creator. */
+    @Test
+    public void testEapPasspointR2Creator() throws Exception {
+        SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2);
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify Passpoint R3 params creator. */
+    @Test
+    public void testEapPasspointR3Creator() throws Exception {
+        SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3);
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = true;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify Enhanced Open params creator. */
+    @Test
+    public void testEnhancedOpenCreator() throws Exception {
+        SecurityParams p = SecurityParams.createEnhancedOpenParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OWE;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OWE};
+        int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {
+                PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+        int[] expectedAllowedGroupCiphers = new int[] {
+                GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+        boolean expectedRequirePmf = true;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify Open params creator. */
+    @Test
+    public void testOpenCreator() throws Exception {
+        SecurityParams p = SecurityParams.createOpenParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify OSEN params creator. */
+    @Test
+    public void testOsenCreator() throws Exception {
+        SecurityParams p = SecurityParams.createOsenParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OSEN};
+        int[] expectedAllowedProtocols = new int[] {Protocol.OSEN};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WAPI CERT params creator. */
+    @Test
+    public void testWapiCertCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWapiCertParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_CERT};
+        int[] expectedAllowedProtocols = new int[] {Protocol.WAPI};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4};
+        int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WAPI PSK params creator. */
+    @Test
+    public void testWapiPskCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWapiPskParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_PSK};
+        int[] expectedAllowedProtocols = new int[] {Protocol.WAPI};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4};
+        int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WEP params creator. */
+    @Test
+    public void testWepCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWepParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WEP;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {AuthAlgorithm.OPEN, AuthAlgorithm.SHARED};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WPA3 Enterprise 192-bit params creator. */
+    @Test
+    public void testWpa3Enterprise192BitCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWpa3Enterprise192BitParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
+        int[] expectedAllowedKeyManagement = new int[] {
+                KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X, KeyMgmt.SUITE_B_192};
+        int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {
+                PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+        int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+        boolean expectedRequirePmf = true;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+
+        assertTrue(p.getAllowedGroupManagementCiphers().get(GroupMgmtCipher.BIP_GMAC_256));
+    }
+
+    /** Verify WPA3 Enterprise params creator. */
+    @Test
+    public void testWpa3EnterpriseCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWpa3EnterpriseParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+        int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {
+                PairwiseCipher.CCMP, PairwiseCipher.GCMP_256};
+        int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.CCMP, GroupCipher.GCMP_256};
+        boolean expectedRequirePmf = true;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WPA3 Personal params creator. */
+    @Test
+    public void testWpa3PersonalCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWpa3PersonalParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_SAE;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.SAE};
+        int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {
+                PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+        int[] expectedAllowedGroupCiphers = new int[] {
+                GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+        boolean expectedRequirePmf = true;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify WPA2 Personal EAP params creator. */
+    @Test
+    public void testWpaWpa2PersonalCreator() throws Exception {
+        SecurityParams p = SecurityParams.createWpaWpa2PersonalParams();
+        int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+        int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_PSK};
+        int[] expectedAllowedProtocols = new int[] {};
+        int[] expectedAllowedAuthAlgorithms = new int[] {};
+        int[] expectedAllowedPairwiseCiphers = new int[] {};
+        int[] expectedAllowedGroupCiphers = new int[] {};
+        boolean expectedRequirePmf = false;
+        verifySecurityParams(p, expectedSecurityType,
+                expectedAllowedKeyManagement, expectedAllowedProtocols,
+                expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+                expectedAllowedGroupCiphers, expectedRequirePmf);
+    }
+
+    /** Verify setter/getter methods */
+    @Test
+    public void testCommonSetterGetter() throws Exception {
+        SecurityParams params = SecurityParams.createWpaWpa2PersonalParams();
+
+        // PSK setting
+        BitSet allowedKeyManagement = new BitSet();
+        allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+
+        BitSet allowedProtocols = new BitSet();
+        allowedProtocols.set(Protocol.RSN);
+        allowedProtocols.set(Protocol.WPA);
+
+        BitSet allowedPairwiseCiphers = new BitSet();
+        allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+        allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+        BitSet allowedGroupCiphers = new BitSet();
+        allowedGroupCiphers.set(GroupCipher.CCMP);
+        allowedGroupCiphers.set(GroupCipher.TKIP);
+        allowedGroupCiphers.set(GroupCipher.WEP40);
+        allowedGroupCiphers.set(GroupCipher.WEP104);
+
+        assertEquals(allowedKeyManagement, params.getAllowedKeyManagement());
+        assertTrue(params.getAllowedKeyManagement().get(KeyMgmt.WPA_PSK));
+
+        assertEquals(allowedProtocols, params.getAllowedProtocols());
+        assertTrue(params.getAllowedProtocols().get(Protocol.RSN));
+        assertTrue(params.getAllowedProtocols().get(Protocol.WPA));
+
+        assertEquals(allowedPairwiseCiphers, params.getAllowedPairwiseCiphers());
+        assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.CCMP));
+        assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.TKIP));
+
+        assertEquals(allowedGroupCiphers, params.getAllowedGroupCiphers());
+        assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.CCMP));
+        assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.TKIP));
+        assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP40));
+        assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP104));
+
+        params.setEnabled(false);
+        assertFalse(params.isEnabled());
+    }
+
+    /** Verify SAE-specific methods */
+    @Test
+    public void testSaeMethods() throws Exception {
+        SecurityParams p = SecurityParams.createWpa3PersonalParams();
+
+        assertFalse(p.isAddedByAutoUpgrade());
+        p.setIsAddedByAutoUpgrade(true);
+        assertTrue(p.isAddedByAutoUpgrade());
+
+        assertFalse(p.isSaeH2eOnlyMode());
+        p.enableSaeH2eOnlyMode(true);
+        assertTrue(p.isSaeH2eOnlyMode());
+
+        assertFalse(p.isSaePkOnlyMode());
+        p.enableSaePkOnlyMode(true);
+        assertTrue(p.isSaePkOnlyMode());
+    }
+
+    /** Verify copy constructor. */
+    @Test
+    public void testCopyConstructor() throws Exception {
+        SecurityParams params = SecurityParams.createWpaWpa2PersonalParams();
+        params.setEnabled(false);
+        params.setIsAddedByAutoUpgrade(true);
+
+        SecurityParams copiedParams = new SecurityParams(params);
+
+        assertTrue(params.isSameSecurityType(copiedParams));
+        assertEquals(params.getAllowedKeyManagement(), copiedParams.getAllowedKeyManagement());
+        assertEquals(params.getAllowedProtocols(), copiedParams.getAllowedProtocols());
+        assertEquals(params.getAllowedAuthAlgorithms(), copiedParams.getAllowedAuthAlgorithms());
+        assertEquals(params.getAllowedPairwiseCiphers(), copiedParams.getAllowedPairwiseCiphers());
+        assertEquals(params.getAllowedGroupCiphers(), copiedParams.getAllowedGroupCiphers());
+        assertEquals(params.getAllowedGroupManagementCiphers(),
+                copiedParams.getAllowedGroupManagementCiphers());
+        assertEquals(params.getAllowedSuiteBCiphers(), copiedParams.getAllowedSuiteBCiphers());
+        assertEquals(params.isRequirePmf(), copiedParams.isRequirePmf());
+        assertEquals(params.isEnabled(), copiedParams.isEnabled());
+        assertEquals(params.isSaeH2eOnlyMode(), copiedParams.isSaeH2eOnlyMode());
+        assertEquals(params.isSaePkOnlyMode(), copiedParams.isSaePkOnlyMode());
+        assertEquals(params.isAddedByAutoUpgrade(), copiedParams.isAddedByAutoUpgrade());
+    }
+
+    /** Check that two params are equal if and only if their types are the same. */
+    @Test
+    public void testEquals() {
+        SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams();
+        SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams();
+        SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams();
+        assertEquals(saeParams1, saeParams2);
+        assertNotEquals(saeParams1, pskParams);
+    }
+
+    /** Check that hash values are the same if and only if their types are the same. */
+    @Test
+    public void testHashCode() {
+        SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams();
+        SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams();
+        SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams();
+        assertEquals(saeParams1.hashCode(), saeParams2.hashCode());
+        assertNotEquals(saeParams1.hashCode(), pskParams.hashCode());
+    }
+
+    /** Verify open network check */
+    @Test
+    public void testIsOpenNetwork() {
+        SecurityParams[] openSecurityParams = new SecurityParams[] {
+                SecurityParams.createEnhancedOpenParams(),
+                SecurityParams.createOpenParams(),
+        };
+        for (SecurityParams p: openSecurityParams) {
+            assertTrue(p.isOpenSecurityType());
+        }
+
+        SecurityParams[] nonOpenSecurityParams = new SecurityParams[] {
+                SecurityParams.createWpaWpa2EnterpriseParams(),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3),
+                SecurityParams.createOsenParams(),
+                SecurityParams.createWapiCertParams(),
+                SecurityParams.createWapiPskParams(),
+                SecurityParams.createWepParams(),
+                SecurityParams.createWpa3Enterprise192BitParams(),
+                SecurityParams.createWpa3EnterpriseParams(),
+                SecurityParams.createWpa3PersonalParams(),
+                SecurityParams.createWpaWpa2PersonalParams(),
+        };
+        for (SecurityParams p: nonOpenSecurityParams) {
+            assertFalse(p.isOpenSecurityType());
+        }
+    }
+
+    /** Verify enterprise network check */
+    @Test
+    public void testIsEnterpriseNetwork() {
+        SecurityParams[] enterpriseSecurityParams = new SecurityParams[] {
+                SecurityParams.createWpaWpa2EnterpriseParams(),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2),
+                SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3),
+                SecurityParams.createWapiCertParams(),
+                SecurityParams.createWpa3Enterprise192BitParams(),
+                SecurityParams.createWpa3EnterpriseParams(),
+        };
+        for (SecurityParams p: enterpriseSecurityParams) {
+            assertTrue(p.isEnterpriseSecurityType());
+        }
+
+        SecurityParams[] nonEnterpriseSecurityParams = new SecurityParams[] {
+                SecurityParams.createEnhancedOpenParams(),
+                SecurityParams.createOpenParams(),
+                SecurityParams.createOsenParams(),
+                SecurityParams.createWapiPskParams(),
+                SecurityParams.createWepParams(),
+                SecurityParams.createWpa3PersonalParams(),
+                SecurityParams.createWpaWpa2PersonalParams(),
+        };
+        for (SecurityParams p: nonEnterpriseSecurityParams) {
+            assertFalse(p.isEnterpriseSecurityType());
+        }
+    }
+
+    /** Check that parcel marshalling/unmarshalling works */
+    @Test
+    public void testParcelMethods() {
+        SecurityParams params = SecurityParams.createWpa3PersonalParams();
+
+        Parcel parcelW = Parcel.obtain();
+        params.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+
+        SecurityParams reParams = SecurityParams.createFromParcel(parcelR);
+        assertEquals(params, reParams);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java
index 702212b..9e3b022 100644
--- a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java
@@ -42,10 +42,12 @@
                 | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
         int[] testSupported2Glist = {1, 2, 3, 4};
         int[] testSupported5Glist = {36, 149};
+        int[] testSupported60Glist = {1, 2};
         SoftApCapability capability = new SoftApCapability(testSoftApFeature);
         capability.setMaxSupportedClients(10);
         capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist);
         capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist);
+        capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist);
 
         SoftApCapability copiedCapability = new SoftApCapability(capability);
 
@@ -64,9 +66,11 @@
         capability.setMaxSupportedClients(10);
         int[] testSupported2Glist = {1, 2, 3, 4};
         int[] testSupported5Glist = {36, 149};
+        int[] testSupported60Glist = {1, 2};
 
         capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist);
         capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist);
+        capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist);
 
         Parcel parcelW = Parcel.obtain();
         capability.writeToParcel(parcelW, 0);
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index ad0fdd3..a609a12 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -20,6 +20,7 @@
 
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.net.MacAddress;
 import android.os.Parcel;
@@ -371,6 +372,7 @@
 
     @Test
     public void testDualBands() {
+        assumeTrue(SdkLevel.isAtLeastS());
         int[] dual_bands = new int[2];
         dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
         dual_bands[1] = SoftApConfiguration.BAND_5GHZ;
@@ -384,6 +386,7 @@
 
     @Test
     public void testDualChannels() {
+        assumeTrue(SdkLevel.isAtLeastS());
         int[] expected_dual_bands = new int[2];
         expected_dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
         expected_dual_bands[1] = SoftApConfiguration.BAND_5GHZ;
@@ -417,6 +420,7 @@
 
     @Test
     public void testInvalidBandWhenSetBands() {
+        assumeTrue(SdkLevel.isAtLeastS());
         boolean isIllegalArgumentExceptionHappened = false;
         int[] dual_bands = new int[2];
         dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
@@ -457,6 +461,7 @@
 
     @Test
     public void testInvalidConfigWhenSetChannels() {
+        assumeTrue(SdkLevel.isAtLeastS());
         boolean isIllegalArgumentExceptionHappened = false;
         SparseIntArray invalid_channels = new SparseIntArray();
         try {
@@ -514,4 +519,14 @@
         }
         assertTrue(isIllegalArgumentExceptionHappened);
     }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConfigWhenSet60GhzChannels() throws Exception {
+        SparseIntArray invalid_channels = new SparseIntArray();
+        invalid_channels.put(SoftApConfiguration.BAND_60GHZ, 99);
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setSsid("ssid")
+                .setChannels(invalid_channels)
+                .build();
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
index 2875843..2121d10 100644
--- a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -32,17 +32,22 @@
  */
 @SmallTest
 public class SoftApInfoTest {
-
+    private static final String TEST_AP_INSTANCE = "wlan1";
+    private static final int TEST_FREQUENCY = 2412;
+    private static final int TEST_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
+    private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_LEGACY;
+    private static final MacAddress TEST_AP_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
     /**
      * Verifies copy constructor.
      */
     @Test
     public void testCopyOperator() throws Exception {
         SoftApInfo info = new SoftApInfo();
-        info.setFrequency(2412);
-        info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
-        info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
-        info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY);
+        info.setFrequency(TEST_FREQUENCY);
+        info.setBandwidth(TEST_BANDWIDTH);
+        info.setBssid(TEST_AP_MAC);
+        info.setWifiStandard(TEST_WIFI_STANDARD);
+        info.setApInstanceIdentifier(TEST_AP_INSTANCE);
 
 
         SoftApInfo copiedInfo = new SoftApInfo(info);
@@ -57,10 +62,11 @@
     @Test
     public void testParcelOperation() throws Exception {
         SoftApInfo info = new SoftApInfo();
-        info.setFrequency(2412);
-        info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
-        info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
-        info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY);
+        info.setFrequency(TEST_FREQUENCY);
+        info.setBandwidth(TEST_BANDWIDTH);
+        info.setBssid(TEST_AP_MAC);
+        info.setWifiStandard(TEST_WIFI_STANDARD);
+        info.setApInstanceIdentifier(TEST_AP_INSTANCE);
 
         Parcel parcelW = Parcel.obtain();
         info.writeToParcel(parcelW, 0);
@@ -88,6 +94,27 @@
         if (SdkLevel.isAtLeastS()) {
             assertEquals(info.getBssid(), null);
             assertEquals(info.getWifiStandard(), ScanResult.WIFI_STANDARD_UNKNOWN);
+            assertEquals(info.getApInstanceIdentifier(), null);
+        }
+    }
+
+    /**
+     * Verifies the set/get method same as expected.
+     */
+    @Test
+    public void testGetXXXAlignedWithSetXXX() throws Exception {
+        SoftApInfo info = new SoftApInfo();
+        info.setFrequency(TEST_FREQUENCY);
+        info.setBandwidth(TEST_BANDWIDTH);
+        info.setBssid(TEST_AP_MAC);
+        info.setWifiStandard(TEST_WIFI_STANDARD);
+        info.setApInstanceIdentifier(TEST_AP_INSTANCE);
+        assertEquals(info.getFrequency(), TEST_FREQUENCY);
+        assertEquals(info.getBandwidth(), TEST_BANDWIDTH);
+        if (SdkLevel.isAtLeastS()) {
+            assertEquals(info.getBssid(), TEST_AP_MAC);
+            assertEquals(info.getWifiStandard(), TEST_WIFI_STANDARD);
+            assertEquals(info.getApInstanceIdentifier(), TEST_AP_INSTANCE);
         }
     }
 
diff --git a/wifi/tests/src/android/net/wifi/WifiClientTest.java b/wifi/tests/src/android/net/wifi/WifiClientTest.java
index 7a3baf9..7046563 100644
--- a/wifi/tests/src/android/net/wifi/WifiClientTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiClientTest.java
@@ -42,9 +42,9 @@
      */
     @Test
     public void testWifiClientParcelWriteRead() throws Exception {
-        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
+        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
 
-        assertParcelSane(writeWifiClient, 1);
+        assertParcelSane(writeWifiClient, 2);
     }
 
     /**
@@ -52,12 +52,12 @@
      */
     @Test
     public void testWifiClientEquals() throws Exception {
-        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
-        WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS);
+        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+        WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
 
         assertEquals(writeWifiClient, writeWifiClientEquals);
         assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode());
-        assertFieldCountEquals(1, WifiClient.class);
+        assertFieldCountEquals(2, WifiClient.class);
     }
 
     /**
@@ -66,8 +66,8 @@
     @Test
     public void testWifiClientNotEquals() throws Exception {
         final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00");
-        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
-        WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals);
+        WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+        WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME);
 
         assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
         assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index c253746..f351e61 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -20,11 +20,13 @@
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OSEN;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -34,9 +36,13 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.MacAddress;
+import android.net.wifi.WifiConfiguration.GroupCipher;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
 import android.os.Parcel;
+import android.util.Pair;
 
 import androidx.test.filters.SmallTest;
 
@@ -45,6 +51,8 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.List;
+
 /**
  * Unit tests for {@link android.net.wifi.WifiConfiguration}.
  */
@@ -187,18 +195,24 @@
 
     @Test
     public void testIsOpenNetwork_NotOpen_HasAuthType() {
-        for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) {
-            if (keyMgmt == WifiConfiguration.KeyMgmt.NONE
-                    || keyMgmt == WifiConfiguration.KeyMgmt.OWE) {
-                continue;
-            }
+        int[] securityTypes = new int [] {
+                SECURITY_TYPE_WEP,
+                SECURITY_TYPE_PSK,
+                SECURITY_TYPE_EAP,
+                SECURITY_TYPE_SAE,
+                SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+                SECURITY_TYPE_WAPI_PSK,
+                SECURITY_TYPE_WAPI_CERT,
+                SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
+                SECURITY_TYPE_OSEN,
+        };
+        for (int type: securityTypes) {
             WifiConfiguration config = new WifiConfiguration();
-            config.allowedKeyManagement.clear();
-            config.allowedKeyManagement.set(keyMgmt);
+            config.setSecurityParams(type);
             config.wepKeys = null;
 
-            assertFalse("Open network reported when key mgmt was set to "
-                            + WifiConfiguration.KeyMgmt.strings[keyMgmt], config.isOpenNetwork());
+            assertFalse("Open network reported when security type was set to "
+                            + type, config.isOpenNetwork());
         }
     }
 
@@ -208,6 +222,7 @@
         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
         config.wepKeys = null;
+        config.convertLegacyFieldsToSecurityParamsIfNeeded();
 
         assertFalse(config.isOpenNetwork());
     }
@@ -865,4 +880,243 @@
         }
         return sb.toString();
     }
+
+    private void verifyAllowedKeyManagement(WifiConfiguration config, int[] akms) {
+        for (int akm: akms) {
+            assertTrue(config.getSecurityParamsList().stream()
+                    .anyMatch(params -> params.getAllowedKeyManagement().get(akm)));
+        }
+    }
+
+    private void verifyAllowedProtocols(WifiConfiguration config, int[] aps) {
+        for (int ap: aps) {
+            assertTrue(config.getSecurityParamsList().stream()
+                    .anyMatch(params -> params.getAllowedProtocols().get(ap)));
+        }
+    }
+
+    private void verifyAllowedPairwiseCiphers(WifiConfiguration config, int[] apcs) {
+        for (int apc: apcs) {
+            assertTrue(config.getSecurityParamsList().stream()
+                    .anyMatch(params -> params.getAllowedPairwiseCiphers().get(apc)));
+        }
+    }
+
+    private void verifyAllowedGroupCiphers(WifiConfiguration config, int[] agcs) {
+        for (int agc: agcs) {
+            assertTrue(config.getSecurityParamsList().stream()
+                    .anyMatch(params -> params.getAllowedGroupCiphers().get(agc)));
+        }
+    }
+
+    /** Verify that adding security types works as expected. */
+    @Test
+    public void testAddSecurityTypes() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+        config.addSecurityParams(SecurityParams.createWapiPskParams());
+        List<SecurityParams> paramsList = config.getSecurityParamsList();
+        assertEquals(3, paramsList.size());
+
+        verifyAllowedKeyManagement(config, new int[] {
+                KeyMgmt.WPA_PSK, KeyMgmt.SAE, KeyMgmt.WAPI_PSK});
+        verifyAllowedProtocols(config, new int[] {Protocol.WPA, Protocol.RSN, Protocol.WAPI});
+        verifyAllowedPairwiseCiphers(config, new int[] {
+                PairwiseCipher.CCMP, PairwiseCipher.TKIP,
+                PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256,
+                PairwiseCipher.SMS4});
+        verifyAllowedGroupCiphers(config, new int[] {
+                GroupCipher.CCMP, GroupCipher.TKIP,
+                GroupCipher.GCMP_128, GroupCipher.GCMP_256,
+                GroupCipher.SMS4});
+    }
+
+    /** Check that a personal security type can be added to a personal configuration. */
+    @Test
+    public void testAddPersonalTypeToPersonalConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+    }
+
+    /** Check that an enterprise security type can be added to an enterprise configuration. */
+    @Test
+    public void testAddEnterpriseTypeToEnterpriseConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+    }
+
+    /** Verify that adding an enterprise type to a personal configuration. */
+    @Test (expected = IllegalArgumentException.class)
+    public void testAddEnterpriseTypeToPersonalConfig() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+    }
+
+    /** Verify that adding a personal type to an enterprise configuration. */
+    @Test (expected = IllegalArgumentException.class)
+    public void testAddPersonalTypeToEnterpriseConfig() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+    }
+
+    /** Check that an open security cannot be added to a non-open configuration. */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddOpenTypeToNonOpenConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+    }
+
+    /** Check that a non-open security cannot be added to an open configuration. */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddNonOpenTypeToOpenConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+    }
+
+    /** Check that a OSEN security cannot be added as additional type. */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddOsenTypeToConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OSEN);
+    }
+
+    /** Verify that adding duplicate security types raises the exception. */
+    @Test (expected = IllegalArgumentException.class)
+    public void testAddDuplicateSecurityTypes() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+    }
+
+    /** Verify that adding duplicate security params raises the exception. */
+    @Test (expected = IllegalArgumentException.class)
+    public void testAddDuplicateSecurityParams() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams());
+        config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams());
+    }
+
+    /** Verify that Suite-B type works as expected. */
+    @Test
+    public void testAddSuiteBSecurityType() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.addSecurityParams(SecurityParams.createWpa3EnterpriseParams());
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+        config.addSecurityParams(SecurityParams.createWpa3Enterprise192BitParams());
+
+        assertFalse(config.isSuiteBCipherEcdheRsaEnabled());
+        config.enableSuiteBCiphers(false, true);
+        assertTrue(config.isSuiteBCipherEcdheRsaEnabled());
+    }
+
+    /** Verify that FILS bit can be set correctly. */
+    @Test
+    public void testFilsKeyMgmt() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+
+        config.enableFils(false, true);
+        assertFalse(config.isFilsSha256Enabled());
+        assertTrue(config.isFilsSha384Enabled());
+    }
+
+    /** Verify that SAE mode can be configured correctly. */
+    @Test
+    public void testSaeTypeMethods() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+        config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+
+        SecurityParams saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+        assertNotNull(saeParams);
+        assertFalse(saeParams.isSaeH2eOnlyMode());
+        assertFalse(saeParams.isSaePkOnlyMode());
+
+        config.enableSaeH2eOnlyMode(true);
+        config.enableSaePkOnlyMode(true);
+
+        saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+        assertNotNull(saeParams);
+        assertTrue(saeParams.isSaeH2eOnlyMode());
+        assertTrue(saeParams.isSaePkOnlyMode());
+    }
+
+    /** Verify the legacy configuration conversion */
+    @Test
+    public void testLegacyConfigurationConversion() {
+        Pair[] keyMgmtSecurityTypePairs = new Pair[] {
+                new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT),
+                new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK),
+                new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+                new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE),
+                new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE),
+                new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN),
+                new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK),
+                new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP),
+                new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK),
+                new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN),
+        };
+
+        for (Pair pair: keyMgmtSecurityTypePairs) {
+            WifiConfiguration config = new WifiConfiguration();
+            config.allowedKeyManagement.set((int) pair.first);
+            config.convertLegacyFieldsToSecurityParamsIfNeeded();
+            assertNotNull(config.getSecurityParams((int) pair.second));
+        }
+
+        // If none of key management is set, it should be open.
+        WifiConfiguration emptyConfig = new WifiConfiguration();
+        emptyConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+        assertNotNull(emptyConfig.getSecurityParams(SECURITY_TYPE_OPEN));
+
+        // If EAP key management is set and requirePmf is true, it is WPA3 Enterprise.
+        WifiConfiguration wpa3EnterpriseConfig = new WifiConfiguration();
+        wpa3EnterpriseConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        wpa3EnterpriseConfig.requirePmf = true;
+        wpa3EnterpriseConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+        assertNotNull(wpa3EnterpriseConfig.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
+
+        // If key management is NONE and wep key is set, it is WEP type.
+        WifiConfiguration wepConfig = new WifiConfiguration();
+        wepConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+        wepConfig.wepKeys = new String[] {"\"abcdef\""};
+        wepConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+        assertNotNull(wepConfig.getSecurityParams(SECURITY_TYPE_WEP));
+    }
+
+    /** Verify the set security params by SecurityParams objects. */
+    @Test
+    public void testSetBySecurityParamsObject() {
+        Pair[] securityParamsSecurityTypePairs = new Pair[] {
+                new Pair<>(SecurityParams.createWapiCertParams(), SECURITY_TYPE_WAPI_CERT),
+                new Pair<>(SecurityParams.createWapiPskParams(), SECURITY_TYPE_WAPI_PSK),
+                new Pair<>(SecurityParams.createWpa3Enterprise192BitParams(),
+                        SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+                new Pair<>(SecurityParams.createEnhancedOpenParams(), SECURITY_TYPE_OWE),
+                new Pair<>(SecurityParams.createWpa3PersonalParams(), SECURITY_TYPE_SAE),
+                new Pair<>(SecurityParams.createOsenParams(), SECURITY_TYPE_OSEN),
+                new Pair<>(SecurityParams.createWpaWpa2EnterpriseParams(), SECURITY_TYPE_EAP),
+                new Pair<>(SecurityParams.createWpaWpa2PersonalParams(), SECURITY_TYPE_PSK),
+                new Pair<>(SecurityParams.createOpenParams(), SECURITY_TYPE_OPEN),
+        };
+        for (Pair pair: securityParamsSecurityTypePairs) {
+            WifiConfiguration config = new WifiConfiguration();
+            config.setSecurityParams((SecurityParams) pair.first);
+            assertNotNull(config.getSecurityParams((int) pair.second));
+        }
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 52e9139..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;
@@ -137,6 +138,7 @@
     private static final int TEST_AP_FREQUENCY = 2412;
     private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
     private static final int TEST_SUB_ID = 3;
+    private static final String TEST_AP_INSTANCE = "wlan1";
 
     @Mock Context mContext;
     @Mock android.net.wifi.IWifiManager mWifiService;
@@ -147,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;
@@ -1111,6 +1114,27 @@
         verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
     }
 
+    /*
+     * Verify client-provided callback is being called through callback proxy
+     */
+    @Test
+    public void softApCallbackProxyCallsOnSoftApInfoListChanged() throws Exception {
+        SoftApInfo testSoftApInfo = new SoftApInfo();
+        testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+        testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+        List<SoftApInfo> infoList = new ArrayList<>();
+        infoList.add(testSoftApInfo);
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        callbackCaptor.getValue().onInfoListChanged(infoList);
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onInfoListChanged(infoList);
+    }
+
 
     /*
      * Verify client-provided callback is being called through callback proxy
@@ -1135,7 +1159,8 @@
      */
     @Test
     public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
-        WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"));
+        WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
+                TEST_AP_INSTANCE);
         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
@@ -1157,6 +1182,8 @@
         SoftApInfo testSoftApInfo = new SoftApInfo();
         testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
         testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+        List<SoftApInfo> infoList = new ArrayList<>();
+        infoList.add(testSoftApInfo);
         SoftApCapability testSoftApCapability = new SoftApCapability(0);
         testSoftApCapability.setMaxSupportedClients(10);
         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
@@ -1169,6 +1196,7 @@
         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
         callbackCaptor.getValue().onConnectedClientsChanged(testClients);
         callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+        callbackCaptor.getValue().onInfoListChanged(infoList);
         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
 
@@ -1177,6 +1205,7 @@
         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
         verify(mSoftApCallback).onConnectedClientsChanged(testClients);
         verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
+        verify(mSoftApCallback).onInfoListChanged(infoList);
         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
     }
@@ -2327,7 +2356,7 @@
      */
     @Test(expected = IllegalArgumentException.class)
     public void testAddSuggestionConnectionStatusListenerWithNullExecutor() {
-        mWifiManager.addSuggestionConnectionStatusListener(null, mListener);
+        mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener);
     }
 
     /**
@@ -2347,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));
     }
 
     /**
@@ -2362,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);
@@ -2382,7 +2413,7 @@
      */
     @Test
     public void testRemoveSuggestionConnectionListener() throws Exception {
-        mWifiManager.removeSuggestionConnectionStatusListener(mListener);
+        mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener);
         verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString());
     }
 
@@ -2609,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));
+    }
+
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
deleted file mode 100644
index fdd11a3..0000000
--- a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.NetworkKey;
-import android.net.RssiCurve;
-import android.net.ScoredNetwork;
-import android.net.WifiKey;
-import android.net.wifi.WifiNetworkScoreCache.CacheListener;
-import android.os.Handler;
-import android.os.HandlerThread;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/** Unit tests for {@link WifiNetworkScoreCache}. */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class WifiNetworkScoreCacheTest {
-
-    public static final String SSID = "ssid";
-    public static final String SSID2 = "ssid2";
-    public static final String SSID3 = "ssid3";
-    public static final String FORMATTED_SSID = "\"" + SSID + "\"";
-    public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\"";
-    public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\"";
-    public static final String BSSID = "AA:AA:AA:AA:AA:AA";
-
-    public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID);
-
-    public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID);
-
-    @Mock private Context mockApplicationContext;
-    @Mock private Context mockContext; // isn't used, can be null
-    @Mock private RssiCurve mockRssiCurve;
-
-
-    private CacheListener mCacheListener;
-    private CountDownLatch mLatch;
-    private Handler mHandler;
-    private List<ScoredNetwork> mUpdatedNetworksCaptor;
-    private ScoredNetwork mValidScoredNetwork;
-    private WifiNetworkScoreCache mScoreCache;
-
-    private static ScanResult buildScanResult(String ssid, String bssid) {
-        return new ScanResult(
-                WifiSsid.createFromAsciiEncoded(ssid),
-                bssid,
-                "" /* caps */,
-                0 /* level */,
-                0 /* frequency */,
-                0 /* tsf */,
-                0 /* distCm */,
-                0 /* distSdCm*/);
-    }
-
-    private static ScoredNetwork buildScoredNetwork(WifiKey key, RssiCurve curve) {
-        return new ScoredNetwork(new NetworkKey(key), curve);
-    }
-
-    // Called from setup
-    private void initializeCacheWithValidScoredNetwork() {
-        mScoreCache.updateScores(ImmutableList.of(mValidScoredNetwork));
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mockContext.getApplicationContext()).thenReturn(mockApplicationContext);
-
-        mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mockRssiCurve);
-        mScoreCache = new WifiNetworkScoreCache(mockContext);
-        initializeCacheWithValidScoredNetwork();
-
-        HandlerThread thread = new HandlerThread("WifiNetworkScoreCacheTest Handler Thread");
-        thread.start();
-        mHandler = new Handler(thread.getLooper());
-        mLatch = new CountDownLatch(1);
-        mCacheListener = new CacheListener(mHandler) {
-            @Override
-            public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
-                mUpdatedNetworksCaptor = updatedNetworks;
-                mLatch.countDown();
-            }
-        };
-    }
-
-
-    @Test
-    public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() {
-        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue();
-    }
-
-    @Test
-    public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() {
-        mScoreCache.clearScores();
-        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse();
-    }
-
-    @Test
-    public void updateScoresShouldAddNewNetwork() {
-        WifiKey key2 = new WifiKey("\"ssid2\"", BSSID);
-        ScoredNetwork network2 = buildScoredNetwork(key2, mockRssiCurve);
-        ScanResult result2 = buildScanResult("ssid2", BSSID);
-
-        mScoreCache.updateScores(ImmutableList.of(network2));
-
-        assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue();
-        assertThat(mScoreCache.isScoredNetwork(result2)).isTrue();
-    }
-
-    @Test
-    public void hasScoreCurveShouldReturnTrue() {
-        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue();
-    }
-
-    @Test
-    public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() {
-        ScanResult unscored = buildScanResult("fake", BSSID);
-        assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse();
-    }
-
-    @Test
-    public void hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve() {
-        ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */);
-        mScoreCache.updateScores(ImmutableList.of(noCurve));
-
-        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse();
-    }
-
-    @Test
-    public void getNetworkScoreShouldReturnScore() {
-        final byte score = 50;
-        final int rssi = -70;
-        ScanResult result = new ScanResult(VALID_SCAN_RESULT);
-        result.level = rssi;
-
-        when(mockRssiCurve.lookupScore(rssi)).thenReturn(score);
-
-        assertThat(mScoreCache.getNetworkScore(result)).isEqualTo(score);
-    }
-
-    @Test
-    public void getMeteredHintShouldReturnFalse() {
-        assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse();
-    }
-
-    @Test
-    public void getMeteredHintShouldReturnTrue() {
-        ScoredNetwork network =
-                new ScoredNetwork(
-                    new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */);
-        mScoreCache.updateScores(ImmutableList.of(network));
-
-        assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue();
-    }
-
-    @Test
-    public void updateScoresShouldInvokeCacheListener_networkCacheUpdated() {
-        mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener);
-        initializeCacheWithValidScoredNetwork();
-
-        try {
-            mLatch.await(1, TimeUnit.SECONDS); // wait for listener to be executed
-        } catch (InterruptedException e) {
-            fail("Interrupted Exception while waiting for listener to be invoked.");
-        }
-        // One network should be updated.
-        assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1);
-        assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork);
-    }
-
-    @Test
-    public void leastRecentlyUsedScore_shouldBeEvictedFromCache() {
-        mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener, 2 /* maxCacheSize */);
-
-        ScoredNetwork network1 = mValidScoredNetwork;
-        ScoredNetwork network2 = buildScoredNetwork(
-                new WifiKey(FORMATTED_SSID2, BSSID), mockRssiCurve);
-        ScoredNetwork network3 = buildScoredNetwork(
-                new WifiKey(FORMATTED_SSID3, BSSID), mockRssiCurve);
-        mScoreCache.updateScores(ImmutableList.of(network1));
-        mScoreCache.updateScores(ImmutableList.of(network2));
-
-        // First score should be evicted because max cache size has been reached.
-        mScoreCache.updateScores(ImmutableList.of(network3));
-
-        assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue();
-        assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue();
-        assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse();
-    }
-}
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index e6eae416..c8006fe 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi.rtt;
 
+import static junit.framework.Assert.fail;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -143,6 +145,7 @@
         PeerHandle peerHandle1 = new PeerHandle(12);
 
         RangingRequest.Builder builder = new RangingRequest.Builder();
+        builder.setRttBurstSize(4);
         builder.addAccessPoint(scanResult1);
         builder.addAccessPoints(scanResults2and3);
         builder.addWifiAwarePeer(mac1);
@@ -163,6 +166,60 @@
     }
 
     /**
+     * Validate the rtt burst size is set correctly when in range.
+     */
+    @Test
+    public void testRangingRequestSetBurstSize() {
+        ScanResult scanResult = new ScanResult();
+        scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+        // create request
+        RangingRequest.Builder builder = new RangingRequest.Builder();
+        builder.setRttBurstSize(4);
+        builder.addAccessPoint(scanResult);
+        RangingRequest request = builder.build();
+
+        // confirm rtt burst size is set correctly to default value
+        assertEquals(request.getRttBurstSize(), 4);
+    }
+
+    /**
+     * Validate the rtt burst size cannot be smaller than the minimum.
+     */
+    @Test
+    public void testRangingRequestMinBurstSizeIsEnforced() {
+        ScanResult scanResult = new ScanResult();
+        scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+        // create request
+        try {
+            RangingRequest.Builder builder = new RangingRequest.Builder();
+            builder.setRttBurstSize(RangingRequest.getMinRttBurstSize() - 1);
+            fail("RTT burst size was smaller than min value.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Validate the rtt burst size cannot exceed the maximum.
+     */
+    @Test
+    public void testRangingRequestMaxBurstSizeIsEnforced() {
+        ScanResult scanResult = new ScanResult();
+        scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+        // create request
+        try {
+            RangingRequest.Builder builder = new RangingRequest.Builder();
+            builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize() + 1);
+            fail("RTT Burst size exceeded max value.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
      * Validate that can request as many range operation as the upper limit on number of requests.
      */
     @Test
@@ -175,7 +232,7 @@
         }
         MacAddress mac1 = MacAddress.fromString("00:01:02:03:04:05");
 
-        // create request
+        // create request using max RTT Peers
         RangingRequest.Builder builder = new RangingRequest.Builder();
         builder.addAccessPoint(scanResult);
         builder.addAccessPoints(scanResultList);
@@ -185,6 +242,18 @@
 
         // verify request
         request.enforceValidity(true);
+        // confirm rtt burst size is set correctly to default value
+        assertEquals(request.getRttBurstSize(), RangingRequest.getDefaultRttBurstSize());
+        // confirm the number of peers in the request is the max number of peers
+        List<ResponderConfig> rttPeers = request.getRttPeers();
+        int numRttPeers = rttPeers.size();
+        assertEquals(RangingRequest.getMaxPeers(), numRttPeers);
+        // confirm each peer has the correct mac address
+        for (int i = 0; i < numRttPeers - 1; ++i) {
+            assertEquals("AA:BB:CC:DD:EE:FF", rttPeers.get(i).macAddress.toString().toUpperCase());
+        }
+        assertEquals("00:01:02:03:04:05",
+                rttPeers.get(numRttPeers - 1).macAddress.toString().toUpperCase());
     }
 
     /**